@khanacademy/wonder-blocks-core
Advanced tools
Comparing version 0.0.0-PR2345-20241216153024 to 0.0.0-PR2345-20250108233653
# @khanacademy/wonder-blocks-core | ||
## 0.0.0-PR2345-20241216153024 | ||
## 0.0.0-PR2345-20250108233653 | ||
### Minor Changes | ||
- 7516b239: Update useOnMountEffect to pass isMountedRef to callback | ||
## 11.0.1 | ||
### Patch Changes | ||
- 11a0f5c6: No functional changes. Adding prepublishOnly script. | ||
## 11.0.0 | ||
### Major Changes | ||
- d23c9c5f: Delete the custom identifier generation API | ||
## 10.0.0 | ||
### Major Changes | ||
- b6009b77: Deprecate the ID provider and unique ID utilities | ||
@@ -8,0 +26,0 @@ |
import _extends from '@babel/runtime/helpers/extends'; | ||
import _objectWithoutPropertiesLoose from '@babel/runtime/helpers/objectWithoutPropertiesLoose'; | ||
import * as React from 'react'; | ||
import { useId, useContext as useContext$1, useRef, useEffect as useEffect$1 } from 'react'; | ||
import { useId, useEffect as useEffect$1, useContext as useContext$1 } from 'react'; | ||
import { StyleSheet, css } from 'aphrodite'; | ||
@@ -251,91 +251,2 @@ | ||
class UniqueIDFactory { | ||
constructor(scope) { | ||
this._uniqueFactoryName = void 0; | ||
this.get = key => { | ||
const normalizedKey = key.toLowerCase(); | ||
if (!this._hasValidIdChars(key)) { | ||
throw new Error(`Invalid identifier key: ${key}`); | ||
} | ||
return `${this._uniqueFactoryName}-${normalizedKey}`; | ||
}; | ||
scope = typeof scope === "string" ? scope : ""; | ||
const normalizedScope = scope.toLowerCase(); | ||
if (!this._hasValidIdChars(normalizedScope)) { | ||
throw new Error(`Invalid factory scope: ${scope}`); | ||
} | ||
this._uniqueFactoryName = `uid-${normalizedScope}-${UniqueIDFactory._factoryUniquenessCounter++}`; | ||
} | ||
_hasValidIdChars(value) { | ||
return typeof value === "string" ? !/\s/.test(value) : false; | ||
} | ||
} | ||
UniqueIDFactory._factoryUniquenessCounter = 0; | ||
class SsrIDFactory { | ||
get(id) { | ||
return id; | ||
} | ||
} | ||
SsrIDFactory.Default = new SsrIDFactory(); | ||
var SsrIDFactory$1 = SsrIDFactory.Default; | ||
class UniqueIDProvider extends React.Component { | ||
constructor(...args) { | ||
super(...args); | ||
this._idFactory = void 0; | ||
} | ||
_performRender(firstRender) { | ||
const { | ||
children, | ||
mockOnFirstRender, | ||
scope | ||
} = this.props; | ||
if (firstRender) { | ||
if (mockOnFirstRender) { | ||
return children(SsrIDFactory$1); | ||
} | ||
return null; | ||
} | ||
if (!this._idFactory) { | ||
this._idFactory = new UniqueIDFactory(scope); | ||
} | ||
return children(this._idFactory); | ||
} | ||
render() { | ||
return React.createElement(InitialFallback, { | ||
fallback: () => this._performRender(true) | ||
}, () => this._performRender(false)); | ||
} | ||
} | ||
class IDProvider extends React.Component { | ||
renderChildren(ids) { | ||
const { | ||
id, | ||
children | ||
} = this.props; | ||
const uniqueId = ids ? ids.get(IDProvider.defaultId) : id; | ||
if (!uniqueId) { | ||
throw new Error("Did not get an identifier factory nor a id prop"); | ||
} | ||
return children(uniqueId); | ||
} | ||
render() { | ||
const { | ||
id, | ||
scope | ||
} = this.props; | ||
if (id) { | ||
return this.renderChildren(); | ||
} else { | ||
return React.createElement(UniqueIDProvider, { | ||
scope: scope, | ||
mockOnFirstRender: true | ||
}, ids => this.renderChildren(ids)); | ||
} | ||
} | ||
} | ||
IDProvider.defaultId = "wb-id"; | ||
let serverSide = false; | ||
@@ -357,34 +268,2 @@ var Server = { | ||
const useRenderState = () => { | ||
const rawRenderState = useContext$1(RenderStateContext); | ||
if (rawRenderState === RenderStateInternal.Standard) { | ||
return RenderState.Standard; | ||
} else { | ||
return RenderState.Initial; | ||
} | ||
}; | ||
const useUniqueIdWithMock = scope => { | ||
const renderState = useRenderState(); | ||
const idFactory = useRef(null); | ||
if (renderState === RenderState.Initial) { | ||
return SsrIDFactory$1; | ||
} | ||
if (!idFactory.current) { | ||
idFactory.current = new UniqueIDFactory(scope); | ||
} | ||
return idFactory.current; | ||
}; | ||
const useUniqueIdWithoutMock = scope => { | ||
const renderState = useRenderState(); | ||
const idFactory = useRef(null); | ||
if (renderState === RenderState.Initial) { | ||
return null; | ||
} | ||
if (!idFactory.current) { | ||
idFactory.current = new UniqueIDFactory(scope); | ||
} | ||
return idFactory.current; | ||
}; | ||
const useForceUpdate = () => { | ||
@@ -417,3 +296,10 @@ const [, setUpdateState] = React.useState({}); | ||
const useOnMountEffect = callback => { | ||
React.useEffect(callback, []); | ||
const isMountedRef = React.useRef(true); | ||
React.useEffect(() => { | ||
const cleanup = callback(isMountedRef); | ||
return () => { | ||
cleanup == null ? void 0 : cleanup(); | ||
isMountedRef.current = false; | ||
}; | ||
}, []); | ||
}; | ||
@@ -440,2 +326,11 @@ | ||
const useRenderState = () => { | ||
const rawRenderState = useContext$1(RenderStateContext); | ||
if (rawRenderState === RenderStateInternal.Standard) { | ||
return RenderState.Standard; | ||
} else { | ||
return RenderState.Initial; | ||
} | ||
}; | ||
const { | ||
@@ -467,2 +362,2 @@ useEffect, | ||
export { IDProvider, Id, InitialFallback, RenderState, RenderStateRoot, Server, Text, UniqueIDProvider, View, addStyle, useForceUpdate, useIsMounted, useLatestRef, useOnMountEffect, useOnline, usePreHydrationEffect, useRenderState, useUniqueIdWithMock, useUniqueIdWithoutMock }; | ||
export { Id, InitialFallback, RenderState, RenderStateRoot, Server, Text, View, addStyle, useForceUpdate, useIsMounted, useLatestRef, useOnMountEffect, useOnline, usePreHydrationEffect, useRenderState }; |
@@ -0,1 +1,2 @@ | ||
import * as React from "react"; | ||
/** | ||
@@ -6,3 +7,3 @@ * Runs a callback once on mount. | ||
* | ||
* @param {() => (void | (() => void))} callback function that forces the component to update. | ||
* @param {(isMountedRef: React.MutableRefObject<boolean>) => void | (() => void)} callback function that forces the component to update. | ||
* | ||
@@ -29,3 +30,24 @@ * The following code snippets are equivalent | ||
* If you only need to do something on mount, don't return a cleanup function from `callback`. | ||
* | ||
* If your callback is async, use the `isMountedRef` ref that's passed to the callback to ensure | ||
* that the component using `useOnMountEffect` hasn't been unmounted, e.g. | ||
* | ||
* ``` | ||
* const MyComponent = () => { | ||
* const [foo, setFoo] = React.useState(""); | ||
* useOnMountEffect((isMountedRef) => { | ||
* const action = async () => { | ||
* const res = await fetch("/foo"); | ||
* const text = res.text(); | ||
* if (isMountedRef.current) { | ||
* setFoo(text); | ||
* } | ||
* } | ||
* | ||
* action(); | ||
* }); | ||
* | ||
* return foo !== "" ? <h1>Loading...</h1> : <h1>{foo}</h1>; | ||
* } | ||
*/ | ||
export declare const useOnMountEffect: (callback: () => void | (() => void)) => void; | ||
export declare const useOnMountEffect: (callback: (isMountedRef: React.MutableRefObject<boolean>) => void | (() => void)) => void; |
@@ -1,11 +0,7 @@ | ||
import type { AriaProps, IIdentifierFactory, StyleType, PropsFor } from "./util/types"; | ||
export { default as Text } from "./components/text"; | ||
export { default as View } from "./components/view"; | ||
export { default as InitialFallback } from "./components/initial-fallback"; | ||
export { default as IDProvider } from "./components/id-provider"; | ||
export { default as UniqueIDProvider } from "./components/unique-id-provider"; | ||
export { default as addStyle } from "./util/add-style"; | ||
export { default as Server } from "./util/server"; | ||
export { Id } from "./components/id"; | ||
export { useUniqueIdWithMock, useUniqueIdWithoutMock, } from "./hooks/use-unique-id"; | ||
export { useForceUpdate } from "./hooks/use-force-update"; | ||
@@ -21,2 +17,2 @@ export { useIsMounted } from "./hooks/use-is-mounted"; | ||
export type { AriaRole, AriaAttributes } from "./util/aria-types"; | ||
export type { AriaProps, IIdentifierFactory, StyleType, PropsFor }; | ||
export type { AriaProps, StyleType, PropsFor } from "./util/types"; |
@@ -278,91 +278,2 @@ 'use strict'; | ||
class UniqueIDFactory { | ||
constructor(scope) { | ||
this._uniqueFactoryName = void 0; | ||
this.get = key => { | ||
const normalizedKey = key.toLowerCase(); | ||
if (!this._hasValidIdChars(key)) { | ||
throw new Error(`Invalid identifier key: ${key}`); | ||
} | ||
return `${this._uniqueFactoryName}-${normalizedKey}`; | ||
}; | ||
scope = typeof scope === "string" ? scope : ""; | ||
const normalizedScope = scope.toLowerCase(); | ||
if (!this._hasValidIdChars(normalizedScope)) { | ||
throw new Error(`Invalid factory scope: ${scope}`); | ||
} | ||
this._uniqueFactoryName = `uid-${normalizedScope}-${UniqueIDFactory._factoryUniquenessCounter++}`; | ||
} | ||
_hasValidIdChars(value) { | ||
return typeof value === "string" ? !/\s/.test(value) : false; | ||
} | ||
} | ||
UniqueIDFactory._factoryUniquenessCounter = 0; | ||
class SsrIDFactory { | ||
get(id) { | ||
return id; | ||
} | ||
} | ||
SsrIDFactory.Default = new SsrIDFactory(); | ||
var SsrIDFactory$1 = SsrIDFactory.Default; | ||
class UniqueIDProvider extends React__namespace.Component { | ||
constructor(...args) { | ||
super(...args); | ||
this._idFactory = void 0; | ||
} | ||
_performRender(firstRender) { | ||
const { | ||
children, | ||
mockOnFirstRender, | ||
scope | ||
} = this.props; | ||
if (firstRender) { | ||
if (mockOnFirstRender) { | ||
return children(SsrIDFactory$1); | ||
} | ||
return null; | ||
} | ||
if (!this._idFactory) { | ||
this._idFactory = new UniqueIDFactory(scope); | ||
} | ||
return children(this._idFactory); | ||
} | ||
render() { | ||
return React__namespace.createElement(InitialFallback, { | ||
fallback: () => this._performRender(true) | ||
}, () => this._performRender(false)); | ||
} | ||
} | ||
class IDProvider extends React__namespace.Component { | ||
renderChildren(ids) { | ||
const { | ||
id, | ||
children | ||
} = this.props; | ||
const uniqueId = ids ? ids.get(IDProvider.defaultId) : id; | ||
if (!uniqueId) { | ||
throw new Error("Did not get an identifier factory nor a id prop"); | ||
} | ||
return children(uniqueId); | ||
} | ||
render() { | ||
const { | ||
id, | ||
scope | ||
} = this.props; | ||
if (id) { | ||
return this.renderChildren(); | ||
} else { | ||
return React__namespace.createElement(UniqueIDProvider, { | ||
scope: scope, | ||
mockOnFirstRender: true | ||
}, ids => this.renderChildren(ids)); | ||
} | ||
} | ||
} | ||
IDProvider.defaultId = "wb-id"; | ||
let serverSide = false; | ||
@@ -384,34 +295,2 @@ var Server = { | ||
const useRenderState = () => { | ||
const rawRenderState = React.useContext(RenderStateContext); | ||
if (rawRenderState === RenderStateInternal.Standard) { | ||
return RenderState.Standard; | ||
} else { | ||
return RenderState.Initial; | ||
} | ||
}; | ||
const useUniqueIdWithMock = scope => { | ||
const renderState = useRenderState(); | ||
const idFactory = React.useRef(null); | ||
if (renderState === RenderState.Initial) { | ||
return SsrIDFactory$1; | ||
} | ||
if (!idFactory.current) { | ||
idFactory.current = new UniqueIDFactory(scope); | ||
} | ||
return idFactory.current; | ||
}; | ||
const useUniqueIdWithoutMock = scope => { | ||
const renderState = useRenderState(); | ||
const idFactory = React.useRef(null); | ||
if (renderState === RenderState.Initial) { | ||
return null; | ||
} | ||
if (!idFactory.current) { | ||
idFactory.current = new UniqueIDFactory(scope); | ||
} | ||
return idFactory.current; | ||
}; | ||
const useForceUpdate = () => { | ||
@@ -444,3 +323,10 @@ const [, setUpdateState] = React__namespace.useState({}); | ||
const useOnMountEffect = callback => { | ||
React__namespace.useEffect(callback, []); | ||
const isMountedRef = React__namespace.useRef(true); | ||
React__namespace.useEffect(() => { | ||
const cleanup = callback(isMountedRef); | ||
return () => { | ||
cleanup == null ? void 0 : cleanup(); | ||
isMountedRef.current = false; | ||
}; | ||
}, []); | ||
}; | ||
@@ -467,2 +353,11 @@ | ||
const useRenderState = () => { | ||
const rawRenderState = React.useContext(RenderStateContext); | ||
if (rawRenderState === RenderStateInternal.Standard) { | ||
return RenderState.Standard; | ||
} else { | ||
return RenderState.Initial; | ||
} | ||
}; | ||
const { | ||
@@ -494,3 +389,2 @@ useEffect, | ||
exports.IDProvider = IDProvider; | ||
exports.Id = Id; | ||
@@ -502,3 +396,2 @@ exports.InitialFallback = InitialFallback; | ||
exports.Text = Text; | ||
exports.UniqueIDProvider = UniqueIDProvider; | ||
exports.View = View; | ||
@@ -513,3 +406,1 @@ exports.addStyle = addStyle; | ||
exports.useRenderState = useRenderState; | ||
exports.useUniqueIdWithMock = useUniqueIdWithMock; | ||
exports.useUniqueIdWithoutMock = useUniqueIdWithoutMock; |
@@ -81,10 +81,2 @@ import * as React from "react"; | ||
} & AriaProps & EventHandlers; | ||
/** | ||
* Interface implemented by types that can provide identifiers. | ||
* @deprecated Use `useId` for your ID needs. If you are in a class-based | ||
* component and cannot use hooks, then use the `Id` component. | ||
*/ | ||
export interface IIdentifierFactory { | ||
get(id: string): string; | ||
} | ||
export * from "./types.propsfor"; |
{ | ||
"name": "@khanacademy/wonder-blocks-core", | ||
"version": "0.0.0-PR2345-20241216153024", | ||
"version": "0.0.0-PR2345-20250108233653", | ||
"design": "v1", | ||
@@ -13,3 +13,4 @@ "publishConfig": { | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
"test": "echo \"Error: no test specified\" && exit 1", | ||
"prepublishOnly": "../../utils/publish/package-pre-publish-check.sh" | ||
}, | ||
@@ -28,3 +29,3 @@ "dependencies": { | ||
"@khanacademy/wb-dev-build-settings": "^2.0.0", | ||
"@khanacademy/wonder-blocks-testing-core": "^2.0.0" | ||
"@khanacademy/wonder-blocks-testing-core": "^2.0.1" | ||
}, | ||
@@ -31,0 +32,0 @@ "author": "", |
66161
25
1615