@pushwoosh/kit-helpers 4.12.3 → 4.12.5
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/analytics/trackEvent.d.ts +4 -0
- package/analytics/trackEvent.js +4 -0
- package/analytics/utils.d.ts +2 -0
- package/callWithRetry.js +0 -2
- package/expand.d.ts +5 -0
- package/expand.js +5 -1
- package/flex.d.ts +2 -0
- package/flex.js +2 -0
- package/formatNumber.d.ts +5 -0
- package/formatNumber.js +4 -0
- package/grid.d.ts +5 -0
- package/grid.js +5 -0
- package/hooks/types.d.ts +2 -0
- package/hooks/useAsync.d.ts +4 -0
- package/hooks/useAsync.js +4 -0
- package/hooks/useAsyncFn.d.ts +7 -0
- package/hooks/useAsyncFn.js +4 -1
- package/hooks/useAsyncFunction.d.ts +6 -0
- package/hooks/useAsyncFunction.js +4 -1
- package/hooks/useClickAway.js +0 -1
- package/hooks/useDelayedEffect.d.ts +4 -0
- package/hooks/useDelayedEffect.js +4 -0
- package/hooks/useDelayedValue.d.ts +1 -0
- package/hooks/useDelayedValue.js +1 -0
- package/hooks/useEffectOnce.d.ts +1 -0
- package/hooks/useEffectOnce.js +1 -0
- package/hooks/useMount.d.ts +1 -0
- package/hooks/useMount.js +1 -0
- package/hooks/useMountedState.d.ts +1 -0
- package/hooks/useMountedState.js +1 -0
- package/hooks/useUnmount.d.ts +1 -0
- package/hooks/useUnmount.js +1 -0
- package/package.json +17 -20
- package/styled-helpers.d.ts +26 -0
- package/styled-helpers.js +16 -0
- package/ai-documentation.md +0 -838
|
@@ -1,2 +1,6 @@
|
|
|
1
1
|
import { type PWTrackingEvent } from './utils';
|
|
2
|
+
/**
|
|
3
|
+
* Queue a product-analytics event on `window.__trackingEventsStore`.
|
|
4
|
+
* Before shared-scripts boots the store is a plain array, so the queue survives an early call.
|
|
5
|
+
*/
|
|
2
6
|
export declare const trackEvent: (event: PWTrackingEvent) => void;
|
package/analytics/trackEvent.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
/* eslint no-underscore-dangle: 0 */
|
|
2
|
+
/**
|
|
3
|
+
* Queue a product-analytics event on `window.__trackingEventsStore`.
|
|
4
|
+
* Before shared-scripts boots the store is a plain array, so the queue survives an early call.
|
|
5
|
+
*/
|
|
2
6
|
export const trackEvent = event => {
|
|
3
7
|
window.__trackingEventsStore = window.__trackingEventsStore ?? [];
|
|
4
8
|
window.__trackingEventsStore.push(event);
|
package/analytics/utils.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
/** A product-analytics event: a name plus arbitrary properties. */
|
|
1
2
|
export interface PWTrackingEvent {
|
|
2
3
|
name: string;
|
|
3
4
|
properties?: Record<string, unknown>;
|
|
4
5
|
}
|
|
6
|
+
/** Sink installed by shared-scripts that replaces the bootstrap array. */
|
|
5
7
|
export interface PWTrackingEventsStoreAPI {
|
|
6
8
|
push(event: PWTrackingEvent): void;
|
|
7
9
|
}
|
package/callWithRetry.js
CHANGED
|
@@ -27,7 +27,6 @@ export const callWithRetry = async (operation, policy) => {
|
|
|
27
27
|
};
|
|
28
28
|
for (let attempt = 1; attempt <= policy.attempts; attempt += 1) {
|
|
29
29
|
try {
|
|
30
|
-
// eslint-disable-next-line no-await-in-loop
|
|
31
30
|
const result = await operation(attempt);
|
|
32
31
|
if (!policy.until || policy.until(result)) {
|
|
33
32
|
return result;
|
|
@@ -45,7 +44,6 @@ export const callWithRetry = async (operation, policy) => {
|
|
|
45
44
|
};
|
|
46
45
|
}
|
|
47
46
|
if (attempt < policy.attempts) {
|
|
48
|
-
// eslint-disable-next-line no-await-in-loop
|
|
49
47
|
await sleep(policy.delay);
|
|
50
48
|
}
|
|
51
49
|
}
|
package/expand.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ type ExpandTransitionProps = {
|
|
|
6
6
|
internalClassName?: string;
|
|
7
7
|
children?: ReactNode;
|
|
8
8
|
};
|
|
9
|
+
/** Transition that scales content out of / into its centre; wrap it in a `TransitionGroup`. */
|
|
9
10
|
export declare const ExpandTransition: import("styled-components").StyledComponent<FC<ExpandTransitionProps>, any, {}, never>;
|
|
10
11
|
type CollapseProps = {
|
|
11
12
|
expanded: boolean;
|
|
@@ -14,5 +15,9 @@ type CollapseProps = {
|
|
|
14
15
|
internalClassName?: string;
|
|
15
16
|
children: (() => ReactNode) | ReactNode;
|
|
16
17
|
};
|
|
18
|
+
/**
|
|
19
|
+
* Height transition driven by the `expanded` prop; measures its own content, so no fixed height is needed.
|
|
20
|
+
* `children` may be a function to keep the subtree unmounted while collapsed.
|
|
21
|
+
*/
|
|
17
22
|
export declare const Collapse: FC<CollapseProps>;
|
|
18
23
|
export {};
|
package/expand.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { createElement as _createElement } from "react";
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
/* eslint-disable react/require-default-props, react/jsx-no-bind */
|
|
4
3
|
import { useEffect, useRef, useState } from 'react';
|
|
5
4
|
import { CSSTransition, TransitionGroup } from 'react-transition-group';
|
|
6
5
|
import styled, { css } from 'styled-components';
|
|
@@ -49,10 +48,15 @@ const CollapseTransition = styled(ExpandTransitionComp).withConfig({
|
|
|
49
48
|
})(["transition:height var(--timeout) linear,opacity var(--timeout) linear;&-enter{overflow:hidden;opacity:0;height:0;}&-enter-active,&-exit{overflow:hidden;opacity:1;height:var(--height);}&-exit-active{overflow:hidden;opacity:0;height:0;}"]);
|
|
50
49
|
const enterExpandCss = css(["overflow:hidden;position:relative;width:1px;height:1px;& > *{position:absolute;top:calc(var(--height) / -2);left:calc(var(--width) / -2);}"]);
|
|
51
50
|
const exitExpandCss = css(["overflow:hidden;position:relative;width:var(--width);height:var(--height);& > *{position:absolute;top:0;left:0;}"]);
|
|
51
|
+
/** Transition that scales content out of / into its centre; wrap it in a `TransitionGroup`. */
|
|
52
52
|
export const ExpandTransition = styled(ExpandTransitionComp).withConfig({
|
|
53
53
|
displayName: "ExpandTransition",
|
|
54
54
|
componentId: "sc-k4fws9-1"
|
|
55
55
|
})(["transition:all var(--timeout) ease-out;& > *{transition:all var(--timeout) ease-out;}&-enter{", "}&-enter-active,&-exit{", "}&-exit-active{", "}"], enterExpandCss, exitExpandCss, enterExpandCss);
|
|
56
|
+
/**
|
|
57
|
+
* Height transition driven by the `expanded` prop; measures its own content, so no fixed height is needed.
|
|
58
|
+
* `children` may be a function to keep the subtree unmounted while collapsed.
|
|
59
|
+
*/
|
|
56
60
|
export const Collapse = ({
|
|
57
61
|
expanded,
|
|
58
62
|
children,
|
package/flex.d.ts
CHANGED
|
@@ -3,7 +3,9 @@ type FlexContainerProps = CommonContainerProps & {
|
|
|
3
3
|
$flexDirection?: 'row' | 'row-reverse' | 'column' | 'column-reverse';
|
|
4
4
|
$flexWrap?: 'nowrap' | 'wrap' | 'wrap-reverse';
|
|
5
5
|
};
|
|
6
|
+
/** `display: flex` box driven by `$`-prefixed props (`$gap`, `$alignItems`, `$flexDirection`, box props). */
|
|
6
7
|
export declare const FlexContainer: import("styled-components").StyledComponent<"div", any, FlexContainerProps, never>;
|
|
8
|
+
/** {@link FlexContainer} that wraps — for tag/chip rows of unknown length. */
|
|
7
9
|
export declare const Cluster: import("styled-components").StyledComponent<"div", any, import("./styled-helpers").CommonBoxProps & {
|
|
8
10
|
$alignContent?: import("./styled-helpers").AlignContentValue;
|
|
9
11
|
$alignItems?: import("./styled-helpers").ItemAlignmentValue;
|
package/flex.js
CHANGED
|
@@ -10,10 +10,12 @@ const flexDeclarations = {
|
|
|
10
10
|
}
|
|
11
11
|
};
|
|
12
12
|
const renderFlexCss = renderDeclarations(flexDeclarations);
|
|
13
|
+
/** `display: flex` box driven by `$`-prefixed props (`$gap`, `$alignItems`, `$flexDirection`, box props). */
|
|
13
14
|
export const FlexContainer = styled.div.withConfig({
|
|
14
15
|
displayName: "FlexContainer",
|
|
15
16
|
componentId: "sc-vvrarn-0"
|
|
16
17
|
})(["display:flex;", ""], renderFlexCss);
|
|
18
|
+
/** {@link FlexContainer} that wraps — for tag/chip rows of unknown length. */
|
|
17
19
|
export const Cluster = styled(FlexContainer).attrs({
|
|
18
20
|
$flexWrap: 'wrap'
|
|
19
21
|
}).withConfig({
|
package/formatNumber.d.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/** `spaced` groups thousands with a space; `short` compacts to `12K` from 10000 up. */
|
|
1
2
|
type NumberFormat = 'spaced' | 'short';
|
|
3
|
+
/**
|
|
4
|
+
* Render a number for display.
|
|
5
|
+
* @param format `spaced` for full digits, `short` for compact notation
|
|
6
|
+
*/
|
|
2
7
|
export declare const formatNumber: (number: number, format: NumberFormat) => string;
|
|
3
8
|
export {};
|
package/formatNumber.js
CHANGED
|
@@ -9,6 +9,10 @@ const getNumberAsShortString = num => {
|
|
|
9
9
|
});
|
|
10
10
|
return formatter.format(num);
|
|
11
11
|
};
|
|
12
|
+
/**
|
|
13
|
+
* Render a number for display.
|
|
14
|
+
* @param format `spaced` for full digits, `short` for compact notation
|
|
15
|
+
*/
|
|
12
16
|
export const formatNumber = (number, format) => {
|
|
13
17
|
switch (format) {
|
|
14
18
|
case 'spaced':
|
package/grid.d.ts
CHANGED
|
@@ -5,7 +5,9 @@ type GridContainerProps = CommonContainerProps & {
|
|
|
5
5
|
$justifyItems?: ItemAlignmentValue;
|
|
6
6
|
$placeItems?: ItemAlignmentValue;
|
|
7
7
|
};
|
|
8
|
+
/** `display: grid` box driven by `$`-prefixed props (`$gap`, `$gridAutoFlow`, `$placeItems`, box props). */
|
|
8
9
|
export declare const GridContainer: import("styled-components").StyledComponent<"div", any, GridContainerProps, never>;
|
|
10
|
+
/** Grid with explicit columns: a number means that many equal columns, a string is used as `grid-template-columns`. */
|
|
9
11
|
export declare const Columns: import("styled-components").StyledComponent<"div", any, import("./styled-helpers").CommonBoxProps & {
|
|
10
12
|
$alignContent?: import("./styled-helpers").AlignContentValue;
|
|
11
13
|
$alignItems?: ItemAlignmentValue;
|
|
@@ -18,6 +20,7 @@ export declare const Columns: import("styled-components").StyledComponent<"div",
|
|
|
18
20
|
} & {
|
|
19
21
|
$sizes: StrNum;
|
|
20
22
|
}, never>;
|
|
23
|
+
/** Grid with explicit rows: a number means that many equal rows, a string is used as `grid-template-rows`. */
|
|
21
24
|
export declare const Rows: import("styled-components").StyledComponent<"div", any, import("./styled-helpers").CommonBoxProps & {
|
|
22
25
|
$alignContent?: import("./styled-helpers").AlignContentValue;
|
|
23
26
|
$alignItems?: ItemAlignmentValue;
|
|
@@ -30,6 +33,7 @@ export declare const Rows: import("styled-components").StyledComponent<"div", an
|
|
|
30
33
|
} & {
|
|
31
34
|
$sizes: StrNum;
|
|
32
35
|
}, never>;
|
|
36
|
+
/** Grid that lays children out in one row. */
|
|
33
37
|
export declare const Horizontal: import("styled-components").StyledComponent<"div", any, import("./styled-helpers").CommonBoxProps & {
|
|
34
38
|
$alignContent?: import("./styled-helpers").AlignContentValue;
|
|
35
39
|
$alignItems?: ItemAlignmentValue;
|
|
@@ -42,6 +46,7 @@ export declare const Horizontal: import("styled-components").StyledComponent<"di
|
|
|
42
46
|
} & {
|
|
43
47
|
$gridAutoFlow: string;
|
|
44
48
|
}, "$gridAutoFlow">;
|
|
49
|
+
/** Grid that lays children out in one column. */
|
|
45
50
|
export declare const Vertical: import("styled-components").StyledComponent<"div", any, import("./styled-helpers").CommonBoxProps & {
|
|
46
51
|
$alignContent?: import("./styled-helpers").AlignContentValue;
|
|
47
52
|
$alignItems?: ItemAlignmentValue;
|
package/grid.js
CHANGED
|
@@ -15,24 +15,29 @@ const gridDeclarations = {
|
|
|
15
15
|
}
|
|
16
16
|
};
|
|
17
17
|
const renderGridCss = renderDeclarations(gridDeclarations);
|
|
18
|
+
/** `display: grid` box driven by `$`-prefixed props (`$gap`, `$gridAutoFlow`, `$placeItems`, box props). */
|
|
18
19
|
export const GridContainer = styled.div.withConfig({
|
|
19
20
|
displayName: "GridContainer",
|
|
20
21
|
componentId: "sc-1mpmh7u-0"
|
|
21
22
|
})(["display:grid;", ""], renderGridCss);
|
|
23
|
+
/** Grid with explicit columns: a number means that many equal columns, a string is used as `grid-template-columns`. */
|
|
22
24
|
export const Columns = styled(GridContainer).withConfig({
|
|
23
25
|
displayName: "Columns",
|
|
24
26
|
componentId: "sc-1mpmh7u-1"
|
|
25
27
|
})(["grid-template-columns:", ";"], props => gridTemplate(props.$sizes));
|
|
28
|
+
/** Grid with explicit rows: a number means that many equal rows, a string is used as `grid-template-rows`. */
|
|
26
29
|
export const Rows = styled(GridContainer).withConfig({
|
|
27
30
|
displayName: "Rows",
|
|
28
31
|
componentId: "sc-1mpmh7u-2"
|
|
29
32
|
})(["grid-template-rows:", ";"], props => gridTemplate(props.$sizes));
|
|
33
|
+
/** Grid that lays children out in one row. */
|
|
30
34
|
export const Horizontal = styled(GridContainer).attrs({
|
|
31
35
|
$gridAutoFlow: 'column'
|
|
32
36
|
}).withConfig({
|
|
33
37
|
displayName: "Horizontal",
|
|
34
38
|
componentId: "sc-1mpmh7u-3"
|
|
35
39
|
})([""]);
|
|
40
|
+
/** Grid that lays children out in one column. */
|
|
36
41
|
export const Vertical = styled(GridContainer).attrs({
|
|
37
42
|
$gridAutoFlow: 'row'
|
|
38
43
|
}).withConfig({
|
package/hooks/types.d.ts
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
|
+
/** Value a promise resolves to. */
|
|
1
2
|
export type PromiseType<P extends Promise<any>> = P extends Promise<infer T> ? T : never;
|
|
3
|
+
/** Any async function, the constraint the async hooks are generic over. */
|
|
2
4
|
export type FunctionReturningPromise = (...args: any[]) => Promise<any>;
|
package/hooks/useAsync.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { type DependencyList } from 'react';
|
|
2
2
|
import { type FunctionReturningPromise } from './types';
|
|
3
3
|
export type { AsyncState, AsyncFnReturn } from './useAsyncFn';
|
|
4
|
+
/**
|
|
5
|
+
* Run an async function on mount and whenever `deps` change; starts in the loading state.
|
|
6
|
+
* Rejections land in `state.error`, they are not re-thrown.
|
|
7
|
+
*/
|
|
4
8
|
export default function useAsync<T extends FunctionReturningPromise>(fn: T, deps?: DependencyList): {
|
|
5
9
|
loading: boolean;
|
|
6
10
|
error?: undefined;
|
package/hooks/useAsync.js
CHANGED
|
@@ -3,6 +3,10 @@ import useAsyncFn from './useAsyncFn';
|
|
|
3
3
|
const getInitialState = () => ({
|
|
4
4
|
loading: true
|
|
5
5
|
});
|
|
6
|
+
/**
|
|
7
|
+
* Run an async function on mount and whenever `deps` change; starts in the loading state.
|
|
8
|
+
* Rejections land in `state.error`, they are not re-thrown.
|
|
9
|
+
*/
|
|
6
10
|
export default function useAsync(fn, deps = []) {
|
|
7
11
|
const [state, callback] = useAsyncFn(fn, deps, getInitialState);
|
|
8
12
|
useEffect(() => {
|
package/hooks/useAsyncFn.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type DependencyList } from 'react';
|
|
2
2
|
import type { FunctionReturningPromise, PromiseType } from './types';
|
|
3
|
+
/** Loading / error / value of one async call; the union makes the impossible combinations untypeable. */
|
|
3
4
|
export type AsyncState<T> = {
|
|
4
5
|
loading: boolean;
|
|
5
6
|
error?: undefined;
|
|
@@ -18,12 +19,18 @@ export type AsyncState<T> = {
|
|
|
18
19
|
value: T;
|
|
19
20
|
};
|
|
20
21
|
type StateFromFunctionReturningPromise<T extends FunctionReturningPromise> = AsyncState<PromiseType<ReturnType<T>>>;
|
|
22
|
+
/** `reset: true` drops the previous value while reloading, instead of keeping it visible. */
|
|
21
23
|
export type CallbackParams = {
|
|
22
24
|
reset?: boolean;
|
|
23
25
|
};
|
|
26
|
+
/** What {@link useAsyncFn} returns: current state and the trigger. */
|
|
24
27
|
export type AsyncFnReturn<T extends FunctionReturningPromise = FunctionReturningPromise> = [
|
|
25
28
|
StateFromFunctionReturningPromise<T>,
|
|
26
29
|
(p?: CallbackParams) => ReturnType<T>
|
|
27
30
|
];
|
|
31
|
+
/**
|
|
32
|
+
* Run an async function on demand and track its state. Only the newest call may write state,
|
|
33
|
+
* so an overtaken request cannot overwrite a fresher result.
|
|
34
|
+
*/
|
|
28
35
|
export default function useAsyncFn<T extends FunctionReturningPromise>(fn: T, deps?: DependencyList, initialState?: StateFromFunctionReturningPromise<T> | (() => StateFromFunctionReturningPromise<T>)): AsyncFnReturn<T>;
|
|
29
36
|
export {};
|
package/hooks/useAsyncFn.js
CHANGED
|
@@ -3,6 +3,10 @@ import useMountedState from './useMountedState';
|
|
|
3
3
|
const getDefaultState = () => ({
|
|
4
4
|
loading: false
|
|
5
5
|
});
|
|
6
|
+
/**
|
|
7
|
+
* Run an async function on demand and track its state. Only the newest call may write state,
|
|
8
|
+
* so an overtaken request cannot overwrite a fresher result.
|
|
9
|
+
*/
|
|
6
10
|
export default function useAsyncFn(fn, deps = [], initialState = getDefaultState) {
|
|
7
11
|
const lastCallId = useRef(0);
|
|
8
12
|
const isMounted = useMountedState();
|
|
@@ -10,7 +14,6 @@ export default function useAsyncFn(fn, deps = [], initialState = getDefaultState
|
|
|
10
14
|
const callback = useCallback(({
|
|
11
15
|
reset
|
|
12
16
|
} = {}) => {
|
|
13
|
-
// eslint-disable-next-line no-plusplus
|
|
14
17
|
const callId = ++lastCallId.current;
|
|
15
18
|
const canSet = () => isMounted() && callId === lastCallId.current;
|
|
16
19
|
if (canSet()) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { FunctionReturningPromise, PromiseType } from './types';
|
|
2
|
+
/** Same as `AsyncState` plus `count` — how many calls have started, useful to tell first load from a refresh. */
|
|
2
3
|
export type AsyncFunctionState<T> = {
|
|
3
4
|
loading: boolean;
|
|
4
5
|
count: number;
|
|
@@ -21,9 +22,14 @@ export type AsyncFunctionState<T> = {
|
|
|
21
22
|
value: T;
|
|
22
23
|
};
|
|
23
24
|
type StateFromFunctionReturningPromise<T extends FunctionReturningPromise> = AsyncFunctionState<PromiseType<ReturnType<T>>>;
|
|
25
|
+
/** What {@link useAsyncFunction} returns: current state and the original function, stabilised. */
|
|
24
26
|
export type AsyncFunctionReturn<T extends FunctionReturningPromise = FunctionReturningPromise> = [
|
|
25
27
|
StateFromFunctionReturningPromise<T>,
|
|
26
28
|
T
|
|
27
29
|
];
|
|
30
|
+
/**
|
|
31
|
+
* Like {@link useAsyncFn} but the returned trigger keeps the function's own arguments and identity is stable.
|
|
32
|
+
* Prefer it when the call takes parameters.
|
|
33
|
+
*/
|
|
28
34
|
export default function useAsyncFunction<T extends FunctionReturningPromise>(fn: T): AsyncFunctionReturn<T>;
|
|
29
35
|
export {};
|
|
@@ -5,12 +5,15 @@ const getDefaultState = () => ({
|
|
|
5
5
|
loading: false,
|
|
6
6
|
count: 0
|
|
7
7
|
});
|
|
8
|
+
/**
|
|
9
|
+
* Like {@link useAsyncFn} but the returned trigger keeps the function's own arguments and identity is stable.
|
|
10
|
+
* Prefer it when the call takes parameters.
|
|
11
|
+
*/
|
|
8
12
|
export default function useAsyncFunction(fn) {
|
|
9
13
|
const countRef = useRef(0);
|
|
10
14
|
const isMounted = useMountedState();
|
|
11
15
|
const [state, setState] = useState(getDefaultState);
|
|
12
16
|
const execute = usePersistentFunction((...args) => {
|
|
13
|
-
// eslint-disable-next-line no-plusplus
|
|
14
17
|
const count = ++countRef.current;
|
|
15
18
|
const canSet = () => isMounted() && count === countRef.current;
|
|
16
19
|
if (canSet()) {
|
package/hooks/useClickAway.js
CHANGED
|
@@ -48,7 +48,6 @@ export function useClickAway(use, ref,
|
|
|
48
48
|
cb) {
|
|
49
49
|
// Persist the callback function to avoid re-subscribing on every render
|
|
50
50
|
const persistentCb = usePersistentFunction(cb);
|
|
51
|
-
// eslint-disable-next-line consistent-return
|
|
52
51
|
useEffect(() => {
|
|
53
52
|
// Only subscribe if the hook is active and the ref points to an element
|
|
54
53
|
if (use && ref.current) {
|
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
import { type DependencyList } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Run an effect `delay` ms after `deps` settle; a new change cancels the pending run.
|
|
4
|
+
* The effect gets `getIsRunning()` so async work can bail out after unmount.
|
|
5
|
+
*/
|
|
2
6
|
declare const useDelayedEffect: (effect: (getIsRunning: () => boolean) => void, deps: DependencyList, delay: number) => void;
|
|
3
7
|
export default useDelayedEffect;
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { useEffect } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Run an effect `delay` ms after `deps` settle; a new change cancels the pending run.
|
|
4
|
+
* The effect gets `getIsRunning()` so async work can bail out after unmount.
|
|
5
|
+
*/
|
|
2
6
|
const useDelayedEffect = (effect, deps, delay) => {
|
|
3
7
|
useEffect(() => {
|
|
4
8
|
let isRunning = true;
|
package/hooks/useDelayedValue.js
CHANGED
package/hooks/useEffectOnce.d.ts
CHANGED
package/hooks/useEffectOnce.js
CHANGED
package/hooks/useMount.d.ts
CHANGED
package/hooks/useMount.js
CHANGED
package/hooks/useMountedState.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useCallback, useEffect, useRef } from 'react';
|
|
2
|
+
/** Getter telling whether the component is still mounted — guard state writes after an await with it. */
|
|
2
3
|
export default function useMountedState() {
|
|
3
4
|
const mountedRef = useRef(false);
|
|
4
5
|
const get = useCallback(() => mountedRef.current, []);
|
package/hooks/useUnmount.d.ts
CHANGED
package/hooks/useUnmount.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useRef } from 'react';
|
|
2
2
|
import useEffectOnce from './useEffectOnce';
|
|
3
|
+
/** Call `fn` on unmount; the latest render's `fn` is used, so it needs no stable identity. */
|
|
3
4
|
const useUnmount = fn => {
|
|
4
5
|
const fnRef = useRef(fn);
|
|
5
6
|
// update the ref each render so if it change the newest callback will be invoked
|
package/package.json
CHANGED
|
@@ -1,37 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pushwoosh/kit-helpers",
|
|
3
|
-
"version": "4.12.
|
|
3
|
+
"version": "4.12.5",
|
|
4
4
|
"description": "React component for build Pushwoosh products",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "index.js",
|
|
7
7
|
"types": "index.d.ts",
|
|
8
8
|
"sideEffects": false,
|
|
9
9
|
"publishConfig": {
|
|
10
|
-
"access": "public"
|
|
10
|
+
"access": "public",
|
|
11
|
+
"directory": "dist"
|
|
11
12
|
},
|
|
12
|
-
"scripts": {
|
|
13
|
-
"start": "npm run playground",
|
|
14
|
-
"build": "pushwoosh-engine lib:build && cp ai-documentation.md dist/ai-documentation.md",
|
|
15
|
-
"playground": "pushwoosh-engine lib:playground",
|
|
16
|
-
"check": "npm run check:lint && npm run check:types",
|
|
17
|
-
"check:lint": "echo \"Run check:lint\" && NODE_ENV=production eslint ./src",
|
|
18
|
-
"check:lint-fix": "echo \"Run check:lint\" && NODE_ENV=production eslint ./src --fix",
|
|
19
|
-
"check:types": "echo \"Run check:types\" && pushwoosh-engine lib:check-types"
|
|
20
|
-
},
|
|
21
|
-
"pre-commit": "check",
|
|
22
13
|
"dependencies": {
|
|
23
14
|
"react-transition-group": "^4.4.5"
|
|
24
15
|
},
|
|
25
16
|
"devDependencies": {
|
|
26
|
-
"@pushwoosh/
|
|
27
|
-
"@
|
|
28
|
-
"@types/react": "^18.3.
|
|
29
|
-
"@types/react-dom": "^18.3.0",
|
|
17
|
+
"@pushwoosh/kit-constants": "^1.12.3",
|
|
18
|
+
"@types/react": "^18.3.31",
|
|
19
|
+
"@types/react-dom": "^18.3.7",
|
|
30
20
|
"@types/react-transition-group": "^4.4.10",
|
|
31
21
|
"@types/styled-components": "^5.1.34",
|
|
32
22
|
"@types/webpack-env": "^1.18.8",
|
|
33
|
-
"cross-env": "^7.0.3",
|
|
34
|
-
"pre-commit": "^1.2.2",
|
|
35
23
|
"react": "^18.3.1",
|
|
36
24
|
"react-dom": "^18.3.1",
|
|
37
25
|
"styled-components": "^5.3.11"
|
|
@@ -41,6 +29,15 @@
|
|
|
41
29
|
"styled-components": ">=5.3.3"
|
|
42
30
|
},
|
|
43
31
|
"engines": {
|
|
44
|
-
"node": ">=
|
|
32
|
+
"node": ">= 24"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"start": "pnpm run playground",
|
|
36
|
+
"build": "pushwoosh-engine lib:build",
|
|
37
|
+
"playground": "pushwoosh-engine lib:playground",
|
|
38
|
+
"check": "pnpm run check:lint && pnpm run check:types",
|
|
39
|
+
"check:lint": "echo \"Run check:lint\" && NODE_ENV=production eslint ./src",
|
|
40
|
+
"check:lint-fix": "echo \"Run check:lint\" && NODE_ENV=production eslint ./src --fix",
|
|
41
|
+
"check:types": "echo \"Run check:types\" && pushwoosh-engine lib:check-types"
|
|
45
42
|
}
|
|
46
|
-
}
|
|
43
|
+
}
|
package/styled-helpers.d.ts
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
|
+
/** A CSS length: a number is taken as px, a string is passed through verbatim. */
|
|
1
2
|
export type StrNum = string | number;
|
|
3
|
+
/** Type guard for `number`. */
|
|
2
4
|
export declare const isNumber: (value: unknown) => value is number;
|
|
5
|
+
/** Turn a {@link StrNum} into a CSS value: `8` -> `8px`, `'2em'` -> `'2em'`. */
|
|
3
6
|
export declare const toCssValue: (value: StrNum) => string;
|
|
7
|
+
/**
|
|
8
|
+
* One `property: value;` declaration, or `undefined` when the value is unset.
|
|
9
|
+
* @param valueConvert applied to the value before printing, e.g. {@link toCssValue}
|
|
10
|
+
*/
|
|
4
11
|
export declare const createCssDeclaration: (property: string, value: any, valueConvert?: (v: any) => any) => string | undefined;
|
|
12
|
+
/** Per-side value for a box property — either the four sides, or the `horizontal`/`vertical` shorthands. */
|
|
5
13
|
export type CssBoxSides<T> = {
|
|
6
14
|
top?: T;
|
|
7
15
|
right?: T;
|
|
@@ -16,12 +24,22 @@ export type CssBoxSides<T> = {
|
|
|
16
24
|
right?: T;
|
|
17
25
|
left?: T;
|
|
18
26
|
};
|
|
27
|
+
/**
|
|
28
|
+
* Declarations for a box property (`margin`, `padding`, `border`): one shorthand for a scalar,
|
|
29
|
+
* or per-side declarations for a {@link CssBoxSides} object.
|
|
30
|
+
*/
|
|
19
31
|
export declare function createCssBoxDeclaration<T>(property: string, value?: StrNum | CssBoxSides<T>, valueConvert?: (v: any) => any): string | undefined;
|
|
32
|
+
/** Allowed `overflow` values. */
|
|
20
33
|
export type OverflowValue = 'hidden' | 'auto' | 'scroll' | 'visible';
|
|
34
|
+
/** Allowed `position` values. */
|
|
21
35
|
export type PositionValue = 'static' | 'relative' | 'absolute' | 'fixed' | 'sticky';
|
|
36
|
+
/** Allowed values for the item-alignment properties (`align-items`, `justify-items`, `place-items`). */
|
|
22
37
|
export type ItemAlignmentValue = 'center' | 'start' | 'end' | 'baseline' | 'stretch';
|
|
38
|
+
/** Allowed `justify-content` values. */
|
|
23
39
|
export type JustifyContentValue = 'center' | 'start' | 'end' | 'space-between' | 'space-around' | 'space-evenly' | 'stretch';
|
|
40
|
+
/** Allowed `align-content` values. */
|
|
24
41
|
export type AlignContentValue = JustifyContentValue | 'baseline';
|
|
42
|
+
/** Box-model and positioning props shared by every layout component; the `$` prefix keeps them off the DOM. */
|
|
25
43
|
export type CommonBoxProps = {
|
|
26
44
|
$bgColor?: string;
|
|
27
45
|
$basis?: StrNum;
|
|
@@ -50,17 +68,25 @@ export type CommonBoxProps = {
|
|
|
50
68
|
$width?: StrNum;
|
|
51
69
|
$zIndex?: number;
|
|
52
70
|
};
|
|
71
|
+
/** {@link CommonBoxProps} plus the alignment props meaningful for a flex or grid container. */
|
|
53
72
|
export type CommonContainerProps = CommonBoxProps & {
|
|
54
73
|
$alignContent?: AlignContentValue;
|
|
55
74
|
$alignItems?: ItemAlignmentValue;
|
|
56
75
|
$gap?: StrNum;
|
|
57
76
|
$justifyContent?: JustifyContentValue;
|
|
58
77
|
};
|
|
78
|
+
/** How one prop maps to CSS: target property, whether it is a box property, and an optional value converter. */
|
|
59
79
|
export type CssDeclarationConfig = {
|
|
60
80
|
property: string;
|
|
61
81
|
box?: boolean;
|
|
62
82
|
convert?: (v: any) => any;
|
|
63
83
|
};
|
|
84
|
+
/** Prop-to-CSS map for {@link CommonBoxProps}. */
|
|
64
85
|
export declare const commonBoxDeclarations: Partial<Record<keyof CommonBoxProps, CssDeclarationConfig>>;
|
|
86
|
+
/** Prop-to-CSS map for {@link CommonContainerProps}. */
|
|
65
87
|
export declare const commonContainerDeclarations: Partial<Record<keyof CommonContainerProps, CssDeclarationConfig>>;
|
|
88
|
+
/**
|
|
89
|
+
* Build the styled-components interpolation for a declaration map: takes props, returns the CSS text.
|
|
90
|
+
* Props absent from the map are ignored, so a component only reacts to what it declared.
|
|
91
|
+
*/
|
|
66
92
|
export declare const renderDeclarations: <T extends Record<string, any>>(declarations: Partial<Record<keyof T, CssDeclarationConfig>>) => (props: T) => string;
|
package/styled-helpers.js
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
|
+
/** Type guard for `number`. */
|
|
1
2
|
export const isNumber = value => typeof value === 'number';
|
|
3
|
+
/** Turn a {@link StrNum} into a CSS value: `8` -> `8px`, `'2em'` -> `'2em'`. */
|
|
2
4
|
export const toCssValue = value => isNumber(value) ? `${value}px` : value;
|
|
5
|
+
/**
|
|
6
|
+
* One `property: value;` declaration, or `undefined` when the value is unset.
|
|
7
|
+
* @param valueConvert applied to the value before printing, e.g. {@link toCssValue}
|
|
8
|
+
*/
|
|
3
9
|
export const createCssDeclaration = (property, value, valueConvert) => {
|
|
4
10
|
if (value !== undefined) {
|
|
5
11
|
return `${property}: ${valueConvert ? valueConvert(value) : value};`;
|
|
6
12
|
}
|
|
7
13
|
return undefined;
|
|
8
14
|
};
|
|
15
|
+
/**
|
|
16
|
+
* Declarations for a box property (`margin`, `padding`, `border`): one shorthand for a scalar,
|
|
17
|
+
* or per-side declarations for a {@link CssBoxSides} object.
|
|
18
|
+
*/
|
|
9
19
|
export function createCssBoxDeclaration(property, value, valueConvert) {
|
|
10
20
|
if (typeof value === 'object') {
|
|
11
21
|
const declarations = [];
|
|
@@ -27,6 +37,7 @@ export function createCssBoxDeclaration(property, value, valueConvert) {
|
|
|
27
37
|
}
|
|
28
38
|
return createCssDeclaration(property, value, valueConvert);
|
|
29
39
|
}
|
|
40
|
+
/** Prop-to-CSS map for {@link CommonBoxProps}. */
|
|
30
41
|
export const commonBoxDeclarations = {
|
|
31
42
|
$bgColor: {
|
|
32
43
|
property: 'background-color'
|
|
@@ -125,6 +136,7 @@ export const commonBoxDeclarations = {
|
|
|
125
136
|
property: 'z-index'
|
|
126
137
|
}
|
|
127
138
|
};
|
|
139
|
+
/** Prop-to-CSS map for {@link CommonContainerProps}. */
|
|
128
140
|
export const commonContainerDeclarations = {
|
|
129
141
|
...commonBoxDeclarations,
|
|
130
142
|
$alignContent: {
|
|
@@ -141,6 +153,10 @@ export const commonContainerDeclarations = {
|
|
|
141
153
|
property: 'justify-content'
|
|
142
154
|
}
|
|
143
155
|
};
|
|
156
|
+
/**
|
|
157
|
+
* Build the styled-components interpolation for a declaration map: takes props, returns the CSS text.
|
|
158
|
+
* Props absent from the map are ignored, so a component only reacts to what it declared.
|
|
159
|
+
*/
|
|
144
160
|
export const renderDeclarations = declarations => props => Object.entries(props).map(([key, value]) => {
|
|
145
161
|
const config = declarations[key];
|
|
146
162
|
if (!config || value === undefined) return undefined;
|