@cleanweb/oore 2.0.0-alpha.12 → 2.0.0-alpha.14
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/slots/hook.d.ts +3 -2
- package/build/slots/hook.js +19 -13
- package/build/slots/types.d.ts +36 -28
- package/package.json +1 -1
package/build/slots/hook.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type { ReactElement, ReactNode } from 'react';
|
|
1
|
+
import type { ReactElement, ReactNode, ReactPortal } from 'react';
|
|
2
2
|
import type { IUseSlots, PotentialSlotComponent } from './types';
|
|
3
3
|
export declare const isElementChild: (child: ReactNode) => child is ReactElement<any, any>;
|
|
4
4
|
interface IGetSlotName {
|
|
5
5
|
(TargetComponent: PotentialSlotComponent, child?: ReactElement): string | undefined;
|
|
6
6
|
}
|
|
7
7
|
export declare const getComponentSlotName: IGetSlotName;
|
|
8
|
+
export declare const isPortalChild: (child: ReactNode) => child is ReactPortal;
|
|
8
9
|
/**
|
|
9
10
|
* Groups `children` prop into predefined slots.
|
|
10
11
|
*
|
|
@@ -16,4 +17,4 @@ export declare const getComponentSlotName: IGetSlotName;
|
|
|
16
17
|
* @see {@link SlotComponent} for more on how to use the returned slot nodes.
|
|
17
18
|
*/
|
|
18
19
|
export declare const useSlots: IUseSlots;
|
|
19
|
-
export type {
|
|
20
|
+
export type { SlottedComponent, TSlotsRecord, SlotComponent, PotentialSlotComponent, } from './types';
|
package/build/slots/hook.js
CHANGED
|
@@ -32,7 +32,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
32
32
|
return to.concat(ar || Array.prototype.slice.call(from));
|
|
33
33
|
};
|
|
34
34
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
-
exports.useSlots = exports.getComponentSlotName = exports.isElementChild = void 0;
|
|
35
|
+
exports.useSlots = exports.isPortalChild = exports.getComponentSlotName = exports.isElementChild = void 0;
|
|
36
36
|
var errors_1 = require("../helpers/errors");
|
|
37
37
|
var react_1 = __importStar(require("react"));
|
|
38
38
|
var isElementChild = function (child) {
|
|
@@ -47,9 +47,6 @@ var getComponentSlotName = function (TargetComponent, child) {
|
|
|
47
47
|
var keyTypes = ['string', 'number', 'symbol'];
|
|
48
48
|
var slotName = child.props['data-slot-name'];
|
|
49
49
|
if (keyTypes.includes(typeof slotName)) {
|
|
50
|
-
if (typeof child.type === 'string') {
|
|
51
|
-
child.props.tagName = child.type;
|
|
52
|
-
}
|
|
53
50
|
return slotName;
|
|
54
51
|
}
|
|
55
52
|
}
|
|
@@ -65,6 +62,12 @@ var getComponentSlotName = function (TargetComponent, child) {
|
|
|
65
62
|
return undefined;
|
|
66
63
|
};
|
|
67
64
|
exports.getComponentSlotName = getComponentSlotName;
|
|
65
|
+
var isPortalChild = function (child) {
|
|
66
|
+
return (!!child
|
|
67
|
+
&& typeof child === 'object'
|
|
68
|
+
&& 'children' in child);
|
|
69
|
+
};
|
|
70
|
+
exports.isPortalChild = isPortalChild;
|
|
68
71
|
/**
|
|
69
72
|
* Groups `children` prop into predefined slots.
|
|
70
73
|
*
|
|
@@ -77,7 +80,7 @@ exports.getComponentSlotName = getComponentSlotName;
|
|
|
77
80
|
*/
|
|
78
81
|
var useSlots = function (children, Caller) {
|
|
79
82
|
var slotsAliasLookup = (0, react_1.useMemo)(function () {
|
|
80
|
-
var entries = Object.entries(Caller.
|
|
83
|
+
var entries = Object.entries(Caller.Slots);
|
|
81
84
|
var aliasLookup = {};
|
|
82
85
|
entries.forEach(function (_a) {
|
|
83
86
|
var alias = _a[0], RegisteredSlotComponent = _a[1];
|
|
@@ -89,15 +92,17 @@ var useSlots = function (children, Caller) {
|
|
|
89
92
|
aliasLookup[slotName] = alias;
|
|
90
93
|
});
|
|
91
94
|
return aliasLookup;
|
|
92
|
-
}, [Caller.
|
|
95
|
+
}, [Caller.Slots]);
|
|
96
|
+
// @todo Expose original source order of `children` with respect to slot aliases.
|
|
93
97
|
var result = (0, react_1.useMemo)(function () {
|
|
94
98
|
var _a;
|
|
95
99
|
var slotNodes = {};
|
|
96
100
|
var unmatchedChildren = [];
|
|
97
101
|
var invalidChildren = [];
|
|
98
102
|
var requiredSlotAliases = __spreadArray([], ((_a = Caller.requiredSlotAliases) !== null && _a !== void 0 ? _a : []), true);
|
|
99
|
-
react_1.default.Children.forEach(children, function (
|
|
103
|
+
react_1.default.Children.forEach(children, function (_child) {
|
|
100
104
|
var _a;
|
|
105
|
+
var child = _child;
|
|
101
106
|
if (!child) {
|
|
102
107
|
invalidChildren.push(child);
|
|
103
108
|
return;
|
|
@@ -114,15 +119,16 @@ var useSlots = function (children, Caller) {
|
|
|
114
119
|
return;
|
|
115
120
|
}
|
|
116
121
|
var slotAlias = (function () {
|
|
122
|
+
var _a;
|
|
117
123
|
var slotName = (0, exports.getComponentSlotName)(child.type, child);
|
|
118
|
-
return slotName ? slotsAliasLookup[slotName] : null;
|
|
124
|
+
return slotName ? (_a = slotsAliasLookup[slotName]) !== null && _a !== void 0 ? _a : null : null;
|
|
119
125
|
})();
|
|
120
|
-
if (slotAlias && (typeof Caller.slots[slotAlias] !== 'string')) {
|
|
121
|
-
if ((_a = Caller.slots[slotAlias]) === null || _a === void 0 ? void 0 : _a.isRequiredSlot) {
|
|
122
|
-
requiredSlotAliases.push(slotAlias);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
126
|
if (slotAlias) {
|
|
127
|
+
if (typeof Caller.Slots[slotAlias] !== 'string') {
|
|
128
|
+
if ((_a = Caller.Slots[slotAlias]) === null || _a === void 0 ? void 0 : _a.isRequiredSlot) {
|
|
129
|
+
requiredSlotAliases.push(slotAlias);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
126
132
|
if (slotNodes[slotAlias]) {
|
|
127
133
|
slotNodes[slotAlias].push(child);
|
|
128
134
|
}
|
package/build/slots/types.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import type { ReactElement, ReactNode, ComponentType, ReactPortal, JSX } from 'react';
|
|
2
|
+
/** @todo ComponentType force children to be ReactNode, but custom components can have any children type. */
|
|
3
|
+
type JSXTagLike = string | keyof JSX.IntrinsicElements | ComponentType<any>;
|
|
4
|
+
/** This fixes overly narrow T type used by React's ComponentProps type. */
|
|
5
|
+
export type ComponentProps<T extends JSXTagLike> = (T extends ComponentType<infer P> ? P : T extends keyof JSX.IntrinsicElements ? JSX.IntrinsicElements[T] : {});
|
|
5
6
|
export type TSlotName = keyof any;
|
|
6
7
|
export type TSlotAlias = keyof any;
|
|
7
8
|
/**
|
|
@@ -11,18 +12,24 @@ export type TSlotAlias = keyof any;
|
|
|
11
12
|
* each alias in this record to hold any `ReactNode`s rendered for that slot.
|
|
12
13
|
*/
|
|
13
14
|
export type TSlotsRecord<TKey extends TSlotAlias = TSlotAlias> = {
|
|
14
|
-
[Key in TKey]: string |
|
|
15
|
+
[Key in TKey]: SlotComponent<string | ComponentType<any>>;
|
|
15
16
|
};
|
|
16
|
-
export type DisplayNamedComponent<
|
|
17
|
-
displayName:
|
|
18
|
-
};
|
|
19
|
-
export type SlotNamedComponent<TComponentArg extends TComponent = TComponent, TSlotNameArg extends TSlotName = TSlotName> = TComponentArg & {
|
|
20
|
-
slotName: TSlotNameArg;
|
|
17
|
+
export type DisplayNamedComponent<TComponent extends ComponentType<any> = ComponentType<any>, TName extends string = string> = TComponent & {
|
|
18
|
+
displayName: TName;
|
|
21
19
|
};
|
|
20
|
+
interface ISlotConfig<TName> {
|
|
21
|
+
slotName: TName;
|
|
22
|
+
/**
|
|
23
|
+
* @deprecated The SlottedComponent should be responsible for indicating which slots it requires.
|
|
24
|
+
* Individual slot components may be reused by multiple slotted components with varying requirements.
|
|
25
|
+
*/
|
|
26
|
+
isRequiredSlot?: boolean;
|
|
27
|
+
}
|
|
22
28
|
/**
|
|
23
29
|
* A child component used to insert content into a specific slot in the parent component.
|
|
24
30
|
* This can either be a string, or a React component with a `slotName` property.
|
|
25
|
-
*
|
|
31
|
+
*
|
|
32
|
+
* > `displayName` is no longer supported as a fallback for `slotName`.
|
|
26
33
|
*
|
|
27
34
|
* ### Strings
|
|
28
35
|
* For strings, they are treated by React a native tags. This lets you use custom strings
|
|
@@ -38,7 +45,7 @@ export type SlotNamedComponent<TComponentArg extends TComponent = TComponent, TS
|
|
|
38
45
|
* and you can map that to
|
|
39
46
|
* ```jsx
|
|
40
47
|
* <button
|
|
41
|
-
* {...slotNodes.Option.props}
|
|
48
|
+
* {...slotNodes.Option[0].props}
|
|
42
49
|
* type="button"
|
|
43
50
|
* />
|
|
44
51
|
* ```
|
|
@@ -49,9 +56,9 @@ export type SlotNamedComponent<TComponentArg extends TComponent = TComponent, TS
|
|
|
49
56
|
*
|
|
50
57
|
* So consumers may pass the following as `children`.
|
|
51
58
|
* ```jsx
|
|
52
|
-
* <Parent.
|
|
59
|
+
* <Parent.Slots.Content>
|
|
53
60
|
* Some awesome content.
|
|
54
|
-
* </Parent.
|
|
61
|
+
* </Parent.Slots.Content>
|
|
55
62
|
* ```
|
|
56
63
|
* and you can map that to
|
|
57
64
|
* ```jsx
|
|
@@ -62,7 +69,7 @@ export type SlotNamedComponent<TComponentArg extends TComponent = TComponent, TS
|
|
|
62
69
|
* </>
|
|
63
70
|
* ```
|
|
64
71
|
*
|
|
65
|
-
* This means `Parent.
|
|
72
|
+
* This means `Parent.Slots.Content` must be defined as a proper React component
|
|
66
73
|
* and is solely responsible for doing something with the `"Some awesome content."`
|
|
67
74
|
* which was passed into it as children.
|
|
68
75
|
*
|
|
@@ -70,9 +77,7 @@ export type SlotNamedComponent<TComponentArg extends TComponent = TComponent, TS
|
|
|
70
77
|
* extracts the props passed to the slot and handles
|
|
71
78
|
* what the slot actually renders.
|
|
72
79
|
*/
|
|
73
|
-
export type SlotComponent<
|
|
74
|
-
isRequiredSlot?: boolean;
|
|
75
|
-
};
|
|
80
|
+
export type SlotComponent<TComponent extends JSXTagLike = ComponentType<any>, TName extends TSlotName = TSlotName> = (TComponent extends string ? TComponent : TComponent & ISlotConfig<TName>);
|
|
76
81
|
/**
|
|
77
82
|
* A parent component which accepts content that can be grouped into predefined slots.
|
|
78
83
|
* By convention, it should have a `slots` property which is a {@link TSlotsRecord}.
|
|
@@ -81,18 +86,20 @@ export type SlotComponent<TComponentArg extends TComponent = TComponent> = (Slot
|
|
|
81
86
|
* directly from the parent component itself,
|
|
82
87
|
* through an alias that is easy to remember.
|
|
83
88
|
*/
|
|
84
|
-
export type
|
|
85
|
-
|
|
86
|
-
requiredSlotAliases?:
|
|
89
|
+
export type SlottedComponent<TOwner extends object = ComponentType<any>, TSlots extends TSlotsRecord = TSlotsRecord> = TOwner & {
|
|
90
|
+
Slots: TSlots;
|
|
91
|
+
requiredSlotAliases?: Array<keyof TSlots>;
|
|
87
92
|
};
|
|
93
|
+
export type TypedNode<P, T extends JSXTagLike> = (ReactElement<P, T> | (ReactElement<P, T> & ReactPortal));
|
|
94
|
+
export type TSlotNode<TSlotted extends SlottedComponent, Key extends keyof TSlotted['Slots'] = keyof TSlotted['Slots']> = (TypedNode<ComponentProps<TSlotted['Slots'][Key]>, TSlotted['Slots'][Key]>);
|
|
88
95
|
/**
|
|
89
96
|
* A record of slot aliases mapped to the corresponding `ReactNode`(s)
|
|
90
97
|
* to be rendered for that slot.
|
|
91
98
|
*/
|
|
92
|
-
export type TSlotNodes<
|
|
93
|
-
[Key in
|
|
99
|
+
export type TSlotNodes<TSlotted extends SlottedComponent> = {
|
|
100
|
+
[Key in keyof TSlotted['Slots']]?: Array<TSlotNode<TSlotted, Key>>;
|
|
94
101
|
};
|
|
95
|
-
export type TUseSlotsResult<
|
|
102
|
+
export type TUseSlotsResult<TSlotted extends SlottedComponent> = Readonly<[
|
|
96
103
|
/**
|
|
97
104
|
* A record of slot aliases to their corresponding React nodes.
|
|
98
105
|
* Each alias maps to an array of one or more React nodes that were passed
|
|
@@ -100,7 +107,7 @@ export type TUseSlotsResult<TSlotAliasArg extends TSlotAlias = TSlotAlias> = Rea
|
|
|
100
107
|
*
|
|
101
108
|
* If a slot was not rendered in `children`, it's alias will be `undefined` in this object.
|
|
102
109
|
*/
|
|
103
|
-
slotNodes: TSlotNodes<
|
|
110
|
+
slotNodes: TSlotNodes<TSlotted>,
|
|
104
111
|
/**
|
|
105
112
|
* Valid React nodes passed as children which did not match any of the
|
|
106
113
|
* predefined slots.
|
|
@@ -112,12 +119,13 @@ export type TUseSlotsResult<TSlotAliasArg extends TSlotAlias = TSlotAlias> = Rea
|
|
|
112
119
|
invalidChildren: any[]
|
|
113
120
|
]>;
|
|
114
121
|
export interface IUseSlots {
|
|
115
|
-
<
|
|
122
|
+
<TSlotted extends SlottedComponent>(
|
|
116
123
|
/**
|
|
117
124
|
* Your component's `children` prop.
|
|
118
125
|
* The nodes it contains will be categorized and
|
|
119
126
|
* grouped according to the predefined {@link slotComponents}.
|
|
120
127
|
*/
|
|
121
|
-
children: ReactNode, Caller:
|
|
128
|
+
children: ReactNode, Caller: TSlotted): TUseSlotsResult<TSlotted>;
|
|
122
129
|
}
|
|
123
|
-
export type PotentialSlotComponent = string | SlotComponent |
|
|
130
|
+
export type PotentialSlotComponent = string | SlotComponent | ComponentType<any>;
|
|
131
|
+
export {};
|
package/package.json
CHANGED