@pyreon/elements 0.24.5 → 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,316 +0,0 @@
1
- /**
2
- * Data-driven list renderer that supports three input modes: children,
3
- * an array of primitives, or an array of objects.
4
- * Each item receives positional metadata (first, last, odd, even, position)
5
- * and optional injected props via `itemProps`. Items can be individually
6
- * wrapped with `wrapComponent`. Children always take priority over the
7
- * component+data prop pattern.
8
- */
9
-
10
- import type { VNode, VNodeChild } from '@pyreon/core'
11
- import { Fragment } from '@pyreon/core'
12
- import { isEmpty, render } from '@pyreon/ui-core'
13
- import type {
14
- ChildrenProps,
15
- ExtendedProps,
16
- LooseProps,
17
- ObjectProps,
18
- ObjectValue,
19
- SimpleProps,
20
- SimpleValue,
21
- } from './types'
22
-
23
- type ClassifiedData =
24
- | { type: 'simple'; data: SimpleValue[] }
25
- | { type: 'complex'; data: ObjectValue[] }
26
- | null
27
-
28
- const classifyData = (data: unknown[]): ClassifiedData => {
29
- const items = data.filter(
30
- (item) =>
31
- item != null && !(typeof item === 'object' && isEmpty(item as Record<string, unknown>)),
32
- )
33
-
34
- if (items.length === 0) return null
35
-
36
- let isSimple = true
37
- let isComplex = true
38
-
39
- for (const item of items) {
40
- if (typeof item === 'string' || typeof item === 'number') {
41
- isComplex = false
42
- } else if (typeof item === 'object') {
43
- isSimple = false
44
- } else {
45
- isSimple = false
46
- isComplex = false
47
- }
48
- }
49
-
50
- if (isSimple) return { type: 'simple', data: items as SimpleValue[] }
51
- if (isComplex) return { type: 'complex', data: items as ObjectValue[] }
52
- return null
53
- }
54
-
55
- const RESERVED_PROPS = [
56
- 'children',
57
- 'component',
58
- 'wrapComponent',
59
- 'data',
60
- 'itemKey',
61
- 'valueName',
62
- 'itemProps',
63
- 'wrapProps',
64
- ] as const
65
-
66
- type AttachItemProps = ({ i, length }: { i: number; length: number }) => ExtendedProps
67
-
68
- const attachItemProps: AttachItemProps = ({ i, length }: { i: number; length: number }) => {
69
- const position = i + 1
70
-
71
- return {
72
- index: i,
73
- first: position === 1,
74
- last: position === length,
75
- odd: position % 2 === 1,
76
- even: position % 2 === 0,
77
- position,
78
- }
79
- }
80
-
81
- const Component = (props: LooseProps) => {
82
- const {
83
- itemKey,
84
- valueName,
85
- children: rawChildren,
86
- component,
87
- data,
88
- wrapComponent: Wrapper,
89
- wrapProps,
90
- itemProps,
91
- } = props
92
-
93
- // Unwrap the Pyreon compiler's `() => x` accessor wrap. When the parent
94
- // emits `<Iterator>{items}</Iterator>` and the compiler-emitted form is
95
- // `Iterator({ children: () => items })`, the downstream `Array.isArray`
96
- // check returns false, the Fragment check returns false (function is not
97
- // an object), and the fallthrough `renderChild(function)` calls
98
- // `render(function, props)` which interprets the function as a component
99
- // function — wrong shape, lost per-item metadata. Resolving eagerly here
100
- // keeps every downstream branch correct. Mirrors the kinetic Stagger /
101
- // TransitionItem fix (PR #731 + parallel top-level fixes).
102
- const children = typeof rawChildren === 'function'
103
- ? (rawChildren as () => VNodeChild)()
104
- : rawChildren
105
-
106
- const injectItemProps = typeof itemProps === 'function' ? itemProps : () => itemProps
107
-
108
- const injectWrapItemProps = typeof wrapProps === 'function' ? wrapProps : () => wrapProps
109
-
110
- const getKey = (item: string | number, index: number) => {
111
- if (typeof itemKey === 'function') return itemKey(item, index)
112
- return index
113
- }
114
-
115
- const renderChild = (child: VNodeChild, total = 1, i = 0) => {
116
- if (!itemProps && !Wrapper) return child
117
-
118
- const extendedProps = attachItemProps({
119
- i,
120
- length: total,
121
- })
122
-
123
- const finalItemProps = itemProps ? injectItemProps({}, extendedProps) : {}
124
-
125
- if (Wrapper) {
126
- const finalWrapProps = wrapProps ? injectWrapItemProps({}, extendedProps) : {}
127
-
128
- return (
129
- <Wrapper key={i} {...finalWrapProps}>
130
- {render(child, finalItemProps)}
131
- </Wrapper>
132
- )
133
- }
134
-
135
- return render(child, {
136
- key: i,
137
- ...finalItemProps,
138
- })
139
- }
140
-
141
- // --------------------------------------------------------
142
- // render children
143
- // --------------------------------------------------------
144
- const renderChildren = () => {
145
- if (!children) return null
146
-
147
- // if children is Array
148
- if (Array.isArray(children)) {
149
- return children.map((item, i) => renderChild(item, children.length, i))
150
- }
151
-
152
- // if children is Fragment — check VNode type
153
- if (
154
- typeof children === 'object' &&
155
- 'type' in (children as VNode) &&
156
- (children as VNode).type === Fragment
157
- ) {
158
- const fragmentChildren = (children as VNode).children as VNodeChild[]
159
- const childrenLength = fragmentChildren.length
160
-
161
- return fragmentChildren.map((item, i) => renderChild(item, childrenLength, i))
162
- }
163
-
164
- // if single child
165
- return renderChild(children)
166
- }
167
-
168
- // --------------------------------------------------------
169
- // render array of strings or numbers
170
- // --------------------------------------------------------
171
- const renderSimpleArray = (simpleData: SimpleValue[]) => {
172
- const { length } = simpleData
173
-
174
- if (length === 0) return null
175
-
176
- return simpleData.map((item, i) => {
177
- const key = getKey(item, i)
178
- const keyName = valueName ?? 'children'
179
- const extendedProps = attachItemProps({
180
- i,
181
- length,
182
- })
183
-
184
- const finalItemProps = {
185
- ...(itemProps ? injectItemProps({ [keyName]: item }, extendedProps) : {}),
186
- [keyName]: item,
187
- }
188
-
189
- if (Wrapper) {
190
- const finalWrapProps = wrapProps
191
- ? injectWrapItemProps({ [keyName]: item }, extendedProps)
192
- : {}
193
-
194
- return (
195
- <Wrapper key={key} {...finalWrapProps}>
196
- {render(component, finalItemProps)}
197
- </Wrapper>
198
- )
199
- }
200
-
201
- return render(component, { key, ...finalItemProps })
202
- })
203
- }
204
-
205
- // --------------------------------------------------------
206
- // render array of objects
207
- // --------------------------------------------------------
208
- const getObjectKey = (item: ObjectValue, index: number) => {
209
- if (!itemKey) return item.key ?? item.id ?? item.itemId ?? index
210
- if (typeof itemKey === 'function') return itemKey(item, index)
211
- if (typeof itemKey === 'string') return item[itemKey]
212
-
213
- return index
214
- }
215
-
216
- const renderComplexArray = (complexData: ObjectValue[]) => {
217
- const { length } = complexData
218
-
219
- if (length === 0) return null
220
-
221
- return complexData.map((item, i) => {
222
- const { component: itemComponent, ...restItem } = item
223
- const renderItem = itemComponent ?? component
224
- const key = getObjectKey(restItem, i)
225
- const extendedProps = attachItemProps({
226
- i,
227
- length,
228
- })
229
-
230
- const finalItemProps = {
231
- ...(itemProps ? injectItemProps(item, extendedProps) : {}),
232
- ...restItem,
233
- }
234
-
235
- if (Wrapper && !itemComponent) {
236
- const finalWrapProps = wrapProps ? injectWrapItemProps(item, extendedProps) : {}
237
-
238
- return (
239
- <Wrapper key={key} {...finalWrapProps}>
240
- {render(renderItem, finalItemProps)}
241
- </Wrapper>
242
- )
243
- }
244
-
245
- return render(renderItem, { key, ...finalItemProps })
246
- })
247
- }
248
-
249
- // --------------------------------------------------------
250
- // render list items
251
- // --------------------------------------------------------
252
- const renderItems = (): VNodeChild => {
253
- // children have priority over props component + data
254
- if (children) return renderChildren() as VNodeChild
255
-
256
- // render props component + data
257
- if (component && Array.isArray(data)) {
258
- const classified = classifyData(data)
259
- if (!classified) return null
260
- if (classified.type === 'simple') return renderSimpleArray(classified.data) as VNodeChild
261
- return renderComplexArray(classified.data) as VNodeChild
262
- }
263
-
264
- return null
265
- }
266
-
267
- return renderItems()
268
- }
269
-
270
- // ---------------------------------------------------------------------------
271
- // Public callable type — overloads expose the generic `<T>` API at the JSX
272
- // boundary while the impl stays loose-typed. TS picks the matching overload
273
- // based on the props object passed:
274
- //
275
- // <Iterator data={['a','b']} valueName="text" component={Item} />
276
- // ^ T inferred as string → SimpleProps<string> overload selected
277
- //
278
- // <Iterator data={users} component={UserCard} />
279
- // ^ T inferred as User → ObjectProps<User> overload selected
280
- //
281
- // <Iterator>{...}</Iterator> → ChildrenProps overload selected
282
- // ---------------------------------------------------------------------------
283
- export interface IteratorComponent {
284
- // T is inferred from the `data` prop at the JSX site — no explicit
285
- // generic argument needed. Order matters: SimpleProps first (matches
286
- // `data: SimpleValue[]`), then ObjectProps (object[]), then ChildrenProps,
287
- // then a LooseProps fallback.
288
- //
289
- // The narrow overloads (Simple / Object / Children) drive per-mode T
290
- // inference and stricter compile-time errors for direct callers (e.g.
291
- // `valueName` required for primitive arrays, forbidden for object arrays).
292
- // The LooseProps fallback exists for forwarding patterns where the props
293
- // type is a wide union that doesn't bind to any single narrow overload —
294
- // notably `Partial<(typeof Wrapper)['$$types']>` spread back into the JSX
295
- // site after `@pyreon/rocketstyle`'s 4-overload-aware `ExtractProps`
296
- // distributes the union across all of Iterator's call signatures. Without
297
- // the loose binding home, the wide union has nowhere to land and TS
298
- // reports "no overload matches this call" at every forwarding site.
299
- //
300
- // Direct callers still see the strict per-mode errors — the loose fallback
301
- // only fires when none of the three narrow overloads match.
302
- <T extends SimpleValue>(props: SimpleProps<T>): VNodeChild
303
- <T extends ObjectValue>(props: ObjectProps<T>): VNodeChild
304
- (props: ChildrenProps): VNodeChild
305
- (props: LooseProps): VNodeChild
306
- isIterator: true
307
- RESERVED_PROPS: typeof RESERVED_PROPS
308
- displayName?: string
309
- }
310
-
311
- const Iterator = Object.assign(Component, {
312
- isIterator: true as const,
313
- RESERVED_PROPS,
314
- }) as unknown as IteratorComponent
315
-
316
- export default Iterator
@@ -1,30 +0,0 @@
1
- import component from './component'
2
- import type {
3
- ChildrenProps,
4
- ElementType,
5
- ExtendedProps,
6
- LooseProps,
7
- MaybeNull,
8
- ObjectProps,
9
- ObjectValue,
10
- Props,
11
- PropsCallback,
12
- SimpleProps,
13
- SimpleValue,
14
- } from './types'
15
-
16
- export type {
17
- ChildrenProps,
18
- ElementType,
19
- ExtendedProps,
20
- LooseProps,
21
- MaybeNull,
22
- ObjectProps,
23
- ObjectValue,
24
- Props,
25
- PropsCallback,
26
- SimpleProps,
27
- SimpleValue,
28
- }
29
-
30
- export default component
@@ -1,138 +0,0 @@
1
- import type { ComponentFn, VNodeChild } from '@pyreon/core'
2
- import type { HTMLTags } from '@pyreon/ui-core'
3
-
4
- export type MaybeNull = undefined | null
5
- export type TObj = Record<string, unknown>
6
- export type SimpleValue = string | number
7
- export type ObjectValue = Partial<{
8
- id: SimpleValue
9
- key: SimpleValue
10
- itemId: SimpleValue
11
- component: ElementType
12
- }> &
13
- Record<string, unknown>
14
-
15
- export type ElementType<T extends Record<string, unknown> = any> = ComponentFn<T> | HTMLTags
16
-
17
- export type ExtendedProps = {
18
- index: number
19
- first: boolean
20
- last: boolean
21
- odd: boolean
22
- even: boolean
23
- position: number
24
- }
25
-
26
- // ---------------------------------------------------------------------------
27
- // Per-mode prop shapes — narrowed via the `T` data-element type
28
- // ---------------------------------------------------------------------------
29
-
30
- /**
31
- * Iterator over an array of strings/numbers. Each item is wrapped in
32
- * `{ [valueName]: item }` and that object is what callbacks see + what's
33
- * spread onto the rendered component.
34
- */
35
- export type SimpleProps<T extends SimpleValue> = {
36
- data: Array<T | MaybeNull>
37
- /** A component to be rendered per item. */
38
- component: ElementType
39
- /**
40
- * Key under which each primitive value is exposed to `component` and
41
- * callbacks. Defaults to `'children'` at runtime — i.e. the value is
42
- * passed to the component as its children.
43
- */
44
- valueName?: string
45
- /** Optional wrapper around each item. */
46
- wrapComponent?: ElementType
47
- /** Stable key per item (defaults to index). */
48
- itemKey?: (item: T, index: number) => SimpleValue
49
- /** Extra props merged onto the rendered component, optionally per-item. */
50
- itemProps?: TObj | ((item: { [k: string]: T }, ext: ExtendedProps) => TObj)
51
- /** Extra props merged onto the wrapper, optionally per-item. */
52
- wrapProps?: TObj | ((item: { [k: string]: T }, ext: ExtendedProps) => TObj)
53
- children?: never
54
- }
55
-
56
- /**
57
- * Iterator over an array of objects. Each item is spread onto the rendered
58
- * component as props. Per-item `component` overrides also work — when an
59
- * item carries its own `component` field, the wrapper is bypassed.
60
- */
61
- export type ObjectProps<T extends ObjectValue> = {
62
- data: Array<T | MaybeNull>
63
- /** Default component to be rendered per item (item-level `component` overrides). */
64
- component: ElementType
65
- /** `valueName` is meaningless when iterating objects — TS forbids it. */
66
- valueName?: never
67
- /** Optional wrapper around each item. */
68
- wrapComponent?: ElementType
69
- /** Stable key per item — pick a key from the item, or compute it. */
70
- itemKey?: keyof T | ((item: T, index: number) => SimpleValue)
71
- /** Extra props merged onto the rendered component, optionally per-item. */
72
- itemProps?: TObj | ((item: T, ext: ExtendedProps) => TObj)
73
- /** Extra props merged onto the wrapper, optionally per-item. */
74
- wrapProps?: TObj | ((item: T, ext: ExtendedProps) => TObj)
75
- children?: never
76
- }
77
-
78
- /**
79
- * Iterator over `children` — no `data`/`component`. Each child gets
80
- * positional metadata via `itemProps` and an optional `wrapComponent`.
81
- */
82
- export type ChildrenProps = {
83
- children: VNodeChild
84
- data?: never
85
- component?: never
86
- valueName?: never
87
- itemKey?: never
88
- wrapComponent?: ElementType
89
- itemProps?: TObj | ((_: Record<string, never>, ext: ExtendedProps) => TObj)
90
- wrapProps?: TObj | ((_: Record<string, never>, ext: ExtendedProps) => TObj)
91
- }
92
-
93
- // ---------------------------------------------------------------------------
94
- // Loose backward-compatible fallback shape (today's behavior)
95
- //
96
- // Used when callers don't (or can't) parameterize `Props<T>` — keeps the
97
- // existing call surface intact so this refactor lands non-breaking.
98
- // ---------------------------------------------------------------------------
99
-
100
- export type PropsCallback =
101
- | TObj
102
- | ((
103
- itemProps: Record<string, never> | Record<string, SimpleValue> | ObjectValue,
104
- extendedProps: ExtendedProps,
105
- ) => TObj)
106
-
107
- export type LooseProps = Partial<{
108
- children: VNodeChild
109
- data: Array<SimpleValue | ObjectValue | MaybeNull>
110
- component: ElementType
111
- valueName: string
112
- wrapComponent: ElementType
113
- itemProps: PropsCallback
114
- wrapProps: PropsCallback
115
- itemKey:
116
- | keyof ObjectValue
117
- | ((item: SimpleValue | Omit<ObjectValue, 'component'>, index: number) => SimpleValue)
118
- }>
119
-
120
- // ---------------------------------------------------------------------------
121
- // Public, generic-aware Props<T>
122
- //
123
- // Props<string> → SimpleProps<string> (valueName REQUIRED)
124
- // Props<{ id; name }> → ObjectProps<{...}> (valueName FORBIDDEN)
125
- // Props<unknown> / Props → LooseProps (today's behavior)
126
- //
127
- // `unknown extends T` is the canonical "did the caller actually narrow T?"
128
- // check — true only when T is left as `unknown`, false for any concrete
129
- // narrowing. Fallback to LooseProps preserves existing call sites.
130
- // ---------------------------------------------------------------------------
131
-
132
- export type Props<T = unknown> = unknown extends T
133
- ? LooseProps
134
- : T extends SimpleValue
135
- ? SimpleProps<T>
136
- : T extends ObjectValue
137
- ? ObjectProps<T>
138
- : ChildrenProps
@@ -1,180 +0,0 @@
1
- /**
2
- * Wrapper component that serves as the outermost styled container for Element.
3
- * On web, it detects button/fieldset/legend tags and applies a two-layer flex
4
- * fix (parent + child Styled) because these HTML elements do not natively
5
- * support `display: flex` consistently across browsers.
6
- */
7
- import { h, splitProps } from '@pyreon/core'
8
- import { getShouldBeEmpty } from '../../Element/utils'
9
- import { IS_DEVELOPMENT } from '../../utils'
10
- import { internElementBundle } from '../internElementBundle'
11
- import Styled from './styled'
12
- import type { Props } from './types'
13
- import { isWebFixNeeded } from './utils'
14
-
15
- const DEV_PROPS: Record<string, string> = IS_DEVELOPMENT ? { 'data-pyr-element': 'Element' } : {}
16
-
17
- /**
18
- * Build a props object for `h(Styled, ...)` by copying own property
19
- * DESCRIPTORS from `rest`, then layering the additional fields. Compiler-
20
- * emitted reactive props (`_rp(() => signal())` converted to getters by
21
- * `makeReactiveProps`) survive end-to-end with their getter intact.
22
- *
23
- * Why we bypass JSX spread here: the standard JSX automatic-runtime
24
- * compilation lowers `<Styled {...rest} foo={x}>` to roughly
25
- * `jsx(Styled, { ...rest, foo: x })`. That `{...rest, foo: x}` object
26
- * literal is evaluated at JS level — it fires every getter on `rest` and
27
- * stores the resolved value before `jsx()` ever sees the object. No
28
- * amount of in-runtime descriptor preservation can recover the getters
29
- * once they've been collapsed by the surface-level spread. The fix is
30
- * structural: don't use JSX spread for reactive-prop forwarding. Build
31
- * the props object with descriptor preservation and pass it to `h()`
32
- * directly — `h()` stores props as-is on the vnode, no copy, getters
33
- * survive into mount.
34
- */
35
- const buildStyledProps = (
36
- rest: Record<string, unknown>,
37
- refValue: unknown,
38
- asTag: unknown,
39
- extras: Record<string, unknown>,
40
- ): Record<string, unknown> => {
41
- const result: Record<string, unknown> = {}
42
- const descriptors = Object.getOwnPropertyDescriptors(rest)
43
- for (const key in descriptors) {
44
- Object.defineProperty(result, key, descriptors[key]!)
45
- }
46
- for (const key in DEV_PROPS) {
47
- result[key] = DEV_PROPS[key]
48
- }
49
- result.ref = refValue
50
- result.as = asTag
51
- for (const key in extras) {
52
- result[key] = extras[key]
53
- }
54
- return result
55
- }
56
-
57
- // Layout / ref keys consumed by Wrapper itself. Everything else is forwarded
58
- // onto the underlying DOM node. Listed as a tuple so `splitProps` narrows
59
- // `own` correctly while preserving reactive prop tracking on both halves.
60
- const OWN_KEYS: Array<keyof Props | 'ref'> = [
61
- 'children',
62
- 'tag',
63
- 'block',
64
- 'extendCss',
65
- 'direction',
66
- 'alignX',
67
- 'alignY',
68
- 'equalCols',
69
- 'isInline',
70
- 'ref',
71
- 'dangerouslySetInnerHTML',
72
- ]
73
-
74
- const Component = (props: Partial<Props> & { ref?: unknown }) => {
75
- const [own, rest] = splitProps(props, OWN_KEYS)
76
-
77
- const needsFix = !own.dangerouslySetInnerHTML && isWebFixNeeded(own.tag)
78
-
79
- // Void HTML elements (hr, input, img, br, …) cannot have children. Even
80
- // a falsy `{own.children}` slot becomes `[undefined]` in the vnode and
81
- // trips runtime-dom's void-element warning. Element already skips passing
82
- // children to Wrapper for void tags; this guard makes sure the empty
83
- // slot is dropped here too instead of leaking into the JSX.
84
- const isVoidTag = !own.dangerouslySetInnerHTML && getShouldBeEmpty(own.tag)
85
-
86
- // dangerouslySetInnerHTML and children are mutually exclusive — both
87
- // become inner content (per `runtime-server/src/index.ts:228` and
88
- // `runtime-dom/src/props.ts:289`). Pre-fix the prop was in OWN_KEYS,
89
- // moved into `own` by splitProps, and never re-attached to the rendered
90
- // vnode — so `<Logo dangerouslySetInnerHTML={...} />` rendered an empty
91
- // <div></div>. Forward the prop to the styled vnode and drop the
92
- // children slot when innerHTML is set.
93
- const innerHTML = own.dangerouslySetInnerHTML
94
-
95
- if (!needsFix) {
96
- const bundle = internElementBundle({
97
- block: own.block,
98
- direction: own.direction,
99
- alignX: own.alignX,
100
- alignY: own.alignY,
101
- equalCols: own.equalCols,
102
- extraStyles: own.extendCss,
103
- })
104
- if (isVoidTag) {
105
- return h(
106
- Styled,
107
- buildStyledProps(rest as unknown as Record<string, unknown>, own.ref, own.tag, {
108
- $element: bundle,
109
- }),
110
- )
111
- }
112
- if (innerHTML) {
113
- return h(
114
- Styled,
115
- buildStyledProps(rest as unknown as Record<string, unknown>, own.ref, own.tag, {
116
- $element: bundle,
117
- dangerouslySetInnerHTML: innerHTML,
118
- }),
119
- )
120
- }
121
- return h(
122
- Styled,
123
- buildStyledProps(rest as unknown as Record<string, unknown>, own.ref, own.tag, {
124
- $element: bundle,
125
- children: own.children,
126
- }),
127
- )
128
- }
129
-
130
- const asTag = own.isInline ? 'span' : 'div'
131
- const parentBundle = internElementBundle({
132
- parentFix: true as const,
133
- block: own.block,
134
- extraStyles: own.extendCss,
135
- })
136
- const childBundle = internElementBundle({
137
- childFix: true as const,
138
- direction: own.direction,
139
- alignX: own.alignX,
140
- alignY: own.alignY,
141
- equalCols: own.equalCols,
142
- })
143
-
144
- // needsFix path: innerHTML belongs on the INNER styled node (where the
145
- // actual content lives), NOT on the outer flex-fix wrapper. The
146
- // `needsFix` computation already excludes the innerHTML case
147
- // (`!own.dangerouslySetInnerHTML && isWebFixNeeded(own.tag)`), so this
148
- // branch normally won't execute when innerHTML is set — but we keep
149
- // the defensive forwarding so the contract is robust against future
150
- // refactors of the needsFix gate.
151
- if (innerHTML) {
152
- return h(
153
- Styled,
154
- buildStyledProps(rest as unknown as Record<string, unknown>, own.ref, own.tag, {
155
- $element: parentBundle,
156
- children: h(Styled, {
157
- as: asTag,
158
- $childFix: true,
159
- $element: childBundle,
160
- dangerouslySetInnerHTML: innerHTML,
161
- }),
162
- }),
163
- )
164
- }
165
-
166
- return h(
167
- Styled,
168
- buildStyledProps(rest as unknown as Record<string, unknown>, own.ref, own.tag, {
169
- $element: parentBundle,
170
- children: h(Styled, {
171
- as: asTag,
172
- $childFix: true,
173
- $element: childBundle,
174
- children: own.children,
175
- }),
176
- }),
177
- )
178
- }
179
-
180
- export default Component
@@ -1,10 +0,0 @@
1
- /**
2
- * HTML elements that need a two-layer DOM workaround because browsers do not
3
- * fully support flexbox layout on button, fieldset, and legend elements.
4
- * @see https://stackoverflow.com/questions/35464067/flexbox-not-working-on-button-or-fieldset-elements
5
- */
6
- export const INLINE_ELEMENTS_FLEX_FIX = {
7
- button: true,
8
- fieldset: true,
9
- legend: true,
10
- }
@@ -1,3 +0,0 @@
1
- import component from './component'
2
-
3
- export default component