@fluentui/react-context-selector 0.0.0-nightly-20220302-0405.1

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.
@@ -0,0 +1,44 @@
1
+ import * as React_2 from 'react';
2
+
3
+ export declare type Context<Value> = React_2.Context<Value> & {
4
+ Provider: React_2.FC<React_2.ProviderProps<Value>>;
5
+ Consumer: never;
6
+ };
7
+
8
+ export declare type ContextSelector<Value, SelectedValue> = (value: Value) => SelectedValue;
9
+
10
+ export declare type ContextValue<Value> = {
11
+ /** Holds a set of subscribers from components. */
12
+ listeners: ((payload: readonly [ContextVersion, Value]) => void)[];
13
+ /** Holds an actual value of React's context that will be propagated down for computations. */
14
+ value: React_2.MutableRefObject<Value>;
15
+ /** A version field is used to sync a context value and consumers. */
16
+ version: React_2.MutableRefObject<ContextVersion>;
17
+ };
18
+
19
+ export declare type ContextValues<Value> = ContextValue<Value> & {
20
+ /** List of listners to publish changes */
21
+ listeners: ((payload: readonly [ContextVersion, Record<string, Value>]) => void)[];
22
+ };
23
+
24
+ export declare type ContextVersion = number;
25
+
26
+ export declare const createContext: <Value>(defaultValue: Value) => Context<Value>;
27
+
28
+ /**
29
+ * This hook returns context selected value by selector.
30
+ * It will only accept context created by `createContext`.
31
+ * It will trigger re-render if only the selected value is referencially changed.
32
+ */
33
+ export declare const useContextSelector: <Value, SelectedValue>(context: Context<Value>, selector: ContextSelector<Value, SelectedValue>) => SelectedValue;
34
+
35
+ /**
36
+ * Utility hook for contexts created by react-context-selector to determine if a parent context exists
37
+ * WARNING: This hook will not work for native React contexts
38
+ *
39
+ * @param context - context created by react-context-selector
40
+ * @returns whether the hook is wrapped by a parent context
41
+ */
42
+ export declare function useHasParentContext<Value>(context: Context<Value>): boolean;
43
+
44
+ export { }
@@ -0,0 +1,2 @@
1
+ import { Context } from './types';
2
+ export declare const createContext: <Value>(defaultValue: Value) => Context<Value>;
@@ -0,0 +1,60 @@
1
+ import { useIsomorphicLayoutEffect } from '@fluentui/react-utilities';
2
+ import * as React from 'react';
3
+ import { unstable_NormalPriority as NormalPriority, unstable_runWithPriority as runWithPriority } from 'scheduler';
4
+
5
+ const createProvider = Original => {
6
+ const Provider = props => {
7
+ // Holds an actual "props.value"
8
+ const valueRef = React.useRef(props.value); // Used to sync context updates and avoid stale values, can be considered as render/effect counter of Provider.
9
+
10
+ const versionRef = React.useRef(0); // A stable object, is used to avoid context updates via mutation of its values.
11
+
12
+ const contextValue = React.useRef();
13
+
14
+ if (!contextValue.current) {
15
+ contextValue.current = {
16
+ value: valueRef,
17
+ version: versionRef,
18
+ listeners: []
19
+ };
20
+ }
21
+
22
+ useIsomorphicLayoutEffect(() => {
23
+ valueRef.current = props.value;
24
+ versionRef.current += 1;
25
+ runWithPriority(NormalPriority, () => {
26
+ contextValue.current.listeners.forEach(listener => {
27
+ listener([versionRef.current, props.value]);
28
+ });
29
+ });
30
+ }, [props.value]);
31
+ return /*#__PURE__*/React.createElement(Original, {
32
+ value: contextValue.current
33
+ }, props.children);
34
+ };
35
+ /* istanbul ignore else */
36
+
37
+
38
+ if (process.env.NODE_ENV !== 'production') {
39
+ Provider.displayName = 'ContextSelector.Provider';
40
+ }
41
+
42
+ return Provider;
43
+ };
44
+
45
+ export const createContext = defaultValue => {
46
+ const context = /*#__PURE__*/React.createContext({
47
+ value: {
48
+ current: defaultValue
49
+ },
50
+ version: {
51
+ current: -1
52
+ },
53
+ listeners: []
54
+ });
55
+ context.Provider = createProvider(context.Provider); // We don't support Consumer API
56
+
57
+ delete context.Consumer;
58
+ return context;
59
+ };
60
+ //# sourceMappingURL=createContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["createContext.ts"],"names":[],"mappings":"AAAA,SAAS,yBAAT,QAA0C,2BAA1C;AACA,OAAO,KAAK,KAAZ,MAAuB,OAAvB;AACA,SAAS,uBAAuB,IAAI,cAApC,EAAoD,wBAAwB,IAAI,eAAhF,QAAuG,WAAvG;;AAIA,MAAM,cAAc,GAAW,QAAR,IAAyD;AAC9E,QAAM,QAAQ,GAAyC,KAAK,IAAG;AAC7D;AACA,UAAM,QAAQ,GAAG,KAAK,CAAC,MAAN,CAAa,KAAK,CAAC,KAAnB,CAAjB,CAF6D,CAG7D;;AACA,UAAM,UAAU,GAAG,KAAK,CAAC,MAAN,CAAa,CAAb,CAAnB,CAJ6D,CAM7D;;AACA,UAAM,YAAY,GAAG,KAAK,CAAC,MAAN,EAArB;;AAEA,QAAI,CAAC,YAAY,CAAC,OAAlB,EAA2B;AACzB,MAAA,YAAY,CAAC,OAAb,GAAuB;AACrB,QAAA,KAAK,EAAE,QADc;AAErB,QAAA,OAAO,EAAE,UAFY;AAGrB,QAAA,SAAS,EAAE;AAHU,OAAvB;AAKD;;AAED,IAAA,yBAAyB,CAAC,MAAK;AAC7B,MAAA,QAAQ,CAAC,OAAT,GAAmB,KAAK,CAAC,KAAzB;AACA,MAAA,UAAU,CAAC,OAAX,IAAsB,CAAtB;AAEA,MAAA,eAAe,CAAC,cAAD,EAAiB,MAAK;AAClC,QAAA,YAAY,CAAC,OAAb,CAA6C,SAA7C,CAAuD,OAAvD,CAA+D,QAAQ,IAAG;AACzE,UAAA,QAAQ,CAAC,CAAC,UAAU,CAAC,OAAZ,EAAqB,KAAK,CAAC,KAA3B,CAAD,CAAR;AACD,SAFA;AAGF,OAJc,CAAf;AAKD,KATwB,EAStB,CAAC,KAAK,CAAC,KAAP,CATsB,CAAzB;AAWA,wBAAO,KAAK,CAAC,aAAN,CAAoB,QAApB,EAA8B;AAAE,MAAA,KAAK,EAAE,YAAY,CAAC;AAAtB,KAA9B,EAA+D,KAAK,CAAC,QAArE,CAAP;AACD,GA7BD;AA+BA;;;AACA,MAAI,OAAO,CAAC,GAAR,CAAY,QAAZ,KAAyB,YAA7B,EAA2C;AACzC,IAAA,QAAQ,CAAC,WAAT,GAAuB,0BAAvB;AACD;;AAED,SAAQ,QAAR;AACD,CAtCD;;AAwCA,OAAO,MAAM,aAAa,GAAW,YAAR,IAA+C;AAC1E,QAAM,OAAO,gBAAG,KAAK,CAAC,aAAN,CAAyC;AACvD,IAAA,KAAK,EAAE;AAAE,MAAA,OAAO,EAAE;AAAX,KADgD;AAEvD,IAAA,OAAO,EAAE;AAAE,MAAA,OAAO,EAAE,CAAC;AAAZ,KAF8C;AAGvD,IAAA,SAAS,EAAE;AAH4C,GAAzC,CAAhB;AAMA,EAAA,OAAO,CAAC,QAAR,GAAmB,cAAc,CAAQ,OAAO,CAAC,QAAhB,CAAjC,CAP0E,CAS1E;;AACA,SAAS,OAAsC,CAAC,QAAhD;AAEA,SAAQ,OAAR;AACD,CAbM","sourcesContent":["import { useIsomorphicLayoutEffect } from '@fluentui/react-utilities';\nimport * as React from 'react';\nimport { unstable_NormalPriority as NormalPriority, unstable_runWithPriority as runWithPriority } from 'scheduler';\n\nimport { Context, ContextValue } from './types';\n\nconst createProvider = <Value>(Original: React.Provider<ContextValue<Value>>) => {\n const Provider: React.FC<React.ProviderProps<Value>> = props => {\n // Holds an actual \"props.value\"\n const valueRef = React.useRef(props.value);\n // Used to sync context updates and avoid stale values, can be considered as render/effect counter of Provider.\n const versionRef = React.useRef(0);\n\n // A stable object, is used to avoid context updates via mutation of its values.\n const contextValue = React.useRef<ContextValue<Value>>();\n\n if (!contextValue.current) {\n contextValue.current = {\n value: valueRef,\n version: versionRef,\n listeners: [],\n };\n }\n\n useIsomorphicLayoutEffect(() => {\n valueRef.current = props.value;\n versionRef.current += 1;\n\n runWithPriority(NormalPriority, () => {\n (contextValue.current as ContextValue<Value>).listeners.forEach(listener => {\n listener([versionRef.current, props.value]);\n });\n });\n }, [props.value]);\n\n return React.createElement(Original, { value: contextValue.current }, props.children);\n };\n\n /* istanbul ignore else */\n if (process.env.NODE_ENV !== 'production') {\n Provider.displayName = 'ContextSelector.Provider';\n }\n\n return (Provider as unknown) as React.Provider<ContextValue<Value>>;\n};\n\nexport const createContext = <Value>(defaultValue: Value): Context<Value> => {\n const context = React.createContext<ContextValue<Value>>({\n value: { current: defaultValue },\n version: { current: -1 },\n listeners: [],\n });\n\n context.Provider = createProvider<Value>(context.Provider);\n\n // We don't support Consumer API\n delete ((context as unknown) as Context<Value>).Consumer;\n\n return (context as unknown) as Context<Value>;\n};\n"],"sourceRoot":"../src/"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export { createContext } from './createContext';
2
+ export { useContextSelector } from './useContextSelector';
3
+ export { useHasParentContext } from './useHasParentContext';
4
+ export * from './types';
package/lib/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { createContext } from './createContext';
2
+ export { useContextSelector } from './useContextSelector';
3
+ export { useHasParentContext } from './useHasParentContext';
4
+ export * from './types';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"../src/","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,cAAc,SAAS,CAAC","sourcesContent":["export { createContext } from './createContext';\nexport { useContextSelector } from './useContextSelector';\nexport { useHasParentContext } from './useHasParentContext';\nexport * from './types';\n"]}
@@ -0,0 +1,11 @@
1
+ // This file is read by tools that parse documentation comments conforming to the TSDoc standard.
2
+ // It should be published with your NPM package. It should not be tracked by Git.
3
+ {
4
+ "tsdocVersion": "0.12",
5
+ "toolPackages": [
6
+ {
7
+ "packageName": "@microsoft/api-extractor",
8
+ "packageVersion": "7.18.1"
9
+ }
10
+ ]
11
+ }
package/lib/types.d.ts ADDED
@@ -0,0 +1,19 @@
1
+ import * as React from 'react';
2
+ export declare type Context<Value> = React.Context<Value> & {
3
+ Provider: React.FC<React.ProviderProps<Value>>;
4
+ Consumer: never;
5
+ };
6
+ export declare type ContextSelector<Value, SelectedValue> = (value: Value) => SelectedValue;
7
+ export declare type ContextVersion = number;
8
+ export declare type ContextValue<Value> = {
9
+ /** Holds a set of subscribers from components. */
10
+ listeners: ((payload: readonly [ContextVersion, Value]) => void)[];
11
+ /** Holds an actual value of React's context that will be propagated down for computations. */
12
+ value: React.MutableRefObject<Value>;
13
+ /** A version field is used to sync a context value and consumers. */
14
+ version: React.MutableRefObject<ContextVersion>;
15
+ };
16
+ export declare type ContextValues<Value> = ContextValue<Value> & {
17
+ /** List of listners to publish changes */
18
+ listeners: ((payload: readonly [ContextVersion, Record<string, Value>]) => void)[];
19
+ };
package/lib/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"../src/","sources":["types.ts"],"names":[],"mappings":"","sourcesContent":["import * as React from 'react';\n\nexport type Context<Value> = React.Context<Value> & {\n Provider: React.FC<React.ProviderProps<Value>>;\n Consumer: never;\n};\n\nexport type ContextSelector<Value, SelectedValue> = (value: Value) => SelectedValue;\n\nexport type ContextVersion = number;\n\nexport type ContextValue<Value> = {\n /** Holds a set of subscribers from components. */\n listeners: ((payload: readonly [ContextVersion, Value]) => void)[];\n\n /** Holds an actual value of React's context that will be propagated down for computations. */\n value: React.MutableRefObject<Value>;\n\n /** A version field is used to sync a context value and consumers. */\n version: React.MutableRefObject<ContextVersion>;\n};\n\nexport type ContextValues<Value> = ContextValue<Value> & {\n /** List of listners to publish changes */\n listeners: ((payload: readonly [ContextVersion, Record<string, Value>]) => void)[];\n};\n"]}
@@ -0,0 +1,7 @@
1
+ import { Context, ContextSelector } from './types';
2
+ /**
3
+ * This hook returns context selected value by selector.
4
+ * It will only accept context created by `createContext`.
5
+ * It will trigger re-render if only the selected value is referencially changed.
6
+ */
7
+ export declare const useContextSelector: <Value, SelectedValue>(context: Context<Value>, selector: ContextSelector<Value, SelectedValue>) => SelectedValue;
@@ -0,0 +1,84 @@
1
+ import { useIsomorphicLayoutEffect } from '@fluentui/react-utilities';
2
+ import * as React from 'react';
3
+ /**
4
+ * This hook returns context selected value by selector.
5
+ * It will only accept context created by `createContext`.
6
+ * It will trigger re-render if only the selected value is referencially changed.
7
+ */
8
+
9
+ export const useContextSelector = (context, selector) => {
10
+ const contextValue = React.useContext(context);
11
+ const {
12
+ value: {
13
+ current: value
14
+ },
15
+ version: {
16
+ current: version
17
+ },
18
+ listeners
19
+ } = contextValue;
20
+ const selected = selector(value);
21
+ const [state, dispatch] = React.useReducer((prevState, payload) => {
22
+ if (!payload) {
23
+ // early bail out when is dispatched during render
24
+ return [value, selected];
25
+ }
26
+
27
+ if (payload[0] <= version) {
28
+ if (objectIs(prevState[1], selected)) {
29
+ return prevState; // bail out
30
+ }
31
+
32
+ return [value, selected];
33
+ }
34
+
35
+ try {
36
+ if (objectIs(prevState[0], payload[1])) {
37
+ return prevState; // do not update
38
+ }
39
+
40
+ const nextSelected = selector(payload[1]);
41
+
42
+ if (objectIs(prevState[1], nextSelected)) {
43
+ return prevState; // do not update
44
+ }
45
+
46
+ return [payload[1], nextSelected];
47
+ } catch (e) {// ignored (stale props or some other reason)
48
+ } // explicitly spread to enforce typing
49
+
50
+
51
+ return [prevState[0], prevState[1]]; // schedule update
52
+ }, [value, selected]);
53
+
54
+ if (!objectIs(state[1], selected)) {
55
+ // schedule re-render
56
+ // this is safe because it's self contained
57
+ dispatch(undefined);
58
+ }
59
+
60
+ useIsomorphicLayoutEffect(() => {
61
+ listeners.push(dispatch);
62
+ return () => {
63
+ const index = listeners.indexOf(dispatch);
64
+ listeners.splice(index, 1);
65
+ };
66
+ }, [listeners]);
67
+ return state[1];
68
+ };
69
+ /**
70
+ * inlined Object.is polyfill to avoid requiring consumers ship their own
71
+ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
72
+ */
73
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
74
+
75
+ function is(x, y) {
76
+ return x === y && (x !== 0 || 1 / x === 1 / y) || x !== x && y !== y // eslint-disable-line no-self-compare
77
+ ;
78
+ } // eslint-disable-next-line @typescript-eslint/no-explicit-any
79
+
80
+
81
+ const objectIs = // eslint-disable-next-line @typescript-eslint/ban-ts-comment
82
+ // @ts-ignore fallback to native if it exists (not in IE11)
83
+ typeof Object.is === 'function' ? Object.is : is;
84
+ //# sourceMappingURL=useContextSelector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["useContextSelector.ts"],"names":[],"mappings":"AAAA,SAAS,yBAAT,QAA0C,2BAA1C;AACA,OAAO,KAAK,KAAZ,MAAuB,OAAvB;AAaA;;;;AAIG;;AACH,OAAO,MAAM,kBAAkB,GAAG,CAChC,OADgC,EAEhC,QAFgC,KAGf;AACjB,QAAM,YAAY,GAAG,KAAK,CAAC,UAAN,CAAkB,OAAlB,CAArB;AAEA,QAAM;AACJ,IAAA,KAAK,EAAE;AAAE,MAAA,OAAO,EAAE;AAAX,KADH;AAEJ,IAAA,OAAO,EAAE;AAAE,MAAA,OAAO,EAAE;AAAX,KAFL;AAGJ,IAAA;AAHI,MAIF,YAJJ;AAKA,QAAM,QAAQ,GAAG,QAAQ,CAAC,KAAD,CAAzB;AAEA,QAAM,CAAC,KAAD,EAAQ,QAAR,IAAoB,KAAK,CAAC,UAAN,CACxB,CACE,SADF,EAEE,OAFF,KAKqC;AACnC,QAAI,CAAC,OAAL,EAAc;AACZ;AACA,aAAO,CAAC,KAAD,EAAQ,QAAR,CAAP;AACD;;AAED,QAAI,OAAO,CAAC,CAAD,CAAP,IAAc,OAAlB,EAA2B;AACzB,UAAI,QAAQ,CAAC,SAAS,CAAC,CAAD,CAAV,EAAe,QAAf,CAAZ,EAAsC;AACpC,eAAO,SAAP,CADoC,CAClB;AACnB;;AAED,aAAO,CAAC,KAAD,EAAQ,QAAR,CAAP;AACD;;AAED,QAAI;AACF,UAAI,QAAQ,CAAC,SAAS,CAAC,CAAD,CAAV,EAAe,OAAO,CAAC,CAAD,CAAtB,CAAZ,EAAwC;AACtC,eAAO,SAAP,CADsC,CACpB;AACnB;;AAED,YAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAD,CAAR,CAA7B;;AAEA,UAAI,QAAQ,CAAC,SAAS,CAAC,CAAD,CAAV,EAAe,YAAf,CAAZ,EAA0C;AACxC,eAAO,SAAP,CADwC,CACtB;AACnB;;AAED,aAAO,CAAC,OAAO,CAAC,CAAD,CAAR,EAAa,YAAb,CAAP;AACD,KAZD,CAYE,OAAO,CAAP,EAAU,CACV;AACD,KA5BkC,CA8BnC;;;AACA,WAAO,CAAC,SAAS,CAAC,CAAD,CAAV,EAAe,SAAS,CAAC,CAAD,CAAxB,CAAP,CA/BmC,CA+BW;AAC/C,GAtCuB,EAuCxB,CAAC,KAAD,EAAQ,QAAR,CAvCwB,CAA1B;;AA0CA,MAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAD,CAAN,EAAW,QAAX,CAAb,EAAmC;AACjC;AACA;AACA,IAAA,QAAQ,CAAC,SAAD,CAAR;AACD;;AAED,EAAA,yBAAyB,CAAC,MAAK;AAC7B,IAAA,SAAS,CAAC,IAAV,CAAe,QAAf;AAEA,WAAO,MAAK;AACV,YAAM,KAAK,GAAG,SAAS,CAAC,OAAV,CAAkB,QAAlB,CAAd;AACA,MAAA,SAAS,CAAC,MAAV,CAAiB,KAAjB,EAAwB,CAAxB;AACD,KAHD;AAID,GAPwB,EAOtB,CAAC,SAAD,CAPsB,CAAzB;AASA,SAAO,KAAK,CAAC,CAAD,CAAZ;AACD,CAvEM;AAyEP;;;AAGG;AACH;;AACA,SAAS,EAAT,CAAY,CAAZ,EAAoB,CAApB,EAA0B;AACxB,SACG,CAAC,KAAK,CAAN,KAAY,CAAC,KAAK,CAAN,IAAW,IAAI,CAAJ,KAAU,IAAI,CAArC,CAAD,IAA8C,CAAC,KAAK,CAAN,IAAW,CAAC,KAAK,CADjE,CACoE;AADpE;AAGD,C,CAED;;;AACA,MAAM,QAAQ,GACZ;AACA;AACA,OAAO,MAAM,CAAC,EAAd,KAAqB,UAArB,GAAkC,MAAM,CAAC,EAAzC,GAA8C,EAHhD","sourcesContent":["import { useIsomorphicLayoutEffect } from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nimport { Context, ContextSelector, ContextValue, ContextVersion } from './types';\n\n/**\n * Narrowing React.Reducer type to be more easily usable below.\n * No need to export this as it's for internal reducer usage.\n */\ntype ContextReducer<Value, SelectedValue> = React.Reducer<\n readonly [Value, SelectedValue],\n undefined | readonly [ContextVersion, Value]\n>;\n\n/**\n * This hook returns context selected value by selector.\n * It will only accept context created by `createContext`.\n * It will trigger re-render if only the selected value is referencially changed.\n */\nexport const useContextSelector = <Value, SelectedValue>(\n context: Context<Value>,\n selector: ContextSelector<Value, SelectedValue>,\n): SelectedValue => {\n const contextValue = React.useContext((context as unknown) as Context<ContextValue<Value>>);\n\n const {\n value: { current: value },\n version: { current: version },\n listeners,\n } = contextValue;\n const selected = selector(value);\n\n const [state, dispatch] = React.useReducer<ContextReducer<Value, SelectedValue>>(\n (\n prevState: readonly [Value /* contextValue */, SelectedValue /* selector(value) */],\n payload:\n | undefined // undefined from render below\n | readonly [ContextVersion, Value], // from provider effect\n ): readonly [Value, SelectedValue] => {\n if (!payload) {\n // early bail out when is dispatched during render\n return [value, selected] as const;\n }\n\n if (payload[0] <= version) {\n if (objectIs(prevState[1], selected)) {\n return prevState; // bail out\n }\n\n return [value, selected] as const;\n }\n\n try {\n if (objectIs(prevState[0], payload[1])) {\n return prevState; // do not update\n }\n\n const nextSelected = selector(payload[1]);\n\n if (objectIs(prevState[1], nextSelected)) {\n return prevState; // do not update\n }\n\n return [payload[1], nextSelected] as const;\n } catch (e) {\n // ignored (stale props or some other reason)\n }\n\n // explicitly spread to enforce typing\n return [prevState[0], prevState[1]] as const; // schedule update\n },\n [value, selected] as const,\n );\n\n if (!objectIs(state[1], selected)) {\n // schedule re-render\n // this is safe because it's self contained\n dispatch(undefined);\n }\n\n useIsomorphicLayoutEffect(() => {\n listeners.push(dispatch);\n\n return () => {\n const index = listeners.indexOf(dispatch);\n listeners.splice(index, 1);\n };\n }, [listeners]);\n\n return state[1] as SelectedValue;\n};\n\n/**\n * inlined Object.is polyfill to avoid requiring consumers ship their own\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction is(x: any, y: any) {\n return (\n (x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y) // eslint-disable-line no-self-compare\n );\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst objectIs: (x: any, y: any) => boolean =\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore fallback to native if it exists (not in IE11)\n typeof Object.is === 'function' ? Object.is : is;\n"],"sourceRoot":"../src/"}
@@ -0,0 +1,9 @@
1
+ import { Context } from './types';
2
+ /**
3
+ * Utility hook for contexts created by react-context-selector to determine if a parent context exists
4
+ * WARNING: This hook will not work for native React contexts
5
+ *
6
+ * @param context - context created by react-context-selector
7
+ * @returns whether the hook is wrapped by a parent context
8
+ */
9
+ export declare function useHasParentContext<Value>(context: Context<Value>): boolean;
@@ -0,0 +1,19 @@
1
+ import * as React from 'react';
2
+ /**
3
+ * Utility hook for contexts created by react-context-selector to determine if a parent context exists
4
+ * WARNING: This hook will not work for native React contexts
5
+ *
6
+ * @param context - context created by react-context-selector
7
+ * @returns whether the hook is wrapped by a parent context
8
+ */
9
+
10
+ export function useHasParentContext(context) {
11
+ const contextValue = React.useContext(context);
12
+
13
+ if (contextValue.version) {
14
+ return contextValue.version.current !== -1;
15
+ }
16
+
17
+ return false;
18
+ }
19
+ //# sourceMappingURL=useHasParentContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["useHasParentContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAZ,MAAuB,OAAvB;AAGA;;;;;;AAMG;;AACH,OAAM,SAAU,mBAAV,CAAqC,OAArC,EAA4D;AAChE,QAAM,YAAY,GAAG,KAAK,CAAC,UAAN,CAAkB,OAAlB,CAArB;;AAEA,MAAI,YAAY,CAAC,OAAjB,EAA0B;AACxB,WAAO,YAAY,CAAC,OAAb,CAAqB,OAArB,KAAiC,CAAC,CAAzC;AACD;;AAED,SAAO,KAAP;AACD","sourcesContent":["import * as React from 'react';\nimport { Context, ContextValue } from './types';\n\n/**\n * Utility hook for contexts created by react-context-selector to determine if a parent context exists\n * WARNING: This hook will not work for native React contexts\n *\n * @param context - context created by react-context-selector\n * @returns whether the hook is wrapped by a parent context\n */\nexport function useHasParentContext<Value>(context: Context<Value>) {\n const contextValue = React.useContext((context as unknown) as Context<ContextValue<Value>>);\n\n if (contextValue.version) {\n return contextValue.version.current !== -1;\n }\n\n return false;\n}\n"],"sourceRoot":"../src/"}
@@ -0,0 +1,2 @@
1
+ import { Context } from './types';
2
+ export declare const createContext: <Value>(defaultValue: Value) => Context<Value>;
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createContext = void 0;
7
+
8
+ const react_utilities_1 = /*#__PURE__*/require("@fluentui/react-utilities");
9
+
10
+ const React = /*#__PURE__*/require("react");
11
+
12
+ const scheduler_1 = /*#__PURE__*/require("scheduler");
13
+
14
+ const createProvider = Original => {
15
+ const Provider = props => {
16
+ // Holds an actual "props.value"
17
+ const valueRef = React.useRef(props.value); // Used to sync context updates and avoid stale values, can be considered as render/effect counter of Provider.
18
+
19
+ const versionRef = React.useRef(0); // A stable object, is used to avoid context updates via mutation of its values.
20
+
21
+ const contextValue = React.useRef();
22
+
23
+ if (!contextValue.current) {
24
+ contextValue.current = {
25
+ value: valueRef,
26
+ version: versionRef,
27
+ listeners: []
28
+ };
29
+ }
30
+
31
+ react_utilities_1.useIsomorphicLayoutEffect(() => {
32
+ valueRef.current = props.value;
33
+ versionRef.current += 1;
34
+ scheduler_1.unstable_runWithPriority(scheduler_1.unstable_NormalPriority, () => {
35
+ contextValue.current.listeners.forEach(listener => {
36
+ listener([versionRef.current, props.value]);
37
+ });
38
+ });
39
+ }, [props.value]);
40
+ return React.createElement(Original, {
41
+ value: contextValue.current
42
+ }, props.children);
43
+ };
44
+ /* istanbul ignore else */
45
+
46
+
47
+ if (process.env.NODE_ENV !== 'production') {
48
+ Provider.displayName = 'ContextSelector.Provider';
49
+ }
50
+
51
+ return Provider;
52
+ };
53
+
54
+ const createContext = defaultValue => {
55
+ const context = React.createContext({
56
+ value: {
57
+ current: defaultValue
58
+ },
59
+ version: {
60
+ current: -1
61
+ },
62
+ listeners: []
63
+ });
64
+ context.Provider = createProvider(context.Provider); // We don't support Consumer API
65
+
66
+ delete context.Consumer;
67
+ return context;
68
+ };
69
+
70
+ exports.createContext = createContext;
71
+ //# sourceMappingURL=createContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["createContext.ts"],"names":[],"mappings":";;;;;;;AAAA,MAAA,iBAAA,gBAAA,OAAA,CAAA,2BAAA,CAAA;;AACA,MAAA,KAAA,gBAAA,OAAA,CAAA,OAAA,CAAA;;AACA,MAAA,WAAA,gBAAA,OAAA,CAAA,WAAA,CAAA;;AAIA,MAAM,cAAc,GAAW,QAAR,IAAyD;AAC9E,QAAM,QAAQ,GAAyC,KAAK,IAAG;AAC7D;AACA,UAAM,QAAQ,GAAG,KAAK,CAAC,MAAN,CAAa,KAAK,CAAC,KAAnB,CAAjB,CAF6D,CAG7D;;AACA,UAAM,UAAU,GAAG,KAAK,CAAC,MAAN,CAAa,CAAb,CAAnB,CAJ6D,CAM7D;;AACA,UAAM,YAAY,GAAG,KAAK,CAAC,MAAN,EAArB;;AAEA,QAAI,CAAC,YAAY,CAAC,OAAlB,EAA2B;AACzB,MAAA,YAAY,CAAC,OAAb,GAAuB;AACrB,QAAA,KAAK,EAAE,QADc;AAErB,QAAA,OAAO,EAAE,UAFY;AAGrB,QAAA,SAAS,EAAE;AAHU,OAAvB;AAKD;;AAED,IAAA,iBAAA,CAAA,yBAAA,CAA0B,MAAK;AAC7B,MAAA,QAAQ,CAAC,OAAT,GAAmB,KAAK,CAAC,KAAzB;AACA,MAAA,UAAU,CAAC,OAAX,IAAsB,CAAtB;AAEA,MAAA,WAAA,CAAA,wBAAA,CAAgB,WAAA,CAAA,uBAAhB,EAAgC,MAAK;AAClC,QAAA,YAAY,CAAC,OAAb,CAA6C,SAA7C,CAAuD,OAAvD,CAA+D,QAAQ,IAAG;AACzE,UAAA,QAAQ,CAAC,CAAC,UAAU,CAAC,OAAZ,EAAqB,KAAK,CAAC,KAA3B,CAAD,CAAR;AACD,SAFA;AAGF,OAJD;AAKD,KATD,EASG,CAAC,KAAK,CAAC,KAAP,CATH;AAWA,WAAO,KAAK,CAAC,aAAN,CAAoB,QAApB,EAA8B;AAAE,MAAA,KAAK,EAAE,YAAY,CAAC;AAAtB,KAA9B,EAA+D,KAAK,CAAC,QAArE,CAAP;AACD,GA7BD;AA+BA;;;AACA,MAAI,OAAO,CAAC,GAAR,CAAY,QAAZ,KAAyB,YAA7B,EAA2C;AACzC,IAAA,QAAQ,CAAC,WAAT,GAAuB,0BAAvB;AACD;;AAED,SAAQ,QAAR;AACD,CAtCD;;AAwCO,MAAM,aAAa,GAAW,YAAR,IAA+C;AAC1E,QAAM,OAAO,GAAG,KAAK,CAAC,aAAN,CAAyC;AACvD,IAAA,KAAK,EAAE;AAAE,MAAA,OAAO,EAAE;AAAX,KADgD;AAEvD,IAAA,OAAO,EAAE;AAAE,MAAA,OAAO,EAAE,CAAC;AAAZ,KAF8C;AAGvD,IAAA,SAAS,EAAE;AAH4C,GAAzC,CAAhB;AAMA,EAAA,OAAO,CAAC,QAAR,GAAmB,cAAc,CAAQ,OAAO,CAAC,QAAhB,CAAjC,CAP0E,CAS1E;;AACA,SAAS,OAAsC,CAAC,QAAhD;AAEA,SAAQ,OAAR;AACD,CAbM;;AAAM,OAAA,CAAA,aAAA,GAAa,aAAb","sourcesContent":["import { useIsomorphicLayoutEffect } from '@fluentui/react-utilities';\nimport * as React from 'react';\nimport { unstable_NormalPriority as NormalPriority, unstable_runWithPriority as runWithPriority } from 'scheduler';\n\nimport { Context, ContextValue } from './types';\n\nconst createProvider = <Value>(Original: React.Provider<ContextValue<Value>>) => {\n const Provider: React.FC<React.ProviderProps<Value>> = props => {\n // Holds an actual \"props.value\"\n const valueRef = React.useRef(props.value);\n // Used to sync context updates and avoid stale values, can be considered as render/effect counter of Provider.\n const versionRef = React.useRef(0);\n\n // A stable object, is used to avoid context updates via mutation of its values.\n const contextValue = React.useRef<ContextValue<Value>>();\n\n if (!contextValue.current) {\n contextValue.current = {\n value: valueRef,\n version: versionRef,\n listeners: [],\n };\n }\n\n useIsomorphicLayoutEffect(() => {\n valueRef.current = props.value;\n versionRef.current += 1;\n\n runWithPriority(NormalPriority, () => {\n (contextValue.current as ContextValue<Value>).listeners.forEach(listener => {\n listener([versionRef.current, props.value]);\n });\n });\n }, [props.value]);\n\n return React.createElement(Original, { value: contextValue.current }, props.children);\n };\n\n /* istanbul ignore else */\n if (process.env.NODE_ENV !== 'production') {\n Provider.displayName = 'ContextSelector.Provider';\n }\n\n return (Provider as unknown) as React.Provider<ContextValue<Value>>;\n};\n\nexport const createContext = <Value>(defaultValue: Value): Context<Value> => {\n const context = React.createContext<ContextValue<Value>>({\n value: { current: defaultValue },\n version: { current: -1 },\n listeners: [],\n });\n\n context.Provider = createProvider<Value>(context.Provider);\n\n // We don't support Consumer API\n delete ((context as unknown) as Context<Value>).Consumer;\n\n return (context as unknown) as Context<Value>;\n};\n"],"sourceRoot":"../src/"}
@@ -0,0 +1,4 @@
1
+ export { createContext } from './createContext';
2
+ export { useContextSelector } from './useContextSelector';
3
+ export { useHasParentContext } from './useHasParentContext';
4
+ export * from './types';
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useHasParentContext = exports.useContextSelector = exports.createContext = void 0;
7
+
8
+ const tslib_1 = /*#__PURE__*/require("tslib");
9
+
10
+ var createContext_1 = /*#__PURE__*/require("./createContext");
11
+
12
+ Object.defineProperty(exports, "createContext", {
13
+ enumerable: true,
14
+ get: function () {
15
+ return createContext_1.createContext;
16
+ }
17
+ });
18
+
19
+ var useContextSelector_1 = /*#__PURE__*/require("./useContextSelector");
20
+
21
+ Object.defineProperty(exports, "useContextSelector", {
22
+ enumerable: true,
23
+ get: function () {
24
+ return useContextSelector_1.useContextSelector;
25
+ }
26
+ });
27
+
28
+ var useHasParentContext_1 = /*#__PURE__*/require("./useHasParentContext");
29
+
30
+ Object.defineProperty(exports, "useHasParentContext", {
31
+ enumerable: true,
32
+ get: function () {
33
+ return useHasParentContext_1.useHasParentContext;
34
+ }
35
+ });
36
+
37
+ tslib_1.__exportStar(require("./types"), exports);
38
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["index.ts"],"names":[],"mappings":";;;;;;;;;AAAA,IAAA,eAAA,gBAAA,OAAA,CAAA,iBAAA,CAAA;;AAAS,MAAA,CAAA,cAAA,CAAA,OAAA,EAAA,eAAA,EAAA;AAAA,EAAA,UAAA,EAAA,IAAA;AAAA,EAAA,GAAA,EAAA,YAAA;AAAA,WAAA,eAAA,CAAA,aAAA;AAAa;AAAb,CAAA;;AACT,IAAA,oBAAA,gBAAA,OAAA,CAAA,sBAAA,CAAA;;AAAS,MAAA,CAAA,cAAA,CAAA,OAAA,EAAA,oBAAA,EAAA;AAAA,EAAA,UAAA,EAAA,IAAA;AAAA,EAAA,GAAA,EAAA,YAAA;AAAA,WAAA,oBAAA,CAAA,kBAAA;AAAkB;AAAlB,CAAA;;AACT,IAAA,qBAAA,gBAAA,OAAA,CAAA,uBAAA,CAAA;;AAAS,MAAA,CAAA,cAAA,CAAA,OAAA,EAAA,qBAAA,EAAA;AAAA,EAAA,UAAA,EAAA,IAAA;AAAA,EAAA,GAAA,EAAA,YAAA;AAAA,WAAA,qBAAA,CAAA,mBAAA;AAAmB;AAAnB,CAAA;;AACT,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,SAAA,CAAA,EAAA,OAAA","sourcesContent":["export { createContext } from './createContext';\nexport { useContextSelector } from './useContextSelector';\nexport { useHasParentContext } from './useHasParentContext';\nexport * from './types';\n"],"sourceRoot":"../src/"}
@@ -0,0 +1,19 @@
1
+ import * as React from 'react';
2
+ export declare type Context<Value> = React.Context<Value> & {
3
+ Provider: React.FC<React.ProviderProps<Value>>;
4
+ Consumer: never;
5
+ };
6
+ export declare type ContextSelector<Value, SelectedValue> = (value: Value) => SelectedValue;
7
+ export declare type ContextVersion = number;
8
+ export declare type ContextValue<Value> = {
9
+ /** Holds a set of subscribers from components. */
10
+ listeners: ((payload: readonly [ContextVersion, Value]) => void)[];
11
+ /** Holds an actual value of React's context that will be propagated down for computations. */
12
+ value: React.MutableRefObject<Value>;
13
+ /** A version field is used to sync a context value and consumers. */
14
+ version: React.MutableRefObject<ContextVersion>;
15
+ };
16
+ export declare type ContextValues<Value> = ContextValue<Value> & {
17
+ /** List of listners to publish changes */
18
+ listeners: ((payload: readonly [ContextVersion, Record<string, Value>]) => void)[];
19
+ };
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","sourceRoot":"../src/"}
@@ -0,0 +1,7 @@
1
+ import { Context, ContextSelector } from './types';
2
+ /**
3
+ * This hook returns context selected value by selector.
4
+ * It will only accept context created by `createContext`.
5
+ * It will trigger re-render if only the selected value is referencially changed.
6
+ */
7
+ export declare const useContextSelector: <Value, SelectedValue>(context: Context<Value>, selector: ContextSelector<Value, SelectedValue>) => SelectedValue;
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useContextSelector = void 0;
7
+
8
+ const react_utilities_1 = /*#__PURE__*/require("@fluentui/react-utilities");
9
+
10
+ const React = /*#__PURE__*/require("react");
11
+ /**
12
+ * This hook returns context selected value by selector.
13
+ * It will only accept context created by `createContext`.
14
+ * It will trigger re-render if only the selected value is referencially changed.
15
+ */
16
+
17
+
18
+ const useContextSelector = (context, selector) => {
19
+ const contextValue = React.useContext(context);
20
+ const {
21
+ value: {
22
+ current: value
23
+ },
24
+ version: {
25
+ current: version
26
+ },
27
+ listeners
28
+ } = contextValue;
29
+ const selected = selector(value);
30
+ const [state, dispatch] = React.useReducer((prevState, payload) => {
31
+ if (!payload) {
32
+ // early bail out when is dispatched during render
33
+ return [value, selected];
34
+ }
35
+
36
+ if (payload[0] <= version) {
37
+ if (objectIs(prevState[1], selected)) {
38
+ return prevState; // bail out
39
+ }
40
+
41
+ return [value, selected];
42
+ }
43
+
44
+ try {
45
+ if (objectIs(prevState[0], payload[1])) {
46
+ return prevState; // do not update
47
+ }
48
+
49
+ const nextSelected = selector(payload[1]);
50
+
51
+ if (objectIs(prevState[1], nextSelected)) {
52
+ return prevState; // do not update
53
+ }
54
+
55
+ return [payload[1], nextSelected];
56
+ } catch (e) {// ignored (stale props or some other reason)
57
+ } // explicitly spread to enforce typing
58
+
59
+
60
+ return [prevState[0], prevState[1]]; // schedule update
61
+ }, [value, selected]);
62
+
63
+ if (!objectIs(state[1], selected)) {
64
+ // schedule re-render
65
+ // this is safe because it's self contained
66
+ dispatch(undefined);
67
+ }
68
+
69
+ react_utilities_1.useIsomorphicLayoutEffect(() => {
70
+ listeners.push(dispatch);
71
+ return () => {
72
+ const index = listeners.indexOf(dispatch);
73
+ listeners.splice(index, 1);
74
+ };
75
+ }, [listeners]);
76
+ return state[1];
77
+ };
78
+
79
+ exports.useContextSelector = useContextSelector;
80
+ /**
81
+ * inlined Object.is polyfill to avoid requiring consumers ship their own
82
+ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
83
+ */
84
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
85
+
86
+ function is(x, y) {
87
+ return x === y && (x !== 0 || 1 / x === 1 / y) || x !== x && y !== y // eslint-disable-line no-self-compare
88
+ ;
89
+ } // eslint-disable-next-line @typescript-eslint/no-explicit-any
90
+
91
+
92
+ const objectIs = // eslint-disable-next-line @typescript-eslint/ban-ts-comment
93
+ // @ts-ignore fallback to native if it exists (not in IE11)
94
+ typeof Object.is === 'function' ? Object.is : is;
95
+ //# sourceMappingURL=useContextSelector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["useContextSelector.ts"],"names":[],"mappings":";;;;;;;AAAA,MAAA,iBAAA,gBAAA,OAAA,CAAA,2BAAA,CAAA;;AACA,MAAA,KAAA,gBAAA,OAAA,CAAA,OAAA,CAAA;AAaA;;;;AAIG;;;AACI,MAAM,kBAAkB,GAAG,CAChC,OADgC,EAEhC,QAFgC,KAGf;AACjB,QAAM,YAAY,GAAG,KAAK,CAAC,UAAN,CAAkB,OAAlB,CAArB;AAEA,QAAM;AACJ,IAAA,KAAK,EAAE;AAAE,MAAA,OAAO,EAAE;AAAX,KADH;AAEJ,IAAA,OAAO,EAAE;AAAE,MAAA,OAAO,EAAE;AAAX,KAFL;AAGJ,IAAA;AAHI,MAIF,YAJJ;AAKA,QAAM,QAAQ,GAAG,QAAQ,CAAC,KAAD,CAAzB;AAEA,QAAM,CAAC,KAAD,EAAQ,QAAR,IAAoB,KAAK,CAAC,UAAN,CACxB,CACE,SADF,EAEE,OAFF,KAKqC;AACnC,QAAI,CAAC,OAAL,EAAc;AACZ;AACA,aAAO,CAAC,KAAD,EAAQ,QAAR,CAAP;AACD;;AAED,QAAI,OAAO,CAAC,CAAD,CAAP,IAAc,OAAlB,EAA2B;AACzB,UAAI,QAAQ,CAAC,SAAS,CAAC,CAAD,CAAV,EAAe,QAAf,CAAZ,EAAsC;AACpC,eAAO,SAAP,CADoC,CAClB;AACnB;;AAED,aAAO,CAAC,KAAD,EAAQ,QAAR,CAAP;AACD;;AAED,QAAI;AACF,UAAI,QAAQ,CAAC,SAAS,CAAC,CAAD,CAAV,EAAe,OAAO,CAAC,CAAD,CAAtB,CAAZ,EAAwC;AACtC,eAAO,SAAP,CADsC,CACpB;AACnB;;AAED,YAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAD,CAAR,CAA7B;;AAEA,UAAI,QAAQ,CAAC,SAAS,CAAC,CAAD,CAAV,EAAe,YAAf,CAAZ,EAA0C;AACxC,eAAO,SAAP,CADwC,CACtB;AACnB;;AAED,aAAO,CAAC,OAAO,CAAC,CAAD,CAAR,EAAa,YAAb,CAAP;AACD,KAZD,CAYE,OAAO,CAAP,EAAU,CACV;AACD,KA5BkC,CA8BnC;;;AACA,WAAO,CAAC,SAAS,CAAC,CAAD,CAAV,EAAe,SAAS,CAAC,CAAD,CAAxB,CAAP,CA/BmC,CA+BW;AAC/C,GAtCuB,EAuCxB,CAAC,KAAD,EAAQ,QAAR,CAvCwB,CAA1B;;AA0CA,MAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAD,CAAN,EAAW,QAAX,CAAb,EAAmC;AACjC;AACA;AACA,IAAA,QAAQ,CAAC,SAAD,CAAR;AACD;;AAED,EAAA,iBAAA,CAAA,yBAAA,CAA0B,MAAK;AAC7B,IAAA,SAAS,CAAC,IAAV,CAAe,QAAf;AAEA,WAAO,MAAK;AACV,YAAM,KAAK,GAAG,SAAS,CAAC,OAAV,CAAkB,QAAlB,CAAd;AACA,MAAA,SAAS,CAAC,MAAV,CAAiB,KAAjB,EAAwB,CAAxB;AACD,KAHD;AAID,GAPD,EAOG,CAAC,SAAD,CAPH;AASA,SAAO,KAAK,CAAC,CAAD,CAAZ;AACD,CAvEM;;AAAM,OAAA,CAAA,kBAAA,GAAkB,kBAAlB;AAyEb;;;AAGG;AACH;;AACA,SAAS,EAAT,CAAY,CAAZ,EAAoB,CAApB,EAA0B;AACxB,SACG,CAAC,KAAK,CAAN,KAAY,CAAC,KAAK,CAAN,IAAW,IAAI,CAAJ,KAAU,IAAI,CAArC,CAAD,IAA8C,CAAC,KAAK,CAAN,IAAW,CAAC,KAAK,CADjE,CACoE;AADpE;AAGD,C,CAED;;;AACA,MAAM,QAAQ,GACZ;AACA;AACA,OAAO,MAAM,CAAC,EAAd,KAAqB,UAArB,GAAkC,MAAM,CAAC,EAAzC,GAA8C,EAHhD","sourcesContent":["import { useIsomorphicLayoutEffect } from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nimport { Context, ContextSelector, ContextValue, ContextVersion } from './types';\n\n/**\n * Narrowing React.Reducer type to be more easily usable below.\n * No need to export this as it's for internal reducer usage.\n */\ntype ContextReducer<Value, SelectedValue> = React.Reducer<\n readonly [Value, SelectedValue],\n undefined | readonly [ContextVersion, Value]\n>;\n\n/**\n * This hook returns context selected value by selector.\n * It will only accept context created by `createContext`.\n * It will trigger re-render if only the selected value is referencially changed.\n */\nexport const useContextSelector = <Value, SelectedValue>(\n context: Context<Value>,\n selector: ContextSelector<Value, SelectedValue>,\n): SelectedValue => {\n const contextValue = React.useContext((context as unknown) as Context<ContextValue<Value>>);\n\n const {\n value: { current: value },\n version: { current: version },\n listeners,\n } = contextValue;\n const selected = selector(value);\n\n const [state, dispatch] = React.useReducer<ContextReducer<Value, SelectedValue>>(\n (\n prevState: readonly [Value /* contextValue */, SelectedValue /* selector(value) */],\n payload:\n | undefined // undefined from render below\n | readonly [ContextVersion, Value], // from provider effect\n ): readonly [Value, SelectedValue] => {\n if (!payload) {\n // early bail out when is dispatched during render\n return [value, selected] as const;\n }\n\n if (payload[0] <= version) {\n if (objectIs(prevState[1], selected)) {\n return prevState; // bail out\n }\n\n return [value, selected] as const;\n }\n\n try {\n if (objectIs(prevState[0], payload[1])) {\n return prevState; // do not update\n }\n\n const nextSelected = selector(payload[1]);\n\n if (objectIs(prevState[1], nextSelected)) {\n return prevState; // do not update\n }\n\n return [payload[1], nextSelected] as const;\n } catch (e) {\n // ignored (stale props or some other reason)\n }\n\n // explicitly spread to enforce typing\n return [prevState[0], prevState[1]] as const; // schedule update\n },\n [value, selected] as const,\n );\n\n if (!objectIs(state[1], selected)) {\n // schedule re-render\n // this is safe because it's self contained\n dispatch(undefined);\n }\n\n useIsomorphicLayoutEffect(() => {\n listeners.push(dispatch);\n\n return () => {\n const index = listeners.indexOf(dispatch);\n listeners.splice(index, 1);\n };\n }, [listeners]);\n\n return state[1] as SelectedValue;\n};\n\n/**\n * inlined Object.is polyfill to avoid requiring consumers ship their own\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction is(x: any, y: any) {\n return (\n (x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y) // eslint-disable-line no-self-compare\n );\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst objectIs: (x: any, y: any) => boolean =\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore fallback to native if it exists (not in IE11)\n typeof Object.is === 'function' ? Object.is : is;\n"],"sourceRoot":"../src/"}
@@ -0,0 +1,9 @@
1
+ import { Context } from './types';
2
+ /**
3
+ * Utility hook for contexts created by react-context-selector to determine if a parent context exists
4
+ * WARNING: This hook will not work for native React contexts
5
+ *
6
+ * @param context - context created by react-context-selector
7
+ * @returns whether the hook is wrapped by a parent context
8
+ */
9
+ export declare function useHasParentContext<Value>(context: Context<Value>): boolean;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useHasParentContext = void 0;
7
+
8
+ const React = /*#__PURE__*/require("react");
9
+ /**
10
+ * Utility hook for contexts created by react-context-selector to determine if a parent context exists
11
+ * WARNING: This hook will not work for native React contexts
12
+ *
13
+ * @param context - context created by react-context-selector
14
+ * @returns whether the hook is wrapped by a parent context
15
+ */
16
+
17
+
18
+ function useHasParentContext(context) {
19
+ const contextValue = React.useContext(context);
20
+
21
+ if (contextValue.version) {
22
+ return contextValue.version.current !== -1;
23
+ }
24
+
25
+ return false;
26
+ }
27
+
28
+ exports.useHasParentContext = useHasParentContext;
29
+ //# sourceMappingURL=useHasParentContext.js.map