@pyreon/attrs 0.24.4 → 0.24.6
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/package.json +5 -7
- package/src/__tests__/attrs.test.ts +0 -531
- package/src/__tests__/attrsHoc.test.ts +0 -179
- package/src/__tests__/utils.test.ts +0 -241
- package/src/attrs.ts +0 -131
- package/src/env.d.ts +0 -6
- package/src/hoc/attrsHoc.ts +0 -74
- package/src/hoc/index.ts +0 -3
- package/src/index.ts +0 -26
- package/src/init.ts +0 -65
- package/src/isAttrsComponent.ts +0 -16
- package/src/types/AttrsComponent.ts +0 -83
- package/src/types/InitAttrsComponent.ts +0 -19
- package/src/types/attrs.ts +0 -2
- package/src/types/config.ts +0 -13
- package/src/types/configuration.ts +0 -40
- package/src/types/hoc.ts +0 -10
- package/src/types/utils.ts +0 -137
- package/src/utils/attrs.ts +0 -46
- package/src/utils/chaining.ts +0 -21
- package/src/utils/collection.ts +0 -14
- package/src/utils/compose.ts +0 -14
- package/src/utils/statics.ts +0 -16
package/src/init.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { isEmpty } from '@pyreon/ui-core'
|
|
2
|
-
import attrsComponent from './attrs'
|
|
3
|
-
import type { InitAttrsComponent } from './types/InitAttrsComponent'
|
|
4
|
-
import type { ElementType } from './types/utils'
|
|
5
|
-
|
|
6
|
-
// Dev-mode gate. `import.meta.env.DEV` is literal-replaced by Vite at build
|
|
7
|
-
// time and tree-shakes to zero bytes in prod. The previous
|
|
8
|
-
// `process.env.NODE_ENV !== 'production'` form was dead code in real Vite
|
|
9
|
-
// browser bundles (Vite does not polyfill `process`).
|
|
10
|
-
const __DEV__ = process.env.NODE_ENV !== 'production'
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Public entry point for creating an attrs-enhanced component.
|
|
14
|
-
*
|
|
15
|
-
* ```tsx
|
|
16
|
-
* const Button = attrs({ name: 'Button', component: Element })
|
|
17
|
-
* .attrs({ tag: 'button' })
|
|
18
|
-
* .attrs<{ primary?: boolean }>(({ primary }) => ({
|
|
19
|
-
* backgroundColor: primary ? 'blue' : 'gray',
|
|
20
|
-
* }))
|
|
21
|
-
* ```
|
|
22
|
-
*/
|
|
23
|
-
export type Attrs = <C extends ElementType>({
|
|
24
|
-
name,
|
|
25
|
-
component,
|
|
26
|
-
}: {
|
|
27
|
-
name: string
|
|
28
|
-
component: C
|
|
29
|
-
}) => ReturnType<InitAttrsComponent<C>>
|
|
30
|
-
|
|
31
|
-
const attrs: Attrs = ({ name, component }) => {
|
|
32
|
-
// Validate required params in development — fail fast with clear errors.
|
|
33
|
-
if (__DEV__) {
|
|
34
|
-
type Errors = Partial<{
|
|
35
|
-
component: string
|
|
36
|
-
name: string
|
|
37
|
-
}>
|
|
38
|
-
|
|
39
|
-
const errors: Errors = {}
|
|
40
|
-
if (!component) {
|
|
41
|
-
errors.component = 'Parameter `component` is missing in params!'
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (!name) {
|
|
45
|
-
errors.name = 'Parameter `name` is missing in params!'
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (!isEmpty(errors)) {
|
|
49
|
-
throw Error(JSON.stringify(errors))
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Bootstrap with empty configuration — all chains start from scratch.
|
|
54
|
-
return attrsComponent({
|
|
55
|
-
name,
|
|
56
|
-
component,
|
|
57
|
-
attrs: [],
|
|
58
|
-
priorityAttrs: [],
|
|
59
|
-
filterAttrs: [],
|
|
60
|
-
compose: {},
|
|
61
|
-
statics: {},
|
|
62
|
-
})
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export default attrs
|
package/src/isAttrsComponent.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export type IsAttrsComponent = <T>(component: T) => boolean
|
|
2
|
-
|
|
3
|
-
/** Runtime type guard — checks if a component was created by `attrs()`. */
|
|
4
|
-
const isAttrsComponent: IsAttrsComponent = (component) => {
|
|
5
|
-
if (
|
|
6
|
-
component &&
|
|
7
|
-
(typeof component === 'object' || typeof component === 'function') &&
|
|
8
|
-
Object.hasOwn(component as object, 'IS_ATTRS')
|
|
9
|
-
) {
|
|
10
|
-
return true
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
return false
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export default isAttrsComponent
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import type { VNode } from '@pyreon/core'
|
|
2
|
-
import type { AttrsCb } from './attrs'
|
|
3
|
-
import type { ConfigAttrs } from './config'
|
|
4
|
-
import type { ComposeParam } from './hoc'
|
|
5
|
-
import type { ElementType, ExtractProps, MergeTypes, TObj } from './utils'
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Props passed to the inner enhanced component.
|
|
9
|
-
* In Pyreon there's no forwardRef — ref flows as a normal prop.
|
|
10
|
-
*/
|
|
11
|
-
export type InnerComponentProps = {
|
|
12
|
-
'data-attrs'?: string | undefined
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* @param OA Origin component props params.
|
|
17
|
-
* @param EA Extended prop types
|
|
18
|
-
* @param S Defined statics
|
|
19
|
-
* @param HOC High-order components
|
|
20
|
-
* @param DFP Calculated final component props
|
|
21
|
-
*/
|
|
22
|
-
export interface AttrsComponent<
|
|
23
|
-
C extends ElementType = ElementType,
|
|
24
|
-
// original component props
|
|
25
|
-
OA extends TObj = {},
|
|
26
|
-
// extended component props
|
|
27
|
-
EA extends TObj = {},
|
|
28
|
-
// statics
|
|
29
|
-
S extends TObj = {},
|
|
30
|
-
// hocs
|
|
31
|
-
HOC extends TObj = {},
|
|
32
|
-
// calculated final props
|
|
33
|
-
DFP extends Record<string, any> = MergeTypes<[OA, EA]>,
|
|
34
|
-
> {
|
|
35
|
-
// The component is callable — Pyreon components are plain functions
|
|
36
|
-
(props: DFP): VNode | null
|
|
37
|
-
|
|
38
|
-
// CONFIG chaining method
|
|
39
|
-
config: <NC extends ElementType | unknown = unknown>({
|
|
40
|
-
name,
|
|
41
|
-
component: NC,
|
|
42
|
-
DEBUG,
|
|
43
|
-
}: ConfigAttrs<NC>) => NC extends ElementType
|
|
44
|
-
? AttrsComponent<NC, ExtractProps<NC>, EA, S, HOC>
|
|
45
|
-
: AttrsComponent<C, OA, EA, S, HOC>
|
|
46
|
-
|
|
47
|
-
// ATTRS chaining method
|
|
48
|
-
attrs: <P extends TObj | unknown = unknown>(
|
|
49
|
-
param: P extends TObj ? Partial<DFP & P> | AttrsCb<DFP & P> : Partial<DFP> | AttrsCb<DFP>,
|
|
50
|
-
config?: Partial<{
|
|
51
|
-
priority: boolean
|
|
52
|
-
filter: unknown extends P ? string[] : (keyof (EA & P))[]
|
|
53
|
-
}>,
|
|
54
|
-
) => P extends TObj
|
|
55
|
-
? AttrsComponent<C, OA, MergeTypes<[EA, P]>, S, HOC>
|
|
56
|
-
: AttrsComponent<C, OA, EA, S, HOC>
|
|
57
|
-
|
|
58
|
-
// COMPOSE chaining method
|
|
59
|
-
compose: <P extends ComposeParam>(
|
|
60
|
-
param: P,
|
|
61
|
-
) => P extends TObj
|
|
62
|
-
? AttrsComponent<C, OA, EA, S, MergeTypes<[HOC, P]>>
|
|
63
|
-
: AttrsComponent<C, OA, EA, S, HOC>
|
|
64
|
-
|
|
65
|
-
// STATICS chaining method
|
|
66
|
-
statics: <P extends TObj | unknown = unknown>(
|
|
67
|
-
param: P,
|
|
68
|
-
) => P extends TObj
|
|
69
|
-
? AttrsComponent<C, OA, EA, MergeTypes<[S, P]>, HOC>
|
|
70
|
-
: AttrsComponent<C, OA, EA, S, HOC>
|
|
71
|
-
|
|
72
|
-
/** Access to all defined statics on the component. */
|
|
73
|
-
meta: S
|
|
74
|
-
|
|
75
|
-
getDefaultAttrs: (props: TObj) => TObj
|
|
76
|
-
|
|
77
|
-
readonly $$originTypes: OA
|
|
78
|
-
readonly $$extendedTypes: EA
|
|
79
|
-
readonly $$types: DFP
|
|
80
|
-
|
|
81
|
-
IS_ATTRS: true
|
|
82
|
-
displayName: string
|
|
83
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { AttrsComponent } from './AttrsComponent'
|
|
2
|
-
import type { Configuration } from './configuration'
|
|
3
|
-
import type { ElementType, ExtractProps } from './utils'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Type of the internal `attrsComponent` factory function.
|
|
7
|
-
* Takes a full Configuration and returns an AttrsComponent whose
|
|
8
|
-
* original props (OA) are extracted from the component type C,
|
|
9
|
-
* with all extension slots (EA, S, HOC) starting empty.
|
|
10
|
-
*/
|
|
11
|
-
export type InitAttrsComponent<C extends ElementType = ElementType> = (
|
|
12
|
-
params: Configuration<C>,
|
|
13
|
-
) => AttrsComponent<
|
|
14
|
-
C,
|
|
15
|
-
ExtractProps<C>, // OA — original component props
|
|
16
|
-
{}, // EA — extended props (empty initially)
|
|
17
|
-
{}, // S — statics (empty initially)
|
|
18
|
-
{} // HOC — composed HOCs (empty initially)
|
|
19
|
-
>
|
package/src/types/attrs.ts
DELETED
package/src/types/config.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { ElementType } from './utils'
|
|
2
|
-
|
|
3
|
-
/** A component that has been enhanced by attrs — identified by the `IS_ATTRS` marker. */
|
|
4
|
-
export type AttrsComponentType = ElementType & {
|
|
5
|
-
IS_ATTRS: true
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
/** Parameters accepted by the `.config()` chaining method. */
|
|
9
|
-
export type ConfigAttrs<C extends ElementType | unknown> = Partial<{
|
|
10
|
-
name: string
|
|
11
|
-
component: C
|
|
12
|
-
DEBUG: boolean
|
|
13
|
-
}>
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import type { ElementType, TFn } from './utils'
|
|
2
|
-
|
|
3
|
-
export type OptionFunc = (...arg: unknown[]) => Record<string, unknown>
|
|
4
|
-
|
|
5
|
-
export type InitConfiguration<C> = {
|
|
6
|
-
name?: string | undefined
|
|
7
|
-
component: C
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Internal configuration accumulated across the chaining API.
|
|
12
|
-
* Arrays hold the full chain — each `.attrs()` call appends to these.
|
|
13
|
-
*/
|
|
14
|
-
export type Configuration<C = ElementType | unknown> = InitConfiguration<C> & {
|
|
15
|
-
DEBUG?: boolean | undefined
|
|
16
|
-
/** Chain of default-props callbacks (resolved in order, later wins). */
|
|
17
|
-
attrs: OptionFunc[]
|
|
18
|
-
/** Chain of priority-props callbacks (resolved before `attrs`, can be overridden by both). */
|
|
19
|
-
priorityAttrs: OptionFunc[]
|
|
20
|
-
/** Prop names to omit before passing to the underlying component. */
|
|
21
|
-
filterAttrs: string[]
|
|
22
|
-
/** Named HOCs — set to null/false to remove from chain. */
|
|
23
|
-
compose: Record<string, TFn | null | undefined | false>
|
|
24
|
-
/** Metadata accessible via `Component.meta`. */
|
|
25
|
-
statics: Record<string, any>
|
|
26
|
-
} & Record<string, any>
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Single-item variant of Configuration — represents what a single
|
|
30
|
-
* `.attrs()` / `.config()` call contributes (one function, not an array).
|
|
31
|
-
* Used by `cloneAndEnhance` to merge into the accumulated Configuration.
|
|
32
|
-
*/
|
|
33
|
-
export type ExtendedConfiguration<C = ElementType | unknown> = InitConfiguration<C> & {
|
|
34
|
-
DEBUG?: boolean | undefined
|
|
35
|
-
attrs: OptionFunc
|
|
36
|
-
priorityAttrs: OptionFunc
|
|
37
|
-
filterAttrs: string[]
|
|
38
|
-
compose: Record<string, TFn | null | undefined | false>
|
|
39
|
-
statics: Record<string, any>
|
|
40
|
-
} & Record<string, any>
|
package/src/types/hoc.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { ElementType } from './utils'
|
|
2
|
-
|
|
3
|
-
export type GenericHoc = (component: ElementType) => ElementType
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Parameters for `.compose()` — a record of named HOCs.
|
|
7
|
-
* Setting a key to `null`, `undefined`, or `false` removes a
|
|
8
|
-
* previously defined HOC from the chain.
|
|
9
|
-
*/
|
|
10
|
-
export type ComposeParam = Record<string, GenericHoc | null | undefined | false>
|
package/src/types/utils.ts
DELETED
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import type { VNodeChild } from '@pyreon/core'
|
|
2
|
-
|
|
3
|
-
// ─── Base Types ───────────────────────────────────────────────
|
|
4
|
-
|
|
5
|
-
export type TObj = Record<string, unknown>
|
|
6
|
-
export type TFn = (...args: any) => any
|
|
7
|
-
export type CallBackParam = TObj | TFn
|
|
8
|
-
export type DisplayName = string
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* A Pyreon component function that accepts additional static properties.
|
|
12
|
-
* Aligned with @pyreon/core's ComponentFn — returns VNodeChild (not just VNode | null)
|
|
13
|
-
* to support components returning strings, numbers, undefined, etc.
|
|
14
|
-
*/
|
|
15
|
-
export type ComponentFn<P = any> = ((props: P) => VNodeChild) & Partial<Record<string, any>>
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* An element type — either a Pyreon component function or an intrinsic tag string.
|
|
19
|
-
*/
|
|
20
|
-
export type ElementType<T extends TObj | unknown = any> = ComponentFn<T>
|
|
21
|
-
|
|
22
|
-
export type ValueOf<T> = T[keyof T]
|
|
23
|
-
|
|
24
|
-
export type ArrayOfValues<T> = T[keyof T]
|
|
25
|
-
|
|
26
|
-
export type ArrayOfKeys<T> = keyof T[]
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* A HOC that wraps a component and merges additional props `P`
|
|
30
|
-
* with the wrapped component's own props.
|
|
31
|
-
*/
|
|
32
|
-
export type SimpleHoc<P extends Record<string, unknown> = Record<string, unknown>> = <
|
|
33
|
-
T extends ComponentFn<any>,
|
|
34
|
-
>(
|
|
35
|
-
WrappedComponent: T,
|
|
36
|
-
) => ComponentFn<MergeTypes<[P, ExtractProps<T>]>>
|
|
37
|
-
|
|
38
|
-
/** Maps each key to `never` if the value is null, undefined, or false. */
|
|
39
|
-
type IsFalseOrNullable<T> = T extends null | undefined | false ? never : true
|
|
40
|
-
export type NullableKeys<T> = { [K in keyof T]: IsFalseOrNullable<T[K]> }
|
|
41
|
-
|
|
42
|
-
/** Unwraps a callback to its return type, or returns the object as-is. */
|
|
43
|
-
export type ReturnCbParam<P extends TFn | TObj> = P extends TFn ? ReturnType<P> : P
|
|
44
|
-
|
|
45
|
-
// ─── MergeTypes ───────────────────────────────────────────────
|
|
46
|
-
//
|
|
47
|
-
// Merges a tuple of object types left-to-right (like Object.assign),
|
|
48
|
-
// then strips keys whose values resolved to `never`, `null`, or `undefined`.
|
|
49
|
-
//
|
|
50
|
-
// Usage: MergeTypes<[BaseProps, ExtendedProps, OverrideProps]>
|
|
51
|
-
//
|
|
52
|
-
// This is the backbone of the chaining API — each `.attrs<P>()`
|
|
53
|
-
// call produces MergeTypes<[PreviousProps, P]> so later definitions
|
|
54
|
-
// override earlier ones while preserving the rest.
|
|
55
|
-
// ──────────────────────────────────────────────────────────────
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Forces TypeScript to expand/flatten a type for better IDE display.
|
|
59
|
-
* Short-circuits for `any` — the mapped type would turn `any` into
|
|
60
|
-
* `{ [x: string]: any; [x: number]: any; [x: symbol]: any }`, losing
|
|
61
|
-
* its identity as `any` and breaking downstream type checks.
|
|
62
|
-
*/
|
|
63
|
-
type Id<T> = 0 extends 1 & T ? T : T extends infer U ? { [K in keyof U]: U[K] } : never
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Strips keys whose values are `never`, `null`, or `undefined`.
|
|
67
|
-
* Uses tuple wrapping `[T[P]] extends [never]` to avoid distribution
|
|
68
|
-
* over union types (a bare `T[P] extends never` would incorrectly
|
|
69
|
-
* match union members).
|
|
70
|
-
*
|
|
71
|
-
* Short-circuits for `any` — the `as` clause in mapped types loses
|
|
72
|
-
* index signatures, which would turn `any` into an empty type.
|
|
73
|
-
*/
|
|
74
|
-
type IsAny<T> = 0 extends 1 & T ? true : false
|
|
75
|
-
|
|
76
|
-
type ExtractNullableKeys<T> = 0 extends 1 & T
|
|
77
|
-
? T
|
|
78
|
-
: {
|
|
79
|
-
[P in keyof T as IsAny<T[P]> extends true
|
|
80
|
-
? P
|
|
81
|
-
: [T[P]] extends [never]
|
|
82
|
-
? never
|
|
83
|
-
: [T[P]] extends [null | undefined]
|
|
84
|
-
? never
|
|
85
|
-
: P]: T[P]
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/** Merges two types: keeps all keys from L that don't exist in R, then adds all of R. */
|
|
89
|
-
type SpreadTwo<L, R> = Id<Pick<L, Exclude<keyof L, keyof R>> & R>
|
|
90
|
-
|
|
91
|
-
/** Recursively spreads a tuple of types left-to-right. */
|
|
92
|
-
type Spread<A extends readonly [...any]> = A extends [infer L, ...infer R]
|
|
93
|
-
? SpreadTwo<L, Spread<R>>
|
|
94
|
-
: unknown
|
|
95
|
-
|
|
96
|
-
/** Recursively checks whether any element in the tuple is `any`. */
|
|
97
|
-
type _HasAny<A> = A extends [infer L, ...infer R] ? (0 extends 1 & L ? true : _HasAny<R>) : false
|
|
98
|
-
|
|
99
|
-
export type MergeTypes<A extends readonly [...any]> =
|
|
100
|
-
_HasAny<A> extends true ? any : ExtractNullableKeys<Spread<A>>
|
|
101
|
-
|
|
102
|
-
// ─── ExtractProps ─────────────────────────────────────────────
|
|
103
|
-
|
|
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
|
package/src/utils/attrs.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { isEmpty } from '@pyreon/ui-core'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Strips keys with `undefined` values from a props object.
|
|
5
|
-
* This prevents undefined consumer props from overriding defaults
|
|
6
|
-
* computed by `.attrs()` callbacks. Only explicitly set values
|
|
7
|
-
* (including `null`) should override defaults.
|
|
8
|
-
*/
|
|
9
|
-
type RemoveUndefinedProps = <T extends Record<string, any>>(
|
|
10
|
-
props: T,
|
|
11
|
-
) => { [I in keyof T as T[I] extends undefined ? never : I]: T[I] }
|
|
12
|
-
|
|
13
|
-
export const removeUndefinedProps = (<T extends Record<string, any>>(props: T) => {
|
|
14
|
-
// Direct for-in loop avoids the `Object.keys` array allocation that
|
|
15
|
-
// the prior `reduce` over `Object.keys(props)` paid on every render.
|
|
16
|
-
// The hot path fires on every content-equal re-render of any attrs-
|
|
17
|
-
// wrapped component. Ported from vitus-labs `b003de47`.
|
|
18
|
-
const result: Record<string, unknown> = {}
|
|
19
|
-
for (const key in props) {
|
|
20
|
-
const value = props[key]
|
|
21
|
-
if (value !== undefined) result[key] = value
|
|
22
|
-
}
|
|
23
|
-
return result
|
|
24
|
-
}) as RemoveUndefinedProps
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Reduces an array of option functions (from chained `.attrs()` calls)
|
|
28
|
-
* into a single merged result. Each function is called with `args`
|
|
29
|
-
* (typically the current props) and its return value is merged
|
|
30
|
-
* left-to-right via Object.assign — so later `.attrs()` calls
|
|
31
|
-
* override earlier ones.
|
|
32
|
-
*
|
|
33
|
-
* Returns a curried function: first call binds the chain, second
|
|
34
|
-
* call provides the arguments and executes the reduction.
|
|
35
|
-
*/
|
|
36
|
-
type OptionFunc<A> = (...arg: A[]) => Record<string, unknown>
|
|
37
|
-
type CalculateChainOptions = <A>(
|
|
38
|
-
options?: OptionFunc<A>[],
|
|
39
|
-
) => (args: A[]) => ReturnType<OptionFunc<A>>
|
|
40
|
-
|
|
41
|
-
export const calculateChainOptions: CalculateChainOptions = (options) => (args) => {
|
|
42
|
-
const result = {}
|
|
43
|
-
if (!options || isEmpty(options)) return result
|
|
44
|
-
|
|
45
|
-
return options.reduce((acc, item) => Object.assign(acc, item(...args)), {})
|
|
46
|
-
}
|
package/src/utils/chaining.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
type Func = (...args: any) => Record<string, unknown>
|
|
2
|
-
type Obj = Record<string, unknown>
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Appends a new attrs option to the existing chain of option functions.
|
|
6
|
-
*
|
|
7
|
-
* The `.attrs()` API accepts either an object or a callback. This function
|
|
8
|
-
* normalizes both forms into a function (objects are wrapped in `() => obj`)
|
|
9
|
-
* and appends to the existing array. The array is cloned so each chained
|
|
10
|
-
* component gets its own copy — maintaining immutability across the chain.
|
|
11
|
-
*/
|
|
12
|
-
type ChainOptions = (opts: Obj | Func | undefined, defaultOpts: Func[]) => Func[]
|
|
13
|
-
|
|
14
|
-
export const chainOptions: ChainOptions = (opts, defaultOpts = []) => {
|
|
15
|
-
const result = [...defaultOpts]
|
|
16
|
-
|
|
17
|
-
if (typeof opts === 'function') result.push(opts)
|
|
18
|
-
else if (typeof opts === 'object') result.push(() => opts)
|
|
19
|
-
|
|
20
|
-
return result
|
|
21
|
-
}
|
package/src/utils/collection.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Filters out keys with `null`, `undefined`, or `false` values.
|
|
3
|
-
* Used to clean compose config — setting a HOC to `false`/`null` removes it.
|
|
4
|
-
*/
|
|
5
|
-
type RemoveNullableValues = (obj: Record<string, any>) => Record<string, any>
|
|
6
|
-
export const removeNullableValues: RemoveNullableValues = (obj) => {
|
|
7
|
-
const result: Record<string, any> = {}
|
|
8
|
-
for (const [k, v] of Object.entries(obj)) {
|
|
9
|
-
if (v != null && v !== false) {
|
|
10
|
-
result[k] = v
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
return result
|
|
14
|
-
}
|
package/src/utils/compose.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Extracts HOC functions from the `.compose()` configuration and reverses
|
|
3
|
-
* them for correct application order. Setting a key to `null`, `undefined`,
|
|
4
|
-
* or `false` removes a previously defined HOC — only actual functions are kept.
|
|
5
|
-
*
|
|
6
|
-
* The reversal is needed because `compose(a, b, c)(Component)` applies as
|
|
7
|
-
* `a(b(c(Component)))`, so the last-defined HOC should wrap innermost.
|
|
8
|
-
*/
|
|
9
|
-
type CalculateHocsFuncs = (options: Record<string, any>) => ((arg: any) => any)[]
|
|
10
|
-
|
|
11
|
-
export const calculateHocsFuncs: CalculateHocsFuncs = (options = {}) =>
|
|
12
|
-
Object.values(options)
|
|
13
|
-
.filter((item) => typeof item === 'function')
|
|
14
|
-
.reverse()
|
package/src/utils/statics.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { isEmpty } from '@pyreon/ui-core'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Copies user-defined statics from `.statics()` into the component's
|
|
5
|
-
* `meta` object. These are accessible at `Component.meta.myStatic`.
|
|
6
|
-
*/
|
|
7
|
-
type CreateStaticsEnhancers = (params: {
|
|
8
|
-
context: Record<string, any>
|
|
9
|
-
options: Record<string, any>
|
|
10
|
-
}) => void
|
|
11
|
-
|
|
12
|
-
export const createStaticsEnhancers: CreateStaticsEnhancers = ({ context, options }) => {
|
|
13
|
-
if (!isEmpty(options)) {
|
|
14
|
-
Object.assign(context, options)
|
|
15
|
-
}
|
|
16
|
-
}
|