@pyreon/attrs 0.15.0 → 0.18.0
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/lib/index.d.ts +26 -2
- package/lib/index.js +7 -3
- package/package.json +6 -6
- package/src/hoc/attrsHoc.ts +21 -7
- package/src/types/utils.ts +34 -3
package/lib/index.d.ts
CHANGED
|
@@ -42,8 +42,32 @@ type Spread<A extends readonly [...any]> = A extends [infer L, ...infer R] ? Spr
|
|
|
42
42
|
/** Recursively checks whether any element in the tuple is `any`. */
|
|
43
43
|
type _HasAny<A> = A extends [infer L, ...infer R] ? (0 extends 1 & L ? true : _HasAny<R>) : false;
|
|
44
44
|
type MergeTypes<A extends readonly [...any]> = _HasAny<A> extends true ? any : ExtractNullableKeys<Spread<A>>;
|
|
45
|
-
/**
|
|
46
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Extracts the props type from a Pyreon component function — or passes
|
|
47
|
+
* through the input unchanged when it's already a props type.
|
|
48
|
+
*
|
|
49
|
+
* Multi-overload aware: matches up to 4 call signatures and produces the
|
|
50
|
+
* UNION of their first-argument types. Iterator / List / Element are
|
|
51
|
+
* 3-overload primitives — without overload-aware extraction, wrapping
|
|
52
|
+
* them through `attrs()` silently downgraded their public prop surface
|
|
53
|
+
* to the LAST (loosest) overload. Mirrors vitus-labs PR #222.
|
|
54
|
+
*
|
|
55
|
+
* See `@pyreon/rocketstyle` `ExtractProps` for the canonical shape — kept
|
|
56
|
+
* in sync across the 4 copies in core / elements / attrs / rocketstyle.
|
|
57
|
+
*/
|
|
58
|
+
type ExtractProps<TComponentOrTProps> = TComponentOrTProps extends {
|
|
59
|
+
(props: infer P1, ...args: any): any;
|
|
60
|
+
(props: infer P2, ...args: any): any;
|
|
61
|
+
(props: infer P3, ...args: any): any;
|
|
62
|
+
(props: infer P4, ...args: any): any;
|
|
63
|
+
} ? P1 | P2 | P3 | P4 : TComponentOrTProps extends {
|
|
64
|
+
(props: infer P1, ...args: any): any;
|
|
65
|
+
(props: infer P2, ...args: any): any;
|
|
66
|
+
(props: infer P3, ...args: any): any;
|
|
67
|
+
} ? P1 | P2 | P3 : TComponentOrTProps extends {
|
|
68
|
+
(props: infer P1, ...args: any): any;
|
|
69
|
+
(props: infer P2, ...args: any): any;
|
|
70
|
+
} ? P1 | P2 : TComponentOrTProps extends ComponentFn<infer TProps> ? TProps : TComponentOrTProps;
|
|
47
71
|
//#endregion
|
|
48
72
|
//#region src/types/config.d.ts
|
|
49
73
|
/** A component that has been enhanced by attrs — identified by the `IS_ATTRS` marker. */
|
package/lib/index.js
CHANGED
|
@@ -29,14 +29,18 @@ const calculateChainOptions = (options) => (args) => {
|
|
|
29
29
|
const createAttrsHOC = ({ attrs, priorityAttrs }) => {
|
|
30
30
|
const calculateAttrs = calculateChainOptions(attrs);
|
|
31
31
|
const calculatePriorityAttrs = calculateChainOptions(priorityAttrs);
|
|
32
|
+
const hasAttrs = (attrs?.length ?? 0) > 0;
|
|
33
|
+
const hasPriorityAttrs = (priorityAttrs?.length ?? 0) > 0;
|
|
34
|
+
const hasAnyChain = hasAttrs || hasPriorityAttrs;
|
|
32
35
|
const attrsHoc = (WrappedComponent) => {
|
|
33
36
|
const HOCComponent = (props) => {
|
|
34
37
|
const filteredProps = removeUndefinedProps(props);
|
|
35
|
-
|
|
36
|
-
const
|
|
38
|
+
if (!hasAnyChain) return WrappedComponent(filteredProps);
|
|
39
|
+
const prioritizedAttrs = hasPriorityAttrs ? calculatePriorityAttrs([filteredProps]) : null;
|
|
40
|
+
const finalAttrs = hasAttrs ? calculateAttrs([prioritizedAttrs ? {
|
|
37
41
|
...prioritizedAttrs,
|
|
38
42
|
...filteredProps
|
|
39
|
-
}]);
|
|
43
|
+
} : filteredProps]) : null;
|
|
40
44
|
return WrappedComponent({
|
|
41
45
|
...prioritizedAttrs,
|
|
42
46
|
...finalAttrs,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pyreon/attrs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "Attrs HOC chaining for Pyreon components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -41,14 +41,14 @@
|
|
|
41
41
|
"typecheck": "tsc --noEmit"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@pyreon/typescript": "^0.
|
|
44
|
+
"@pyreon/typescript": "^0.18.0",
|
|
45
45
|
"@vitus-labs/tools-rolldown": "^2.3.0"
|
|
46
46
|
},
|
|
47
|
-
"peerDependencies": {
|
|
48
|
-
"@pyreon/core": "^0.15.0",
|
|
49
|
-
"@pyreon/ui-core": "^0.15.0"
|
|
50
|
-
},
|
|
51
47
|
"engines": {
|
|
52
48
|
"node": ">= 22"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@pyreon/core": "^0.18.0",
|
|
52
|
+
"@pyreon/ui-core": "^0.18.0"
|
|
53
53
|
}
|
|
54
54
|
}
|
package/src/hoc/attrsHoc.ts
CHANGED
|
@@ -25,21 +25,35 @@ const createAttrsHOC: AttrsStyleHOC = ({ attrs, priorityAttrs }) => {
|
|
|
25
25
|
// Pre-build the chain reducers once (not per render).
|
|
26
26
|
const calculateAttrs = calculateChainOptions(attrs)
|
|
27
27
|
const calculatePriorityAttrs = calculateChainOptions(priorityAttrs)
|
|
28
|
+
// Most components never call .attrs() — short-circuit the merge work below
|
|
29
|
+
// so the no-chain mount path skips 2 reducer invocations + 3 object spreads.
|
|
30
|
+
// Mirrors vitus-labs's attrsHoc fast-path; React-side memoization
|
|
31
|
+
// (useMemo / useStableValue) is omitted because Pyreon components run once
|
|
32
|
+
// per mount, not on every render.
|
|
33
|
+
const hasAttrs = (attrs?.length ?? 0) > 0
|
|
34
|
+
const hasPriorityAttrs = (priorityAttrs?.length ?? 0) > 0
|
|
35
|
+
const hasAnyChain = hasAttrs || hasPriorityAttrs
|
|
28
36
|
|
|
29
37
|
const attrsHoc = (WrappedComponent: ComponentFn<any>) => {
|
|
30
38
|
const HOCComponent: ComponentFn<any> = (props) => {
|
|
31
39
|
// Strip undefined values so they don't shadow defaults from attrs callbacks.
|
|
32
40
|
const filteredProps = removeUndefinedProps(props)
|
|
33
41
|
|
|
42
|
+
// Fast path: no attrs configured — skip reducers + spreads entirely.
|
|
43
|
+
if (!hasAnyChain) return WrappedComponent(filteredProps)
|
|
44
|
+
|
|
34
45
|
// 1. Resolve priority attrs (lowest precedence defaults).
|
|
35
|
-
const prioritizedAttrs =
|
|
46
|
+
const prioritizedAttrs = hasPriorityAttrs
|
|
47
|
+
? calculatePriorityAttrs([filteredProps])
|
|
48
|
+
: null
|
|
36
49
|
// 2. Resolve normal attrs — these see priority + explicit props as input.
|
|
37
|
-
const finalAttrs =
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
50
|
+
const finalAttrs = hasAttrs
|
|
51
|
+
? calculateAttrs([
|
|
52
|
+
prioritizedAttrs
|
|
53
|
+
? { ...prioritizedAttrs, ...filteredProps }
|
|
54
|
+
: filteredProps,
|
|
55
|
+
])
|
|
56
|
+
: null
|
|
43
57
|
|
|
44
58
|
// 3. Merge: priority < normal attrs < explicit props (last wins).
|
|
45
59
|
const finalProps = {
|
package/src/types/utils.ts
CHANGED
|
@@ -101,6 +101,37 @@ export type MergeTypes<A extends readonly [...any]> =
|
|
|
101
101
|
|
|
102
102
|
// ─── ExtractProps ─────────────────────────────────────────────
|
|
103
103
|
|
|
104
|
-
/**
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
/**
|
|
105
|
+
* Extracts the props type from a Pyreon component function — or passes
|
|
106
|
+
* through the input unchanged when it's already a props type.
|
|
107
|
+
*
|
|
108
|
+
* Multi-overload aware: matches up to 4 call signatures and produces the
|
|
109
|
+
* UNION of their first-argument types. Iterator / List / Element are
|
|
110
|
+
* 3-overload primitives — without overload-aware extraction, wrapping
|
|
111
|
+
* them through `attrs()` silently downgraded their public prop surface
|
|
112
|
+
* to the LAST (loosest) overload. Mirrors vitus-labs PR #222.
|
|
113
|
+
*
|
|
114
|
+
* See `@pyreon/rocketstyle` `ExtractProps` for the canonical shape — kept
|
|
115
|
+
* in sync across the 4 copies in core / elements / attrs / rocketstyle.
|
|
116
|
+
*/
|
|
117
|
+
export type ExtractProps<TComponentOrTProps> = TComponentOrTProps extends {
|
|
118
|
+
(props: infer P1, ...args: any): any
|
|
119
|
+
(props: infer P2, ...args: any): any
|
|
120
|
+
(props: infer P3, ...args: any): any
|
|
121
|
+
(props: infer P4, ...args: any): any
|
|
122
|
+
}
|
|
123
|
+
? P1 | P2 | P3 | P4
|
|
124
|
+
: TComponentOrTProps extends {
|
|
125
|
+
(props: infer P1, ...args: any): any
|
|
126
|
+
(props: infer P2, ...args: any): any
|
|
127
|
+
(props: infer P3, ...args: any): any
|
|
128
|
+
}
|
|
129
|
+
? P1 | P2 | P3
|
|
130
|
+
: TComponentOrTProps extends {
|
|
131
|
+
(props: infer P1, ...args: any): any
|
|
132
|
+
(props: infer P2, ...args: any): any
|
|
133
|
+
}
|
|
134
|
+
? P1 | P2
|
|
135
|
+
: TComponentOrTProps extends ComponentFn<infer TProps>
|
|
136
|
+
? TProps
|
|
137
|
+
: TComponentOrTProps
|