@pyreon/elements 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.
Files changed (70) hide show
  1. package/package.json +10 -12
  2. package/src/Element/component.tsx +0 -315
  3. package/src/Element/constants.ts +0 -96
  4. package/src/Element/index.ts +0 -6
  5. package/src/Element/types.ts +0 -168
  6. package/src/Element/utils.ts +0 -15
  7. package/src/List/component.tsx +0 -105
  8. package/src/List/index.ts +0 -5
  9. package/src/Overlay/component.tsx +0 -140
  10. package/src/Overlay/context.tsx +0 -36
  11. package/src/Overlay/index.ts +0 -7
  12. package/src/Overlay/positioning.ts +0 -191
  13. package/src/Overlay/useOverlay.tsx +0 -461
  14. package/src/Portal/component.tsx +0 -54
  15. package/src/Portal/index.ts +0 -5
  16. package/src/Text/component.tsx +0 -67
  17. package/src/Text/index.ts +0 -5
  18. package/src/Text/styled.ts +0 -30
  19. package/src/Util/component.tsx +0 -43
  20. package/src/Util/index.ts +0 -5
  21. package/src/__tests__/Content.test.tsx +0 -123
  22. package/src/__tests__/Element-slot-reactivity.browser.test.tsx +0 -152
  23. package/src/__tests__/Element.test.ts +0 -819
  24. package/src/__tests__/Iterator.test.ts +0 -492
  25. package/src/__tests__/Iterator.types.test.ts +0 -237
  26. package/src/__tests__/List.test.ts +0 -199
  27. package/src/__tests__/Overlay.test.ts +0 -492
  28. package/src/__tests__/Portal.test.ts +0 -156
  29. package/src/__tests__/Text.test.ts +0 -274
  30. package/src/__tests__/Util.test.ts +0 -63
  31. package/src/__tests__/Wrapper-innerhtml.test.tsx +0 -178
  32. package/src/__tests__/Wrapper.test.tsx +0 -196
  33. package/src/__tests__/elements.browser.test.tsx +0 -132
  34. package/src/__tests__/equalBeforeAfter.test.ts +0 -122
  35. package/src/__tests__/helpers.test.ts +0 -65
  36. package/src/__tests__/integration.test.tsx +0 -118
  37. package/src/__tests__/internElementBundle.test.ts +0 -102
  38. package/src/__tests__/iterator-function-children.test.tsx +0 -120
  39. package/src/__tests__/native-markers.test.ts +0 -13
  40. package/src/__tests__/overlayContext.test.tsx +0 -78
  41. package/src/__tests__/perf-stress.browser.test.tsx +0 -119
  42. package/src/__tests__/positioning.test.ts +0 -90
  43. package/src/__tests__/responsiveProps.test.ts +0 -328
  44. package/src/__tests__/slot-component-reference.test.tsx +0 -157
  45. package/src/__tests__/useOverlay.test.ts +0 -1336
  46. package/src/__tests__/utils.test.ts +0 -69
  47. package/src/__tests__/wrapper-block-cascade.test.ts +0 -121
  48. package/src/constants.ts +0 -1
  49. package/src/env.d.ts +0 -6
  50. package/src/helpers/Content/component.tsx +0 -75
  51. package/src/helpers/Content/index.ts +0 -3
  52. package/src/helpers/Content/styled.ts +0 -105
  53. package/src/helpers/Content/types.ts +0 -49
  54. package/src/helpers/Iterator/component.tsx +0 -316
  55. package/src/helpers/Iterator/index.ts +0 -30
  56. package/src/helpers/Iterator/types.ts +0 -138
  57. package/src/helpers/Wrapper/component.tsx +0 -180
  58. package/src/helpers/Wrapper/constants.ts +0 -10
  59. package/src/helpers/Wrapper/index.ts +0 -3
  60. package/src/helpers/Wrapper/styled.ts +0 -64
  61. package/src/helpers/Wrapper/types.ts +0 -56
  62. package/src/helpers/Wrapper/utils.ts +0 -7
  63. package/src/helpers/index.ts +0 -4
  64. package/src/helpers/internElementBundle.ts +0 -37
  65. package/src/helpers/isPyreonComponent.ts +0 -46
  66. package/src/index.ts +0 -42
  67. package/src/manifest.ts +0 -190
  68. package/src/tests/manifest-snapshot.test.ts +0 -45
  69. package/src/types.ts +0 -112
  70. package/src/utils.ts +0 -5
@@ -1,237 +0,0 @@
1
- /**
2
- * Compile-time type tests for Iterator + List overloads.
3
- *
4
- * The public callable interface ships FOUR overloads in priority order:
5
- *
6
- * 1. SimpleProps<T extends SimpleValue> — `valueName` allowed, no `children`
7
- * 2. ObjectProps<T extends ObjectValue> — `valueName` FORBIDDEN, no `children`
8
- * 3. ChildrenProps — `children` required, no `data`/`component`
9
- * 4. LooseProps — fallback for forwarding patterns
10
- *
11
- * The first three drive per-mode T inference and stricter constraints for
12
- * direct callers. The 4th (LooseProps — added in PR #229's mirror) exists
13
- * so that wide-union props produced by `@pyreon/rocketstyle`'s 4-overload-
14
- * aware `ExtractProps` (PR #222 mirror) have a binding home. Pre-fallback
15
- * the wide union failed to bind to any narrow overload and TS reported
16
- * "no overload matches this call" at every forwarding site.
17
- *
18
- * Trade-off: adding the loose fallback intentionally weakens the strict
19
- * per-mode constraints for DIRECT callers too — a call that doesn't match
20
- * Simple / Object / Children will now match LooseProps and compile. This
21
- * matches vitus-labs's design choice (PR #229): forwarding-pattern support
22
- * is more valuable than mixed-shape rejection at the type level. Runtime
23
- * still picks the right mode based on the data shape.
24
- *
25
- * Regression: pre-PR-5 (4-overload `ExtractProps`), Pyreon's Iterator type
26
- * collapsed all three narrow modes when wrapped through `rocketstyle()` /
27
- * `attrs()` — only the LAST overload's props survived. PR #5 + PR #7
28
- * together restore the full union AND give it a binding home.
29
- */
30
-
31
- import { describe, expectTypeOf, it } from 'vitest'
32
- import { h } from '@pyreon/core'
33
- import Iterator from '../helpers/Iterator/component'
34
- import List from '../List/component'
35
- import type {
36
- ChildrenProps,
37
- LooseProps,
38
- ObjectProps,
39
- Props,
40
- SimpleProps,
41
- } from '../helpers/Iterator/types'
42
-
43
- describe('Iterator — Props<T> generic dispatch', () => {
44
- it('Props<string> narrows to SimpleProps<string>', () => {
45
- expectTypeOf<Props<string>>().toEqualTypeOf<SimpleProps<string>>()
46
- })
47
-
48
- it('Props<{ id: number; name: string }> narrows to ObjectProps<...>', () => {
49
- type User = { id: number; name: string }
50
- expectTypeOf<Props<User>>().toEqualTypeOf<ObjectProps<User>>()
51
- })
52
-
53
- it('Props<unknown> (default) falls back to loose props', () => {
54
- // The default Props (no T) MUST accept the legacy untyped call surface.
55
- // Smoke check: `data: any[]` shape continues to typecheck without
56
- // narrowing.
57
- type Default = Props
58
- const _ok: Default = { data: ['a', 1, null], component: 'div' }
59
- void _ok
60
- })
61
- })
62
-
63
- describe('Iterator — happy-path overload selection', () => {
64
- const Item = (p: { children?: unknown }) => h('span', null, p.children as never)
65
-
66
- it('SimpleProps mode: valueName allowed', () => {
67
- // Direct call with primitive data + valueName → SimpleProps overload
68
- Iterator({
69
- data: ['a', 'b'] as string[],
70
- component: Item,
71
- valueName: 'text',
72
- })
73
-
74
- // Mixed shape (children + data) now falls through to LooseProps — by
75
- // design after PR #229's mirror. Strict per-mode rejection is no longer
76
- // enforced at the type level; runtime picks the right path based on
77
- // which props are present. This compiles and that's intentional.
78
- Iterator({
79
- data: ['a', 'b'] as string[],
80
- component: Item,
81
- children: h('span', null, 'leaked'),
82
- })
83
- })
84
-
85
- it('ObjectProps mode: valueName FORBIDDEN by Object overload but accepted by Loose', () => {
86
- type Row = { id: number; label: string }
87
- Iterator({
88
- data: [{ id: 1, label: 'a' }] as Row[],
89
- component: Item,
90
- })
91
-
92
- // `valueName: 'row'` doesn't match ObjectProps' `valueName?: never`, but
93
- // the LooseProps fallback accepts it. Pre-PR-7 this errored; now it's a
94
- // legal forwarding shape.
95
- Iterator({
96
- data: [{ id: 1, label: 'a' }] as Row[],
97
- component: Item,
98
- valueName: 'row',
99
- })
100
- })
101
-
102
- it('ChildrenProps mode: clean form picked when only children supplied', () => {
103
- Iterator({ children: h('span', null, 'hi') })
104
-
105
- // Mixing children with data / component used to be a hard error.
106
- // Post-PR-7 the LooseProps fallback accepts these — runtime decides
107
- // which mode fires based on which fields are populated.
108
- Iterator({
109
- children: h('span', null, 'hi'),
110
- data: [1, 2, 3],
111
- })
112
-
113
- Iterator({
114
- children: h('span', null, 'hi'),
115
- component: Item,
116
- })
117
- })
118
- })
119
-
120
- describe('Iterator + List — LooseProps fallback for forwarding patterns (PR #7)', () => {
121
- const Item = (p: { children?: unknown }) => h('span', null, p.children as never)
122
-
123
- it('LooseProps shape binds via the 4th overload (no overload-mismatch error)', () => {
124
- // The motivating shape: a wide-union props object produced by
125
- // `Partial<(typeof Wrapper)['$$types']>` (rocketstyle's $$types after
126
- // PR #5's 4-overload ExtractProps distributes the union). Without the
127
- // loose fallback overload, this fails at every forwarding call site
128
- // with "no overload matches this call" — the wide union doesn't bind
129
- // to SimpleProps<T> / ObjectProps<T> / ChildrenProps individually.
130
- const looseForwarded: LooseProps = {
131
- data: ['a', 'b'],
132
- component: Item,
133
- valueName: 'text',
134
- }
135
- Iterator(looseForwarded)
136
- // Cast preserves the LooseProps binding (the conditional Props<T>
137
- // exposes LooseProps when T defaults to unknown).
138
- Iterator(looseForwarded as Props)
139
- })
140
-
141
- it('partial / empty shapes are accepted via LooseProps', () => {
142
- // Empty object — no narrow overload matches (data missing for Simple/
143
- // Object, children missing for Children) but LooseProps' fields are
144
- // all optional. This is the genuine forwarding shape from props spread.
145
- const empty: LooseProps = {}
146
- Iterator(empty)
147
-
148
- // Object with just `data` (no component) — falls through to LooseProps.
149
- Iterator({ data: ['a'] as string[] } as LooseProps)
150
- })
151
-
152
- it('List inherits the LooseProps fallback overload', () => {
153
- const looseForwarded: LooseProps = {
154
- data: [{ id: 1, name: 'A' }],
155
- component: Item,
156
- }
157
- // List's 4th overload mirrors Iterator's — wide unions bind here too.
158
- List({ ...looseForwarded, rootElement: true })
159
- })
160
-
161
- it('the loose fallback is the 4th overload (order matters for inference)', () => {
162
- // Direct callers that DO match SimpleProps shape should still drive
163
- // T inference from `data` — i.e. the overload picked at the call site
164
- // is the FIRST one matching, not LooseProps. This is what preserves
165
- // the strict per-mode constraints for the direct-caller happy path.
166
- //
167
- // We can't introspect "which overload TS picked" directly, but we CAN
168
- // prove SimpleProps<T>'s `valueName?: string` survives — a LooseProps
169
- // pick would lose the per-mode field constraints. The fact that the
170
- // existing `expectTypeOf<Props<string>>().toEqualTypeOf<SimpleProps<string>>()`
171
- // in the first describe block passes is the structural anchor.
172
- type Props_string = Props<string>
173
- expectTypeOf<Props_string>().toEqualTypeOf<SimpleProps<string>>()
174
- // Negative: when T is unparameterized, Props falls back to LooseProps
175
- // by design (the `unknown extends T` clause in Props<T>'s definition).
176
- expectTypeOf<Props>().toEqualTypeOf<LooseProps>()
177
- })
178
- })
179
-
180
- describe('List — generic flow + Element prop forwarding', () => {
181
- const Card = (p: { children?: unknown }) => h('div', null, p.children as never)
182
-
183
- it('inherits Iterator overload constraints', () => {
184
- type User = { id: number; name: string }
185
- List({
186
- data: [{ id: 1, name: 'Alice' }] as User[],
187
- component: Card,
188
- rootElement: true,
189
- })
190
-
191
- // ObjectProps mode forbids `valueName`, but the LooseProps fallback
192
- // accepts it — same trade-off as Iterator (see top-of-file comment).
193
- List({
194
- data: [{ id: 1, name: 'Alice' }] as User[],
195
- component: Card,
196
- valueName: 'user',
197
- })
198
- })
199
-
200
- it('forwards Element layout props (tag, direction, alignX, …)', () => {
201
- List({
202
- data: ['a', 'b'] as string[],
203
- component: Card,
204
- valueName: 'text',
205
- rootElement: true,
206
- tag: 'ul',
207
- direction: 'rows',
208
- alignX: 'center',
209
- })
210
- })
211
-
212
- it('rejects Element label/content (List-specific blacklist)', () => {
213
- List({
214
- children: h('span', null, 'hi'),
215
- // @ts-expect-error — List forbids `label` (ListOnly: label?: never)
216
- label: 'oops',
217
- })
218
-
219
- List({
220
- children: h('span', null, 'hi'),
221
- // @ts-expect-error — List forbids `content` (ListOnly: content?: never)
222
- content: 'oops',
223
- })
224
- })
225
- })
226
-
227
- describe('Children-vs-data type discrimination', () => {
228
- it('ChildrenProps and SimpleProps are mutually exclusive', () => {
229
- // The strict overloads pick exactly one mode. ChildrenProps' `data: never`
230
- // and SimpleProps' `children: never` ensure they can't be unified into
231
- // one shape — verified at the type level here.
232
- type C = ChildrenProps
233
- type S = SimpleProps<string>
234
- expectTypeOf<C['data']>().toEqualTypeOf<undefined>()
235
- expectTypeOf<S['children']>().toEqualTypeOf<undefined>()
236
- })
237
- })
@@ -1,199 +0,0 @@
1
- import type { ComponentFn, VNode } from '@pyreon/core'
2
- import { h } from '@pyreon/core'
3
- import { describe, expect, it } from 'vitest'
4
- import { Element } from '../Element'
5
- import Iterator from '../helpers/Iterator'
6
- import { List } from '../List'
7
-
8
- const asVNode = (v: unknown) => v as VNode
9
-
10
- describe('List', () => {
11
- describe('statics', () => {
12
- it('has correct displayName', () => {
13
- expect(List.displayName).toBe('@pyreon/elements/List')
14
- })
15
-
16
- it('has correct pkgName', () => {
17
- expect(List.pkgName).toBe('@pyreon/elements')
18
- })
19
-
20
- it('has correct PYREON__COMPONENT', () => {
21
- expect(List.PYREON__COMPONENT).toBe('@pyreon/elements/List')
22
- })
23
- })
24
-
25
- describe('rootElement = false (default)', () => {
26
- it('returns a VNode whose type is Iterator', () => {
27
- const Comp: ComponentFn = (props: any) => h('span', null, props.children)
28
- const result = asVNode(
29
- List({
30
- data: ['a', 'b'],
31
- component: Comp,
32
- }),
33
- )
34
-
35
- expect(result.type).toBe(Iterator)
36
- })
37
-
38
- it('passes iterator-related props to the Iterator VNode', () => {
39
- const Comp: ComponentFn = (props: any) => h('span', null, props.children)
40
- const data = ['a', 'b', 'c']
41
- const itemKeyFn = (_item: unknown, i: number) => i
42
- const itemPropsFn = () => ({})
43
- const WrapComp: ComponentFn = (props: any) => h('div', null, ...props.children)
44
-
45
- const result = asVNode(
46
- List({
47
- data,
48
- component: Comp,
49
- itemKey: itemKeyFn,
50
- itemProps: itemPropsFn,
51
- valueName: 'label',
52
- wrapComponent: WrapComp,
53
- wrapProps: { className: 'wrap' },
54
- }),
55
- )
56
-
57
- expect(result.type).toBe(Iterator)
58
- expect(result.props.data).toBe(data)
59
- expect(result.props.component).toBe(Comp)
60
- expect(result.props.itemKey).toBe(itemKeyFn)
61
- expect(result.props.itemProps).toBe(itemPropsFn)
62
- expect(result.props.valueName).toBe('label')
63
- expect(result.props.wrapComponent).toBe(WrapComp)
64
- expect(result.props.wrapProps).toEqual({ className: 'wrap' })
65
- })
66
-
67
- it('does not pass non-iterator props to Iterator', () => {
68
- const Comp: ComponentFn = (props: any) => h('span', null, props.children)
69
- const result = asVNode(
70
- List({
71
- data: ['a'],
72
- component: Comp,
73
- block: true,
74
- gap: 8,
75
- direction: 'rows',
76
- } as any),
77
- )
78
-
79
- expect(result.type).toBe(Iterator)
80
- expect(result.props.block).toBeUndefined()
81
- expect(result.props.gap).toBeUndefined()
82
- expect(result.props.direction).toBeUndefined()
83
- })
84
-
85
- it('forwards children prop to Iterator', () => {
86
- const child = h('span', null, 'hello')
87
- const result = asVNode(List({ children: child }))
88
-
89
- expect(result.type).toBe(Iterator)
90
- expect(result.props.children).toBe(child)
91
- })
92
- })
93
-
94
- describe('rootElement = true', () => {
95
- it('returns a VNode whose type is Element', () => {
96
- const Comp: ComponentFn = (props: any) => h('span', null, props.children)
97
- const result = asVNode(
98
- List({
99
- data: ['a'],
100
- component: Comp,
101
- rootElement: true,
102
- }),
103
- )
104
-
105
- expect(result.type).toBe(Element)
106
- })
107
-
108
- it('passes layout props to the Element VNode', () => {
109
- const Comp: ComponentFn = (props: any) => h('span', null, props.children)
110
- const result = asVNode(
111
- List({
112
- data: ['a'],
113
- component: Comp,
114
- rootElement: true,
115
- block: true,
116
- gap: 8,
117
- direction: 'rows',
118
- } as any),
119
- )
120
-
121
- expect(result.type).toBe(Element)
122
- expect(result.props.block).toBe(true)
123
- expect(result.props.gap).toBe(8)
124
- expect(result.props.direction).toBe('rows')
125
- })
126
-
127
- it('does not pass iterator-reserved props to Element', () => {
128
- const Comp: ComponentFn = (props: any) => h('span', null, props.children)
129
- const result = asVNode(
130
- List({
131
- data: ['x'],
132
- component: Comp,
133
- rootElement: true,
134
- valueName: 'label',
135
- }),
136
- )
137
-
138
- expect(result.type).toBe(Element)
139
- // Iterator-reserved props should not leak to Element
140
- expect(result.props.data).toBeUndefined()
141
- expect(result.props.component).toBeUndefined()
142
- expect(result.props.valueName).toBeUndefined()
143
- })
144
-
145
- it('nests an Iterator VNode as children of Element', () => {
146
- const Comp: ComponentFn = (props: any) => h('span', null, props.children)
147
- const data = ['a', 'b']
148
- const result = asVNode(
149
- List({
150
- data,
151
- component: Comp,
152
- rootElement: true,
153
- }),
154
- )
155
-
156
- expect(result.type).toBe(Element)
157
-
158
- // The children of Element should contain the Iterator VNode
159
- const children = result.props.children as unknown
160
- const iteratorNode = asVNode(Array.isArray(children) ? children[0] : children)
161
- expect(iteratorNode.type).toBe(Iterator)
162
- expect(iteratorNode.props.data).toBe(data)
163
- expect(iteratorNode.props.component).toBe(Comp)
164
- })
165
-
166
- it('forwards ref to Element', () => {
167
- const Comp: ComponentFn = (props: any) => h('span', null, props.children)
168
- const refFn = (_node: unknown) => {
169
- /* noop */
170
- }
171
- const result = asVNode(
172
- List({
173
- data: ['a'],
174
- component: Comp,
175
- rootElement: true,
176
- ref: refFn,
177
- } as any),
178
- )
179
-
180
- expect(result.type).toBe(Element)
181
- expect(result.props.ref).toBe(refFn)
182
- })
183
- })
184
-
185
- describe('Iterator.RESERVED_PROPS', () => {
186
- it('contains the expected prop names', () => {
187
- expect(Iterator.RESERVED_PROPS).toEqual([
188
- 'children',
189
- 'component',
190
- 'wrapComponent',
191
- 'data',
192
- 'itemKey',
193
- 'valueName',
194
- 'itemProps',
195
- 'wrapProps',
196
- ])
197
- })
198
- })
199
- })