@pyreon/attrs 0.13.1 → 0.15.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.js +4 -2
- package/package.json +6 -5
- package/src/__tests__/attrs.test.ts +89 -46
- package/src/__tests__/attrsHoc.test.ts +43 -0
- package/src/attrs.ts +9 -4
- package/src/env.d.ts +6 -0
- package/src/init.ts +7 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
package/lib/index.js
CHANGED
|
@@ -69,6 +69,7 @@ const createStaticsEnhancers = ({ context, options }) => {
|
|
|
69
69
|
|
|
70
70
|
//#endregion
|
|
71
71
|
//#region src/attrs.ts
|
|
72
|
+
const __DEV__$1 = process.env.NODE_ENV !== "production";
|
|
72
73
|
const cloneAndEnhance = (defaultOpts, opts) => attrsComponent({
|
|
73
74
|
...defaultOpts,
|
|
74
75
|
...opts.name ? { name: opts.name } : void 0,
|
|
@@ -105,7 +106,7 @@ const attrsComponent = (options) => {
|
|
|
105
106
|
const hocsFuncs = [createAttrsHOC(options), ...calculateHocsFuncs(options.compose)];
|
|
106
107
|
const EnhancedComponent = (props) => {
|
|
107
108
|
const filteredProps = options.filterAttrs && options.filterAttrs.length > 0 ? omit(props, options.filterAttrs) : props;
|
|
108
|
-
return RenderComponent(
|
|
109
|
+
return RenderComponent(__DEV__$1 ? {
|
|
109
110
|
...filteredProps,
|
|
110
111
|
"data-attrs": componentName
|
|
111
112
|
} : filteredProps);
|
|
@@ -142,8 +143,9 @@ const attrsComponent = (options) => {
|
|
|
142
143
|
|
|
143
144
|
//#endregion
|
|
144
145
|
//#region src/init.ts
|
|
146
|
+
const __DEV__ = process.env.NODE_ENV !== "production";
|
|
145
147
|
const attrs = ({ name, component }) => {
|
|
146
|
-
if (
|
|
148
|
+
if (__DEV__) {
|
|
147
149
|
const errors = {};
|
|
148
150
|
if (!component) errors.component = "Parameter `component` is missing in params!";
|
|
149
151
|
if (!name) errors.name = "Parameter `name` is missing in params!";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pyreon/attrs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "Attrs HOC chaining for Pyreon components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"lib",
|
|
13
|
+
"!lib/**/*.map",
|
|
13
14
|
"!lib/analysis",
|
|
14
15
|
"README.md",
|
|
15
16
|
"LICENSE",
|
|
@@ -40,12 +41,12 @@
|
|
|
40
41
|
"typecheck": "tsc --noEmit"
|
|
41
42
|
},
|
|
42
43
|
"devDependencies": {
|
|
43
|
-
"@pyreon/typescript": "^0.
|
|
44
|
-
"@vitus-labs/tools-rolldown": "^
|
|
44
|
+
"@pyreon/typescript": "^0.15.0",
|
|
45
|
+
"@vitus-labs/tools-rolldown": "^2.3.0"
|
|
45
46
|
},
|
|
46
47
|
"peerDependencies": {
|
|
47
|
-
"@pyreon/core": "^0.
|
|
48
|
-
"@pyreon/ui-core": "^0.
|
|
48
|
+
"@pyreon/core": "^0.15.0",
|
|
49
|
+
"@pyreon/ui-core": "^0.15.0"
|
|
49
50
|
},
|
|
50
51
|
"engines": {
|
|
51
52
|
"node": ">= 22"
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { h } from '@pyreon/core'
|
|
1
2
|
import attrsComponent from '../attrs'
|
|
2
3
|
import attrs from '../init'
|
|
3
4
|
import isAttrsComponent from '../isAttrsComponent'
|
|
@@ -6,12 +7,8 @@ import isAttrsComponent from '../isAttrsComponent'
|
|
|
6
7
|
* Simple base component for testing.
|
|
7
8
|
* Returns a VNode-like object so we can inspect the final props.
|
|
8
9
|
*/
|
|
9
|
-
const BaseComponent = (props: any) =>
|
|
10
|
-
|
|
11
|
-
props: { ...props, 'data-testid': 'base' },
|
|
12
|
-
children: props.children ?? props.label ?? null,
|
|
13
|
-
key: null,
|
|
14
|
-
})
|
|
10
|
+
const BaseComponent = (props: any) =>
|
|
11
|
+
h('div', { ...props, 'data-testid': 'base' }, props.children ?? props.label ?? null)
|
|
15
12
|
|
|
16
13
|
/** Helper: call the component and return its output for inspection. */
|
|
17
14
|
const renderProps = (Component: any, props: Record<string, any> = {}) => {
|
|
@@ -158,35 +155,30 @@ describe('.config() chaining', () => {
|
|
|
158
155
|
})
|
|
159
156
|
|
|
160
157
|
it('should swap the rendered component', () => {
|
|
161
|
-
const AltComponent = (props: any) =>
|
|
162
|
-
|
|
163
|
-
props: { ...props, 'data-testid': 'alt' },
|
|
164
|
-
children: props.label,
|
|
165
|
-
key: null,
|
|
166
|
-
})
|
|
158
|
+
const AltComponent = (props: any) =>
|
|
159
|
+
h('span', { ...props, 'data-testid': 'alt' }, props.label)
|
|
167
160
|
|
|
168
161
|
const Original = attrs({ name: 'Test', component: BaseComponent })
|
|
169
162
|
const Swapped = Original.config({ component: AltComponent })
|
|
170
163
|
|
|
171
164
|
const result = Swapped({ label: 'swapped' }) as any
|
|
172
165
|
expect(result.props['data-testid']).toBe('alt')
|
|
173
|
-
|
|
166
|
+
// h() wraps single string children in an array. The contract here
|
|
167
|
+
// is "the rendered component received the right child text", so
|
|
168
|
+
// assert against the flattened content rather than the bare string.
|
|
169
|
+
expect(result.children).toEqual(['swapped'])
|
|
174
170
|
})
|
|
175
171
|
|
|
176
172
|
it('should preserve attrs chain after config swap', () => {
|
|
177
|
-
const AltComponent = (props: any) =>
|
|
178
|
-
|
|
179
|
-
props: { ...props, 'data-testid': 'alt' },
|
|
180
|
-
children: props.label,
|
|
181
|
-
key: null,
|
|
182
|
-
})
|
|
173
|
+
const AltComponent = (props: any) =>
|
|
174
|
+
h('span', { ...props, 'data-testid': 'alt' }, props.label)
|
|
183
175
|
|
|
184
176
|
const Component = attrs({ name: 'Test', component: BaseComponent })
|
|
185
177
|
.attrs(() => ({ label: 'from-attrs' }))
|
|
186
178
|
.config({ component: AltComponent })
|
|
187
179
|
|
|
188
180
|
const result = Component({}) as any
|
|
189
|
-
expect(result.children).
|
|
181
|
+
expect(result.children).toEqual(['from-attrs'])
|
|
190
182
|
})
|
|
191
183
|
})
|
|
192
184
|
|
|
@@ -226,12 +218,8 @@ describe('.statics() chaining', () => {
|
|
|
226
218
|
// --------------------------------------------------------
|
|
227
219
|
describe('.compose() chaining', () => {
|
|
228
220
|
it('should wrap component with a HOC', () => {
|
|
229
|
-
const withWrapper = (WrappedComponent: any) => (props: any) =>
|
|
230
|
-
|
|
231
|
-
props: { 'data-testid': 'hoc-wrapper' },
|
|
232
|
-
children: WrappedComponent(props),
|
|
233
|
-
key: null,
|
|
234
|
-
})
|
|
221
|
+
const withWrapper = (WrappedComponent: any) => (props: any) =>
|
|
222
|
+
h('div', { 'data-testid': 'hoc-wrapper' }, WrappedComponent(props))
|
|
235
223
|
|
|
236
224
|
const Component = attrs({
|
|
237
225
|
name: 'Test',
|
|
@@ -240,7 +228,10 @@ describe('.compose() chaining', () => {
|
|
|
240
228
|
|
|
241
229
|
const result = Component({ label: 'composed' }) as any
|
|
242
230
|
expect(result.props['data-testid']).toBe('hoc-wrapper')
|
|
243
|
-
|
|
231
|
+
// Real h() wraps single children in an array; nested wrapper holds
|
|
232
|
+
// its inner WrappedComponent(props) result whose `children` is now
|
|
233
|
+
// also wrapped — so two array layers down sits the final string.
|
|
234
|
+
expect(result.children[0].children).toEqual(['composed'])
|
|
244
235
|
})
|
|
245
236
|
|
|
246
237
|
it('should apply multiple HOCs in correct order', () => {
|
|
@@ -267,12 +258,8 @@ describe('.compose() chaining', () => {
|
|
|
267
258
|
})
|
|
268
259
|
|
|
269
260
|
it('should remove a HOC by setting it to false', () => {
|
|
270
|
-
const withWrapper = (WrappedComponent: any) => (props: any) =>
|
|
271
|
-
|
|
272
|
-
props: { 'data-testid': 'hoc-wrapper' },
|
|
273
|
-
children: WrappedComponent(props),
|
|
274
|
-
key: null,
|
|
275
|
-
})
|
|
261
|
+
const withWrapper = (WrappedComponent: any) => (props: any) =>
|
|
262
|
+
h('div', { 'data-testid': 'hoc-wrapper' }, WrappedComponent(props))
|
|
276
263
|
|
|
277
264
|
const WithHoc = attrs({
|
|
278
265
|
name: 'Test',
|
|
@@ -284,7 +271,7 @@ describe('.compose() chaining', () => {
|
|
|
284
271
|
const result = WithoutHoc({ label: 'no-hoc' }) as any
|
|
285
272
|
// Should render base component directly, no wrapper
|
|
286
273
|
expect(result.props['data-testid']).toBe('base')
|
|
287
|
-
expect(result.children).
|
|
274
|
+
expect(result.children).toEqual(['no-hoc'])
|
|
288
275
|
})
|
|
289
276
|
})
|
|
290
277
|
|
|
@@ -359,12 +346,7 @@ describe('isAttrsComponent', () => {
|
|
|
359
346
|
// --------------------------------------------------------
|
|
360
347
|
describe('displayName resolution', () => {
|
|
361
348
|
it('should fall back to component.displayName when name is not provided', () => {
|
|
362
|
-
const NamedComponent = (props: any) => (
|
|
363
|
-
type: 'div',
|
|
364
|
-
props,
|
|
365
|
-
children: props.children,
|
|
366
|
-
key: null,
|
|
367
|
-
})
|
|
349
|
+
const NamedComponent = (props: any) => h('div', props, props.children)
|
|
368
350
|
NamedComponent.displayName = 'MyDisplayName'
|
|
369
351
|
|
|
370
352
|
const Component = attrsComponent({
|
|
@@ -381,12 +363,7 @@ describe('displayName resolution', () => {
|
|
|
381
363
|
|
|
382
364
|
it('should fall back to component.name when name and displayName are not provided', () => {
|
|
383
365
|
function ExplicitNameComponent(props: any) {
|
|
384
|
-
return
|
|
385
|
-
type: 'div',
|
|
386
|
-
props,
|
|
387
|
-
children: props.children,
|
|
388
|
-
key: null,
|
|
389
|
-
}
|
|
366
|
+
return h('div', props, props.children)
|
|
390
367
|
}
|
|
391
368
|
|
|
392
369
|
const Component = attrsComponent({
|
|
@@ -486,3 +463,69 @@ describe('deep chaining', () => {
|
|
|
486
463
|
expect(result.label).toBe('third')
|
|
487
464
|
})
|
|
488
465
|
})
|
|
466
|
+
|
|
467
|
+
// ─── attrs — real h() round-trip (parallel to the BaseComponent mocks) ──
|
|
468
|
+
//
|
|
469
|
+
// The tests above use a `BaseComponent` mock that returns
|
|
470
|
+
// `{ type, props, children, key }` literals, then assert against the
|
|
471
|
+
// `vnode.props` shape. That's the contract at the type level, but it
|
|
472
|
+
// skips the actual h() call shape — `h('div', props, ...children)`
|
|
473
|
+
// flattens children differently than the mock and may pass props
|
|
474
|
+
// through different normalization paths in the runtime. PR #197 was
|
|
475
|
+
// caused by exactly this kind of mock-vs-real divergence.
|
|
476
|
+
//
|
|
477
|
+
// This block re-runs the key attrs contracts through a base component
|
|
478
|
+
// that uses real `h()` from `@pyreon/core`. The mock tests stay as
|
|
479
|
+
// the fast unit-test path; these are the safety net.
|
|
480
|
+
|
|
481
|
+
describe('attrs — real h() round-trip', () => {
|
|
482
|
+
// BaseComponent that returns a real VNode via h(). Same shape as
|
|
483
|
+
// the mock, but built through the public h() API.
|
|
484
|
+
const BaseComponentH = (props: any) =>
|
|
485
|
+
h('div', { ...props, 'data-testid': 'base' }, props.children ?? props.label ?? null)
|
|
486
|
+
|
|
487
|
+
it('passes through props unchanged when no attrs defined', () => {
|
|
488
|
+
const Component = attrs({ name: 'BareH', component: BaseComponentH })
|
|
489
|
+
const result = (Component as any)({ label: 'hello', 'data-custom': 'yes' }) as any
|
|
490
|
+
expect(result.props.label).toBe('hello')
|
|
491
|
+
expect(result.props['data-custom']).toBe('yes')
|
|
492
|
+
expect(result.props['data-testid']).toBe('base')
|
|
493
|
+
})
|
|
494
|
+
|
|
495
|
+
it('applies attrs as default props through real h()', () => {
|
|
496
|
+
const Component = attrs({ name: 'WithAttrs', component: BaseComponentH }).attrs(
|
|
497
|
+
(_props: any) => ({ label: 'default' }),
|
|
498
|
+
)
|
|
499
|
+
const result = (Component as any)({}) as any
|
|
500
|
+
expect(result.props.label).toBe('default')
|
|
501
|
+
expect(result.type).toBe('div')
|
|
502
|
+
})
|
|
503
|
+
|
|
504
|
+
it('overrides default attrs with explicit props', () => {
|
|
505
|
+
const Component = attrs({ name: 'Overridable', component: BaseComponentH }).attrs(
|
|
506
|
+
(_props: any) => ({ label: 'default' }),
|
|
507
|
+
)
|
|
508
|
+
const result = (Component as any)({ label: 'explicit' }) as any
|
|
509
|
+
expect(result.props.label).toBe('explicit')
|
|
510
|
+
})
|
|
511
|
+
|
|
512
|
+
it('chains multiple attrs() calls through real h()', () => {
|
|
513
|
+
const Component = attrs({ name: 'Chained', component: BaseComponentH })
|
|
514
|
+
.attrs(() => ({ a: 1 }))
|
|
515
|
+
.attrs(() => ({ b: 2 }))
|
|
516
|
+
.attrs(() => ({ c: 3 }))
|
|
517
|
+
const result = (Component as any)({}) as any
|
|
518
|
+
expect(result.props.a).toBe(1)
|
|
519
|
+
expect(result.props.b).toBe(2)
|
|
520
|
+
expect(result.props.c).toBe(3)
|
|
521
|
+
})
|
|
522
|
+
|
|
523
|
+
it('later attrs override earlier ones (real h() parallel)', () => {
|
|
524
|
+
const Component = attrs({ name: 'OrderH', component: BaseComponentH })
|
|
525
|
+
.attrs(() => ({ label: 'first' }))
|
|
526
|
+
.attrs(() => ({ label: 'second' }))
|
|
527
|
+
.attrs(() => ({ label: 'third' }))
|
|
528
|
+
const result = (Component as any)({}) as any
|
|
529
|
+
expect(result.props.label).toBe('third')
|
|
530
|
+
})
|
|
531
|
+
})
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { h } from '@pyreon/core'
|
|
1
2
|
import createAttrsHOC from '../hoc/attrsHoc'
|
|
2
3
|
|
|
3
4
|
const Receiver = (props: any) => ({
|
|
@@ -134,3 +135,45 @@ describe('attrsHoc - ref passthrough', () => {
|
|
|
134
135
|
expect(result.props.ref).toBe(refObj)
|
|
135
136
|
})
|
|
136
137
|
})
|
|
138
|
+
|
|
139
|
+
// ─── attrsHoc — real h() round-trip (parallel to the Receiver mock) ──
|
|
140
|
+
//
|
|
141
|
+
// The Receiver above is a mock that returns a `{ type, props,
|
|
142
|
+
// children, key }` literal. The tests assert against that shape.
|
|
143
|
+
// This block re-runs the core HOC contracts against a Receiver that
|
|
144
|
+
// builds its return value via real `h()` from `@pyreon/core` —
|
|
145
|
+
// catches divergence between the mock shape and the actual VNode
|
|
146
|
+
// shape h() produces.
|
|
147
|
+
|
|
148
|
+
describe('attrsHoc — real h() round-trip', () => {
|
|
149
|
+
// Receiver that returns a real VNode via h() instead of a literal.
|
|
150
|
+
const ReceiverH = (props: any) =>
|
|
151
|
+
h('div', { ...props, 'data-testid': 'receiver' }, props.label ?? '')
|
|
152
|
+
|
|
153
|
+
it('passes through props unchanged when no attrs defined', () => {
|
|
154
|
+
const hoc = createAttrsHOC({ attrs: [], priorityAttrs: [] })
|
|
155
|
+
const Enhanced = hoc(ReceiverH as any)
|
|
156
|
+
const result = Enhanced({ label: 'hello', 'data-custom': 'yes' }) as any
|
|
157
|
+
expect(result.props.label).toBe('hello')
|
|
158
|
+
expect(result.props['data-custom']).toBe('yes')
|
|
159
|
+
expect(result.type).toBe('div')
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
it('applies attrs as default props through real h()', () => {
|
|
163
|
+
const hoc = createAttrsHOC({
|
|
164
|
+
attrs: [(_props: any) => ({ label: 'default' })],
|
|
165
|
+
priorityAttrs: [],
|
|
166
|
+
})
|
|
167
|
+
const Enhanced = hoc(ReceiverH as any)
|
|
168
|
+
const result = Enhanced({}) as any
|
|
169
|
+
expect(result.props.label).toBe('default')
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
it('passes ref through real h() output unchanged', () => {
|
|
173
|
+
const hoc = createAttrsHOC({ attrs: [], priorityAttrs: [] })
|
|
174
|
+
const Enhanced = hoc(ReceiverH as any)
|
|
175
|
+
const refObj = { current: null }
|
|
176
|
+
const result = Enhanced({ ref: refObj }) as any
|
|
177
|
+
expect(result.props.ref).toBe(refObj)
|
|
178
|
+
})
|
|
179
|
+
})
|
package/src/attrs.ts
CHANGED
|
@@ -8,6 +8,12 @@ import { chainOptions } from './utils/chaining'
|
|
|
8
8
|
import { calculateHocsFuncs } from './utils/compose'
|
|
9
9
|
import { createStaticsEnhancers } from './utils/statics'
|
|
10
10
|
|
|
11
|
+
// Dev-mode gate. `import.meta.env.DEV` is literal-replaced by Vite at build
|
|
12
|
+
// time and tree-shakes to zero bytes in prod. The previous
|
|
13
|
+
// `process.env.NODE_ENV !== 'production'` form was dead code in real Vite
|
|
14
|
+
// browser bundles (Vite does not polyfill `process`).
|
|
15
|
+
const __DEV__ = process.env.NODE_ENV !== 'production'
|
|
16
|
+
|
|
11
17
|
/**
|
|
12
18
|
* Clones the current configuration and merges new options, then creates a
|
|
13
19
|
* fresh component. This makes the chaining API immutable — each `.attrs()`
|
|
@@ -61,10 +67,9 @@ const attrsComponent: InitAttrsComponent = (options) => {
|
|
|
61
67
|
|
|
62
68
|
const filteredProps = needsFiltering ? omit(props, options.filterAttrs) : props
|
|
63
69
|
|
|
64
|
-
const finalProps =
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
: filteredProps
|
|
70
|
+
const finalProps = __DEV__
|
|
71
|
+
? { ...filteredProps, 'data-attrs': componentName }
|
|
72
|
+
: filteredProps
|
|
68
73
|
|
|
69
74
|
return RenderComponent(finalProps)
|
|
70
75
|
}
|
package/src/env.d.ts
ADDED
package/src/init.ts
CHANGED
|
@@ -3,6 +3,12 @@ import attrsComponent from './attrs'
|
|
|
3
3
|
import type { InitAttrsComponent } from './types/InitAttrsComponent'
|
|
4
4
|
import type { ElementType } from './types/utils'
|
|
5
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
|
+
|
|
6
12
|
/**
|
|
7
13
|
* Public entry point for creating an attrs-enhanced component.
|
|
8
14
|
*
|
|
@@ -24,7 +30,7 @@ export type Attrs = <C extends ElementType>({
|
|
|
24
30
|
|
|
25
31
|
const attrs: Attrs = ({ name, component }) => {
|
|
26
32
|
// Validate required params in development — fail fast with clear errors.
|
|
27
|
-
if (
|
|
33
|
+
if (__DEV__) {
|
|
28
34
|
type Errors = Partial<{
|
|
29
35
|
component: string
|
|
30
36
|
name: string
|
package/lib/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index2.d.ts","names":[],"sources":["../../src/types/attrs.ts","../../src/types/utils.ts","../../src/types/config.ts","../../src/types/hoc.ts","../../src/types/AttrsComponent.ts","../../src/types/configuration.ts","../../src/types/InitAttrsComponent.ts","../../src/init.ts","../../src/isAttrsComponent.ts"],"mappings":"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"}
|
package/lib/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["attrsHoc"],"sources":["../src/utils/attrs.ts","../src/hoc/attrsHoc.ts","../src/utils/chaining.ts","../src/utils/compose.ts","../src/utils/statics.ts","../src/attrs.ts","../src/init.ts","../src/isAttrsComponent.ts","../src/index.ts"],"sourcesContent":["import { isEmpty } from '@pyreon/ui-core'\n\n/**\n * Strips keys with `undefined` values from a props object.\n * This prevents undefined consumer props from overriding defaults\n * computed by `.attrs()` callbacks. Only explicitly set values\n * (including `null`) should override defaults.\n */\ntype RemoveUndefinedProps = <T extends Record<string, any>>(\n props: T,\n) => { [I in keyof T as T[I] extends undefined ? never : I]: T[I] }\n\nexport const removeUndefinedProps = (<T extends Record<string, any>>(props: T) =>\n Object.keys(props).reduce<Record<string, unknown>>((acc, key) => {\n const currentValue = props[key]\n if (currentValue !== undefined) acc[key] = currentValue\n return acc\n }, {})) as RemoveUndefinedProps\n\n/**\n * Reduces an array of option functions (from chained `.attrs()` calls)\n * into a single merged result. Each function is called with `args`\n * (typically the current props) and its return value is merged\n * left-to-right via Object.assign — so later `.attrs()` calls\n * override earlier ones.\n *\n * Returns a curried function: first call binds the chain, second\n * call provides the arguments and executes the reduction.\n */\ntype OptionFunc<A> = (...arg: A[]) => Record<string, unknown>\ntype CalculateChainOptions = <A>(\n options?: OptionFunc<A>[],\n) => (args: A[]) => ReturnType<OptionFunc<A>>\n\nexport const calculateChainOptions: CalculateChainOptions = (options) => (args) => {\n const result = {}\n if (!options || isEmpty(options)) return result\n\n return options.reduce((acc, item) => Object.assign(acc, item(...args)), {})\n}\n","import type { Configuration } from '../types/configuration'\nimport type { ComponentFn } from '../types/utils'\nimport { calculateChainOptions, removeUndefinedProps } from '../utils/attrs'\n\nexport type AttrsStyleHOC = ({\n attrs,\n priorityAttrs,\n}: Pick<Configuration, 'attrs' | 'priorityAttrs'>) => (\n WrappedComponent: ComponentFn<any>,\n) => ComponentFn<any>\n\n/**\n * Creates the core HOC that computes default props from the `.attrs()` chain.\n *\n * This is always the outermost HOC in the compose chain, so it runs first.\n * It resolves both priority and normal attrs callbacks, then merges them\n * with the consumer's explicit props following this precedence:\n *\n * priorityAttrs < normalAttrs < explicit props (last wins)\n *\n * In Pyreon, components are plain functions — no forwardRef needed.\n * The ref flows as a normal prop through the chain.\n */\nconst createAttrsHOC: AttrsStyleHOC = ({ attrs, priorityAttrs }) => {\n // Pre-build the chain reducers once (not per render).\n const calculateAttrs = calculateChainOptions(attrs)\n const calculatePriorityAttrs = calculateChainOptions(priorityAttrs)\n\n const attrsHoc = (WrappedComponent: ComponentFn<any>) => {\n const HOCComponent: ComponentFn<any> = (props) => {\n // Strip undefined values so they don't shadow defaults from attrs callbacks.\n const filteredProps = removeUndefinedProps(props)\n\n // 1. Resolve priority attrs (lowest precedence defaults).\n const prioritizedAttrs = calculatePriorityAttrs([filteredProps])\n // 2. Resolve normal attrs — these see priority + explicit props as input.\n const finalAttrs = calculateAttrs([\n {\n ...prioritizedAttrs,\n ...filteredProps,\n },\n ])\n\n // 3. Merge: priority < normal attrs < explicit props (last wins).\n const finalProps = {\n ...prioritizedAttrs,\n ...finalAttrs,\n ...filteredProps,\n }\n\n return WrappedComponent(finalProps)\n }\n\n return HOCComponent\n }\n\n return attrsHoc\n}\n\nexport default createAttrsHOC\n","type Func = (...args: any) => Record<string, unknown>\ntype Obj = Record<string, unknown>\n\n/**\n * Appends a new attrs option to the existing chain of option functions.\n *\n * The `.attrs()` API accepts either an object or a callback. This function\n * normalizes both forms into a function (objects are wrapped in `() => obj`)\n * and appends to the existing array. The array is cloned so each chained\n * component gets its own copy — maintaining immutability across the chain.\n */\ntype ChainOptions = (opts: Obj | Func | undefined, defaultOpts: Func[]) => Func[]\n\nexport const chainOptions: ChainOptions = (opts, defaultOpts = []) => {\n const result = [...defaultOpts]\n\n if (typeof opts === 'function') result.push(opts)\n else if (typeof opts === 'object') result.push(() => opts)\n\n return result\n}\n","/**\n * Extracts HOC functions from the `.compose()` configuration and reverses\n * them for correct application order. Setting a key to `null`, `undefined`,\n * or `false` removes a previously defined HOC — only actual functions are kept.\n *\n * The reversal is needed because `compose(a, b, c)(Component)` applies as\n * `a(b(c(Component)))`, so the last-defined HOC should wrap innermost.\n */\ntype CalculateHocsFuncs = (options: Record<string, any>) => ((arg: any) => any)[]\n\nexport const calculateHocsFuncs: CalculateHocsFuncs = (options = {}) =>\n Object.values(options)\n .filter((item) => typeof item === 'function')\n .reverse()\n","import { isEmpty } from '@pyreon/ui-core'\n\n/**\n * Copies user-defined statics from `.statics()` into the component's\n * `meta` object. These are accessible at `Component.meta.myStatic`.\n */\ntype CreateStaticsEnhancers = (params: {\n context: Record<string, any>\n options: Record<string, any>\n}) => void\n\nexport const createStaticsEnhancers: CreateStaticsEnhancers = ({ context, options }) => {\n if (!isEmpty(options)) {\n Object.assign(context, options)\n }\n}\n","import { compose, hoistNonReactStatics, omit, pick } from '@pyreon/ui-core'\nimport { attrsHoc } from './hoc'\nimport type { AttrsComponent as AttrsComponentType } from './types/AttrsComponent'\nimport type { Configuration, ExtendedConfiguration } from './types/configuration'\nimport type { InitAttrsComponent } from './types/InitAttrsComponent'\nimport { calculateChainOptions } from './utils/attrs'\nimport { chainOptions } from './utils/chaining'\nimport { calculateHocsFuncs } from './utils/compose'\nimport { createStaticsEnhancers } from './utils/statics'\n\n/**\n * Clones the current configuration and merges new options, then creates a\n * fresh component. This makes the chaining API immutable — each `.attrs()`\n * / `.config()` / `.statics()` call returns a brand-new component with an\n * updated configuration rather than mutating the existing one.\n */\ntype CloneAndEnhance = (\n defaultOpts: Configuration,\n opts: Partial<ExtendedConfiguration>,\n) => ReturnType<typeof attrsComponent>\n\nconst cloneAndEnhance: CloneAndEnhance = (defaultOpts, opts) =>\n attrsComponent({\n ...defaultOpts,\n ...(opts.name ? { name: opts.name } : undefined),\n ...(opts.component ? { component: opts.component } : undefined),\n attrs: chainOptions(opts.attrs, defaultOpts.attrs),\n filterAttrs: [...(defaultOpts.filterAttrs ?? []), ...(opts.filterAttrs ?? [])],\n priorityAttrs: chainOptions(opts.priorityAttrs, defaultOpts.priorityAttrs),\n statics: { ...defaultOpts.statics, ...opts.statics },\n compose: { ...defaultOpts.compose, ...opts.compose },\n } as Parameters<typeof attrsComponent>[0])\n\n/**\n * Core factory that builds an attrs-enhanced Pyreon component.\n *\n * Creates a plain ComponentFn that:\n * 1. Wraps the original with attrsHoc (default props) + user HOCs from `.compose()`.\n * 2. Filters out internal props listed in `filterAttrs`.\n * 3. Attaches `data-attrs` attribute in development for debugging.\n *\n * Then adds chaining methods (`.attrs()`, `.config()`, `.compose()`, `.statics()`)\n * as static properties — each calls `cloneAndEnhance` to produce a new component.\n *\n * In Pyreon, there is no forwardRef — ref flows as a normal prop.\n * Components are plain functions that run once per mount.\n */\nconst attrsComponent: InitAttrsComponent = (options) => {\n const componentName = options.name ?? options.component.displayName ?? options.component.name\n\n const RenderComponent = options.component\n\n // Build the HOC chain: attrsHoc is always first (resolves default props),\n // followed by user-composed HOCs in reverse order (outermost wraps first).\n const hocsFuncs = [attrsHoc(options), ...calculateHocsFuncs(options.compose)]\n\n // The inner component receives already-computed props from the HOC chain.\n // It handles prop filtering and final rendering.\n const EnhancedComponent = (props: Record<string, any>) => {\n const needsFiltering = options.filterAttrs && options.filterAttrs.length > 0\n\n const filteredProps = needsFiltering ? omit(props, options.filterAttrs) : props\n\n const finalProps =\n process.env.NODE_ENV !== 'production'\n ? { ...filteredProps, 'data-attrs': componentName }\n : filteredProps\n\n return RenderComponent(finalProps)\n }\n\n // Apply the full HOC chain: compose(attrsHoc, ...userHocs)(EnhancedComponent)\n const AttrsComponent: AttrsComponentType = compose(...hocsFuncs)(EnhancedComponent)\n\n AttrsComponent.IS_ATTRS = true\n AttrsComponent.displayName = componentName\n AttrsComponent.meta = {}\n\n // Copy static properties from the original component.\n hoistNonReactStatics(AttrsComponent, options.component)\n\n // Populate `component.meta` with user-defined statics from `.statics()`.\n createStaticsEnhancers({\n context: AttrsComponent.meta,\n options: options.statics,\n })\n\n // ─── Chaining Methods ──────────────────────────────────\n // Each method creates a new component via cloneAndEnhance.\n // The original component is never mutated.\n Object.assign(AttrsComponent, {\n attrs: (attrs: any, { priority, filter }: any = {}) => {\n const result: Record<string, any> = {}\n\n if (filter) {\n result.filterAttrs = filter\n }\n\n if (priority) {\n result.priorityAttrs = attrs as ExtendedConfiguration['priorityAttrs']\n\n return cloneAndEnhance(options, result)\n }\n\n result.attrs = attrs as ExtendedConfiguration['attrs']\n\n return cloneAndEnhance(options, result)\n },\n\n config: (opts: any = {}) => {\n const result = pick(opts)\n\n return cloneAndEnhance(options, result)\n },\n\n compose: (opts: any) => cloneAndEnhance(options, { compose: opts }),\n\n statics: (opts: any) => cloneAndEnhance(options, { statics: opts }),\n\n getDefaultAttrs: (props: any) => calculateChainOptions(options.attrs)([props]),\n })\n\n return AttrsComponent\n}\n\nexport default attrsComponent\n","import { isEmpty } from '@pyreon/ui-core'\nimport attrsComponent from './attrs'\nimport type { InitAttrsComponent } from './types/InitAttrsComponent'\nimport type { ElementType } from './types/utils'\n\n/**\n * Public entry point for creating an attrs-enhanced component.\n *\n * ```tsx\n * const Button = attrs({ name: 'Button', component: Element })\n * .attrs({ tag: 'button' })\n * .attrs<{ primary?: boolean }>(({ primary }) => ({\n * backgroundColor: primary ? 'blue' : 'gray',\n * }))\n * ```\n */\nexport type Attrs = <C extends ElementType>({\n name,\n component,\n}: {\n name: string\n component: C\n}) => ReturnType<InitAttrsComponent<C>>\n\nconst attrs: Attrs = ({ name, component }) => {\n // Validate required params in development — fail fast with clear errors.\n if (process.env.NODE_ENV !== 'production') {\n type Errors = Partial<{\n component: string\n name: string\n }>\n\n const errors: Errors = {}\n if (!component) {\n errors.component = 'Parameter `component` is missing in params!'\n }\n\n if (!name) {\n errors.name = 'Parameter `name` is missing in params!'\n }\n\n if (!isEmpty(errors)) {\n throw Error(JSON.stringify(errors))\n }\n }\n\n // Bootstrap with empty configuration — all chains start from scratch.\n return attrsComponent({\n name,\n component,\n attrs: [],\n priorityAttrs: [],\n filterAttrs: [],\n compose: {},\n statics: {},\n })\n}\n\nexport default attrs\n","export type IsAttrsComponent = <T>(component: T) => boolean\n\n/** Runtime type guard — checks if a component was created by `attrs()`. */\nconst isAttrsComponent: IsAttrsComponent = (component) => {\n if (\n component &&\n (typeof component === 'object' || typeof component === 'function') &&\n Object.hasOwn(component as object, 'IS_ATTRS')\n ) {\n return true\n }\n\n return false\n}\n\nexport default isAttrsComponent\n","import type { Attrs } from './init'\nimport attrs from './init'\nimport type { IsAttrsComponent } from './isAttrsComponent'\nimport isAttrsComponent from './isAttrsComponent'\nimport type { AttrsComponent } from './types/AttrsComponent'\nimport type { AttrsCb } from './types/attrs'\nimport type { AttrsComponentType, ConfigAttrs } from './types/config'\nimport type { ComposeParam, GenericHoc } from './types/hoc'\nimport type { ComponentFn, ElementType, TObj } from './types/utils'\n\nexport type {\n Attrs,\n AttrsCb,\n AttrsComponent,\n AttrsComponentType,\n ComponentFn,\n ComposeParam,\n ConfigAttrs,\n ElementType,\n GenericHoc,\n IsAttrsComponent,\n TObj,\n}\n\nexport { attrs, isAttrsComponent }\nexport default attrs\n"],"mappings":"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"}
|