@cleanweb/oore 1.2.2-alpha.2 → 1.2.2-alpha.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/build/helpers/rerender.d.ts +20 -1
- package/build/helpers/rerender.js +26 -21
- package/build/slots/hook.d.ts +10 -0
- package/build/slots/hook.js +38 -12
- package/build/slots/types.d.ts +108 -4
- package/package.json +1 -1
|
@@ -1,5 +1,24 @@
|
|
|
1
|
+
interface ICountRef {
|
|
2
|
+
current: number;
|
|
3
|
+
}
|
|
4
|
+
interface IRefresherReturn {
|
|
5
|
+
/** The last render count just before the rerender was triggered. */
|
|
6
|
+
previousCount: number;
|
|
7
|
+
/** A {@link useRef | RefObject} whose `current` property always has the latest render count. */
|
|
8
|
+
latestCountRef: ICountRef;
|
|
9
|
+
}
|
|
10
|
+
interface IRefresher {
|
|
11
|
+
(): Promise<IRefresherReturn>;
|
|
12
|
+
}
|
|
13
|
+
interface IUseRender {
|
|
14
|
+
(): IRefresher & {
|
|
15
|
+
/** The number of times this instance of the component has been (re)rendered. */
|
|
16
|
+
currentCount: number;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
1
19
|
/**
|
|
2
20
|
* Returns a function that can be called to manually trigger
|
|
3
21
|
* a rerender of your component.
|
|
4
22
|
*/
|
|
5
|
-
export declare const useRerender:
|
|
23
|
+
export declare const useRerender: IUseRender;
|
|
24
|
+
export {};
|
|
@@ -1,37 +1,42 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.useRerender = void 0;
|
|
4
|
-
var mount_state_1 = require("../helpers/mount-state");
|
|
5
4
|
var react_1 = require("react");
|
|
5
|
+
var mount_state_1 = require("../helpers/mount-state");
|
|
6
|
+
;
|
|
6
7
|
/**
|
|
7
8
|
* Returns a function that can be called to manually trigger
|
|
8
9
|
* a rerender of your component.
|
|
9
10
|
*/
|
|
10
11
|
var useRerender = function () {
|
|
11
12
|
var isMounted = (0, mount_state_1.useMountState)();
|
|
12
|
-
var
|
|
13
|
-
var
|
|
13
|
+
var renderCount = (0, react_1.useRef)(0);
|
|
14
|
+
var _a = (0, react_1.useState)(renderCount.current), forceRerender = _a[1];
|
|
15
|
+
renderCount.current++;
|
|
16
|
+
var rerender = (0, react_1.useCallback)(function () {
|
|
17
|
+
var resolve;
|
|
18
|
+
var promise = new Promise(function (_r) { return resolve = _r; });
|
|
14
19
|
var execute = function () {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
20
|
+
forceRerender(renderCount.current);
|
|
21
|
+
resolve({
|
|
22
|
+
previousCount: renderCount.current,
|
|
23
|
+
latestCountRef: renderCount,
|
|
24
|
+
});
|
|
18
25
|
};
|
|
19
|
-
if (isMounted())
|
|
26
|
+
if (isMounted())
|
|
20
27
|
execute();
|
|
21
|
-
|
|
28
|
+
else {
|
|
29
|
+
setTimeout(function () {
|
|
30
|
+
if (isMounted())
|
|
31
|
+
execute();
|
|
32
|
+
else
|
|
33
|
+
console.log('Cannot rerender an unmounted component.');
|
|
34
|
+
}, 1000);
|
|
22
35
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
else {
|
|
29
|
-
console.log('Cannot rerender an unmounted component.');
|
|
30
|
-
}
|
|
31
|
-
}, 1000);
|
|
32
|
-
}); }, [forceRerender]);
|
|
33
|
-
// @ts-expect-error
|
|
34
|
-
rerender.key = key;
|
|
35
|
-
return rerender;
|
|
36
|
+
return promise;
|
|
37
|
+
}, [forceRerender, renderCount]);
|
|
38
|
+
var refresher = function () { return rerender(); };
|
|
39
|
+
refresher.currentCount = renderCount.current;
|
|
40
|
+
return refresher;
|
|
36
41
|
};
|
|
37
42
|
exports.useRerender = useRerender;
|
package/build/slots/hook.d.ts
CHANGED
|
@@ -5,5 +5,15 @@ interface IGetSlotName {
|
|
|
5
5
|
(TargetComponent: PotentialSlotComponent, child?: ReactElement): string | undefined;
|
|
6
6
|
}
|
|
7
7
|
export declare const getComponentSlotName: IGetSlotName;
|
|
8
|
+
/**
|
|
9
|
+
* Groups `children` prop into predefined slots.
|
|
10
|
+
*
|
|
11
|
+
* @returns A {@link TUseSlotsResult} array,
|
|
12
|
+
* which includes a `slotNodes` object that maps the keys from
|
|
13
|
+
* the predefined {@link slotComponents} object to the corresponding
|
|
14
|
+
* React node(s) that were rendered for that slot.
|
|
15
|
+
*
|
|
16
|
+
* @see {@link SlotComponent} for more on how to use the returned slot nodes.
|
|
17
|
+
*/
|
|
8
18
|
export declare const useSlots: IUseSlots;
|
|
9
19
|
export type { SlotNamedComponent, SlottedComponent, TSlotsRecord, PotentialSlotComponent, } from './types';
|
package/build/slots/hook.js
CHANGED
|
@@ -1,4 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
3
26
|
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
4
27
|
if (ar || !(i in from)) {
|
|
@@ -8,13 +31,10 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
8
31
|
}
|
|
9
32
|
return to.concat(ar || Array.prototype.slice.call(from));
|
|
10
33
|
};
|
|
11
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
-
};
|
|
14
34
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
35
|
exports.useSlots = exports.getComponentSlotName = exports.isElementChild = void 0;
|
|
16
36
|
var errors_1 = require("../helpers/errors");
|
|
17
|
-
var react_1 =
|
|
37
|
+
var react_1 = __importStar(require("react"));
|
|
18
38
|
var isElementChild = function (child) {
|
|
19
39
|
if (child && typeof child === 'object' && 'type' in child) {
|
|
20
40
|
return true;
|
|
@@ -45,9 +65,18 @@ var getComponentSlotName = function (TargetComponent, child) {
|
|
|
45
65
|
return undefined;
|
|
46
66
|
};
|
|
47
67
|
exports.getComponentSlotName = getComponentSlotName;
|
|
68
|
+
/**
|
|
69
|
+
* Groups `children` prop into predefined slots.
|
|
70
|
+
*
|
|
71
|
+
* @returns A {@link TUseSlotsResult} array,
|
|
72
|
+
* which includes a `slotNodes` object that maps the keys from
|
|
73
|
+
* the predefined {@link slotComponents} object to the corresponding
|
|
74
|
+
* React node(s) that were rendered for that slot.
|
|
75
|
+
*
|
|
76
|
+
* @see {@link SlotComponent} for more on how to use the returned slot nodes.
|
|
77
|
+
*/
|
|
48
78
|
var useSlots = function (children, slotComponents, requiredSlotAliases) {
|
|
49
|
-
var
|
|
50
|
-
var slotsAliasLookup = useMemo(function () {
|
|
79
|
+
var slotsAliasLookup = (0, react_1.useMemo)(function () {
|
|
51
80
|
var entries = Object.entries(slotComponents);
|
|
52
81
|
var aliasLookup = {};
|
|
53
82
|
entries.forEach(function (_a) {
|
|
@@ -61,7 +90,7 @@ var useSlots = function (children, slotComponents, requiredSlotAliases) {
|
|
|
61
90
|
});
|
|
62
91
|
return aliasLookup;
|
|
63
92
|
}, [slotComponents]);
|
|
64
|
-
var result = useMemo(function () {
|
|
93
|
+
var result = (0, react_1.useMemo)(function () {
|
|
65
94
|
var slotNodes = {};
|
|
66
95
|
var unmatchedChildren = [];
|
|
67
96
|
var invalidChildren = [];
|
|
@@ -91,14 +120,11 @@ var useSlots = function (children, slotComponents, requiredSlotAliases) {
|
|
|
91
120
|
}
|
|
92
121
|
}
|
|
93
122
|
if (slotAlias) {
|
|
94
|
-
if (
|
|
95
|
-
slotNodes[slotAlias] = child;
|
|
96
|
-
}
|
|
97
|
-
else if (Array.isArray(slotNodes[slotAlias])) {
|
|
123
|
+
if (slotNodes[slotAlias]) {
|
|
98
124
|
slotNodes[slotAlias].push(child);
|
|
99
125
|
}
|
|
100
126
|
else {
|
|
101
|
-
slotNodes[slotAlias] = [
|
|
127
|
+
slotNodes[slotAlias] = [child];
|
|
102
128
|
}
|
|
103
129
|
}
|
|
104
130
|
else
|
package/build/slots/types.d.ts
CHANGED
|
@@ -2,6 +2,12 @@ import type { ReactElement, ReactNode, JSXElementConstructor } from 'react';
|
|
|
2
2
|
export type TComponent = JSXElementConstructor<any>;
|
|
3
3
|
export type TSlotName = keyof any;
|
|
4
4
|
export type TSlotAlias = keyof any;
|
|
5
|
+
/**
|
|
6
|
+
* A map of slot aliases to actual {@link SlotComponent}s.
|
|
7
|
+
*
|
|
8
|
+
* The `useSlots` hook will create a corresponding key for
|
|
9
|
+
* each alias in this record to hold any `ReactNode`s rendered for that slot.
|
|
10
|
+
*/
|
|
5
11
|
export type TSlotsRecord<TKey extends TSlotAlias = TSlotAlias> = {
|
|
6
12
|
[Key in TKey]: string | SlotComponent;
|
|
7
13
|
};
|
|
@@ -11,21 +17,119 @@ export type DisplayNamedComponent<TComponentArg extends TComponent = TComponent,
|
|
|
11
17
|
export type SlotNamedComponent<TComponentArg extends TComponent = TComponent, TSlotNameArg extends TSlotName = TSlotName> = TComponentArg & {
|
|
12
18
|
slotName: TSlotNameArg;
|
|
13
19
|
};
|
|
20
|
+
/**
|
|
21
|
+
* A child component used to insert content into a specific slot in the parent component.
|
|
22
|
+
* This can either be a string, or a React component with a `slotName` property.
|
|
23
|
+
* If `slotName` is missing `displayName` will be used as a fallback.
|
|
24
|
+
*
|
|
25
|
+
* ### Strings
|
|
26
|
+
* For strings, they are treated by React a native tags. This lets you use custom strings
|
|
27
|
+
* as if you are rendering a custom Web Component, or simply handle specific HTML tags in a specific way.
|
|
28
|
+
*
|
|
29
|
+
* If using a custom string, you will want to handle it in the parent component by simply forwarding the slot's
|
|
30
|
+
* props to an actual element of your choice.
|
|
31
|
+
*
|
|
32
|
+
* So consumers may pass the following as `children`.
|
|
33
|
+
* ```jsx
|
|
34
|
+
* <option-slot>Click</option-slot>
|
|
35
|
+
* ```
|
|
36
|
+
* and you can map that to
|
|
37
|
+
* ```jsx
|
|
38
|
+
* <button
|
|
39
|
+
* {...slotNodes.Option.props}
|
|
40
|
+
* type="button"
|
|
41
|
+
* />
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* ### React Components
|
|
45
|
+
* For slot components that are actual React components, the parent can simply
|
|
46
|
+
* render the slot node directly.
|
|
47
|
+
*
|
|
48
|
+
* So consumers may pass the following as `children`.
|
|
49
|
+
* ```jsx
|
|
50
|
+
* <Parent.slots.Content>
|
|
51
|
+
* Some awesome content.
|
|
52
|
+
* </Parent.slots.Content>
|
|
53
|
+
* ```
|
|
54
|
+
* and you can map that to
|
|
55
|
+
* ```jsx
|
|
56
|
+
* return <>
|
|
57
|
+
* <h1>Title</h1>
|
|
58
|
+
* {slotNodes.Content}
|
|
59
|
+
* <footer>Powered by oore</footer>
|
|
60
|
+
* </>
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* This means `Parent.slots.Content` must be defined as a proper React component
|
|
64
|
+
* and is solely responsible for doing something with the `"Some awesome content."`
|
|
65
|
+
* which was passed into it as children.
|
|
66
|
+
*
|
|
67
|
+
* This is unlike the string version where the parent component
|
|
68
|
+
* extracts the props passed to the slot and handles
|
|
69
|
+
* what the slot actually renders.
|
|
70
|
+
*/
|
|
14
71
|
export type SlotComponent<TComponentArg extends TComponent = TComponent> = (SlotNamedComponent<TComponentArg> | DisplayNamedComponent<TComponentArg>) & {
|
|
15
72
|
isRequiredSlot?: boolean;
|
|
16
73
|
};
|
|
74
|
+
/**
|
|
75
|
+
* A parent component which accepts content that can be grouped into predefined slots.
|
|
76
|
+
* By convention, it should have a `slots` property which is a {@link TSlotsRecord}.
|
|
77
|
+
*
|
|
78
|
+
* This allows consumers access the predefined slot components
|
|
79
|
+
* directly from the parent component itself,
|
|
80
|
+
* through an alias that is easy to remember.
|
|
81
|
+
*/
|
|
17
82
|
export type SlottedComponent<TComponentArg extends TComponent = TComponent, TSlotAliasArg extends TSlotAlias = TSlotAlias, TSlotsRecordArg extends TSlotsRecord<TSlotAliasArg> = TSlotsRecord<TSlotAliasArg>> = TComponentArg & {
|
|
18
|
-
Slots: TSlotsRecordArg;
|
|
83
|
+
[Key in 'Slots' | 'slots']: TSlotsRecordArg;
|
|
19
84
|
};
|
|
85
|
+
/**
|
|
86
|
+
* A record of slot aliases mapped to the corresponding `ReactNode`(s)
|
|
87
|
+
* to be rendered for that slot.
|
|
88
|
+
*/
|
|
20
89
|
export type TSlotNodes<TSlotAliasArg extends TSlotAlias> = {
|
|
21
|
-
[Key in TSlotAliasArg]?:
|
|
90
|
+
[Key in TSlotAliasArg]?: Array<ReactElement<any>>;
|
|
22
91
|
};
|
|
23
92
|
export type TUseSlotsResult<TSlotAliasArg extends TSlotAlias = TSlotAlias> = Readonly<[
|
|
24
|
-
|
|
93
|
+
/**
|
|
94
|
+
* A record of slot aliases to their corresponding React nodes.
|
|
95
|
+
* Each alias maps to an array of one or more React nodes that were passed
|
|
96
|
+
* as children for that slot.
|
|
97
|
+
*
|
|
98
|
+
* If a slot was not rendered in `children`, it's alias will be `undefined` in this object.
|
|
99
|
+
*/
|
|
100
|
+
slotNodes: TSlotNodes<TSlotAliasArg>,
|
|
101
|
+
/**
|
|
102
|
+
* Valid React nodes passed as children which did not match any of the
|
|
103
|
+
* predefined slots.
|
|
104
|
+
*/
|
|
25
105
|
unmatchedChildren: ReactNode[],
|
|
106
|
+
/**
|
|
107
|
+
* Items included in `children` which are not valid React nodes.
|
|
108
|
+
*/
|
|
26
109
|
invalidChildren: any[]
|
|
27
110
|
]>;
|
|
28
111
|
export interface IUseSlots {
|
|
29
|
-
<TSlotAliasArg extends TSlotAlias = TSlotAlias>(
|
|
112
|
+
<TSlotAliasArg extends TSlotAlias = TSlotAlias>(
|
|
113
|
+
/**
|
|
114
|
+
* Your component's `children` prop.
|
|
115
|
+
* The nodes it contains will be categorized and
|
|
116
|
+
* grouped according to the predefined {@link slotComponents}.
|
|
117
|
+
*/
|
|
118
|
+
children: ReactNode,
|
|
119
|
+
/**
|
|
120
|
+
* A map of slot aliases to their corresponding {@link SlotComponent}.
|
|
121
|
+
* React nodes passed as children will be compared with the components
|
|
122
|
+
* in this record to generate the categorized `slotNodes` object.
|
|
123
|
+
*/
|
|
124
|
+
slotComponents: TSlotsRecord<TSlotAliasArg>,
|
|
125
|
+
/**
|
|
126
|
+
* An array of aliases to be treated as required. If a slot's
|
|
127
|
+
* alias is in this array, the slot is treated as required.
|
|
128
|
+
*
|
|
129
|
+
* If no ReactNode is found in {@link children | `children`}
|
|
130
|
+
* for a required slot, an error will be thrown in development.
|
|
131
|
+
* However in production this is softened to just a console warning.
|
|
132
|
+
*/
|
|
133
|
+
requiredSlotAliases?: TSlotAliasArg[]): TUseSlotsResult<TSlotAliasArg>;
|
|
30
134
|
}
|
|
31
135
|
export type PotentialSlotComponent = string | SlotComponent | TComponent;
|
package/package.json
CHANGED