@remix-run/ui 0.1.1 → 0.2.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/README.md +33 -10
- package/dist/animation/animate-layout-mixin.js +66 -66
- package/dist/animation/animate-layout-mixin.js.map +1 -1
- package/dist/animation/spring.d.ts +6 -35
- package/dist/animation/spring.js +9 -8
- package/dist/animation/spring.js.map +1 -1
- package/dist/components/accordion/accordion.d.ts +7 -7
- package/dist/components/accordion/accordion.js +0 -2
- package/dist/components/accordion/accordion.js.map +1 -1
- package/dist/components/accordion/demos/card.demo.d.ts +6 -0
- package/dist/components/accordion/demos/card.demo.js +58 -0
- package/dist/components/accordion/demos/card.demo.js.map +1 -0
- package/dist/components/accordion/demos/multiple.demo.d.ts +6 -0
- package/dist/components/accordion/demos/multiple.demo.js +19 -0
- package/dist/components/accordion/demos/multiple.demo.js.map +1 -0
- package/dist/components/accordion/demos/overview.demo.d.ts +6 -0
- package/dist/components/accordion/demos/overview.demo.js +19 -0
- package/dist/components/accordion/demos/overview.demo.js.map +1 -0
- package/dist/components/breadcrumbs/breadcrumbs.d.ts +1 -1
- package/dist/components/breadcrumbs/breadcrumbs.js +0 -2
- package/dist/components/breadcrumbs/breadcrumbs.js.map +1 -1
- package/dist/components/breadcrumbs/demos/basic.demo.d.ts +5 -0
- package/dist/components/breadcrumbs/demos/basic.demo.js +14 -0
- package/dist/components/breadcrumbs/demos/basic.demo.js.map +1 -0
- package/dist/components/breadcrumbs/demos/separator.demo.d.ts +5 -0
- package/dist/components/breadcrumbs/demos/separator.demo.js +14 -0
- package/dist/components/breadcrumbs/demos/separator.demo.js.map +1 -0
- package/dist/components/button/button.d.ts +86 -4
- package/dist/components/button/button.js +63 -3
- package/dist/components/button/button.js.map +1 -1
- package/dist/components/button/demos/aliases.demo.d.ts +6 -0
- package/dist/components/button/demos/aliases.demo.js +18 -0
- package/dist/components/button/demos/aliases.demo.js.map +1 -0
- package/dist/components/button/demos/basic.demo.d.ts +6 -0
- package/dist/components/button/demos/basic.demo.js +19 -0
- package/dist/components/button/demos/basic.demo.js.map +1 -0
- package/dist/components/button/demos/states.demo.d.ts +6 -0
- package/dist/components/button/demos/states.demo.js +29 -0
- package/dist/components/button/demos/states.demo.js.map +1 -0
- package/dist/components/combobox/combobox.d.ts +11 -11
- package/dist/components/combobox/combobox.js +0 -2
- package/dist/components/combobox/combobox.js.map +1 -1
- package/dist/components/combobox/demos/overview.demo.d.ts +6 -0
- package/dist/components/combobox/demos/overview.demo.js +153 -0
- package/dist/components/combobox/demos/overview.demo.js.map +1 -0
- package/dist/components/listbox/demos/overview.demo.d.ts +6 -0
- package/dist/components/listbox/demos/overview.demo.js +64 -0
- package/dist/components/listbox/demos/overview.demo.js.map +1 -0
- package/dist/components/listbox/listbox.d.ts +4 -9
- package/dist/components/listbox/listbox.js +21 -33
- package/dist/components/listbox/listbox.js.map +1 -1
- package/dist/components/menu/demos/bubbling.demo.d.ts +5 -0
- package/dist/components/menu/demos/bubbling.demo.js +15 -0
- package/dist/components/menu/demos/bubbling.demo.js.map +1 -0
- package/dist/components/menu/demos/overview.demo.d.ts +6 -0
- package/dist/components/menu/demos/overview.demo.js +32 -0
- package/dist/components/menu/demos/overview.demo.js.map +1 -0
- package/dist/components/menu/menu.d.ts +15 -24
- package/dist/components/menu/menu.js +23 -38
- package/dist/components/menu/menu.js.map +1 -1
- package/dist/components/popover/demos/overview.demo.d.ts +6 -0
- package/dist/components/popover/demos/overview.demo.js +64 -0
- package/dist/components/popover/demos/overview.demo.js.map +1 -0
- package/dist/components/popover/popover.d.ts +5 -5
- package/dist/components/popover/popover.js.map +1 -1
- package/dist/components/select/demos/deconstructed.demo.d.ts +6 -0
- package/dist/components/select/demos/deconstructed.demo.js +53 -0
- package/dist/components/select/demos/deconstructed.demo.js.map +1 -0
- package/dist/components/select/demos/overview.demo.d.ts +5 -0
- package/dist/components/select/demos/overview.demo.js +27 -0
- package/dist/components/select/demos/overview.demo.js.map +1 -0
- package/dist/components/select/select.d.ts +11 -11
- package/dist/components/select/select.js +17 -26
- package/dist/components/select/select.js.map +1 -1
- package/dist/components/tabs/tabs.d.ts +6 -6
- package/dist/components/tabs/tabs.js +0 -2
- package/dist/components/tabs/tabs.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js.map +1 -1
- package/dist/interactions/keydown/keydown.d.ts +1 -1
- package/dist/interactions/outside-click/outside-click-mixin.d.ts +2 -1
- package/dist/interactions/typeahead/typeahead-mixin.d.ts +3 -1
- package/dist/runtime/component.d.ts +18 -12
- package/dist/runtime/component.js +93 -80
- package/dist/runtime/component.js.map +1 -1
- package/dist/runtime/core/attributes.d.ts +14 -0
- package/dist/runtime/core/attributes.js +103 -0
- package/dist/runtime/core/attributes.js.map +1 -0
- package/dist/runtime/core/children.d.ts +7 -0
- package/dist/runtime/core/children.js +30 -0
- package/dist/runtime/core/children.js.map +1 -0
- package/dist/runtime/core/props.d.ts +9 -0
- package/dist/runtime/core/props.js +170 -0
- package/dist/runtime/core/props.js.map +1 -0
- package/dist/runtime/core/vnode.d.ts +3 -0
- package/dist/runtime/core/vnode.js +39 -0
- package/dist/runtime/core/vnode.js.map +1 -0
- package/dist/runtime/create-element.js +2 -1
- package/dist/runtime/create-element.js.map +1 -1
- package/dist/runtime/diff-dom.js +47 -14
- package/dist/runtime/diff-dom.js.map +1 -1
- package/dist/runtime/diff-props.d.ts +1 -2
- package/dist/runtime/diff-props.js +2 -181
- package/dist/runtime/diff-props.js.map +1 -1
- package/dist/runtime/dom.d.ts +20 -9
- package/dist/runtime/frame.d.ts +23 -2
- package/dist/runtime/frame.js +41 -47
- package/dist/runtime/frame.js.map +1 -1
- package/dist/runtime/jsx.d.ts +1 -1
- package/dist/runtime/jsx.js +2 -28
- package/dist/runtime/jsx.js.map +1 -1
- package/dist/runtime/mixins/link-mixin.d.ts +5 -1
- package/dist/runtime/mixins/link-mixin.js.map +1 -1
- package/dist/runtime/mixins/mixin.d.ts +2 -1
- package/dist/runtime/mixins/mixin.js +9 -4
- package/dist/runtime/mixins/mixin.js.map +1 -1
- package/dist/runtime/mixins/on-mixin.d.ts +15 -4
- package/dist/runtime/mixins/on-mixin.js +9 -2
- package/dist/runtime/mixins/on-mixin.js.map +1 -1
- package/dist/runtime/mixins/ref-mixin.d.ts +2 -1
- package/dist/runtime/mixins/ref-mixin.js.map +1 -1
- package/dist/runtime/navigation.js +9 -1
- package/dist/runtime/navigation.js.map +1 -1
- package/dist/runtime/reconcile.d.ts +1 -1
- package/dist/runtime/reconcile.js +452 -197
- package/dist/runtime/reconcile.js.map +1 -1
- package/dist/runtime/run.d.ts +17 -2
- package/dist/runtime/run.js.map +1 -1
- package/dist/runtime/scheduler.d.ts +10 -10
- package/dist/runtime/scheduler.js +1 -1
- package/dist/runtime/scheduler.js.map +1 -1
- package/dist/runtime/stream-protocol.d.ts +8 -0
- package/dist/runtime/stream-protocol.js +20 -0
- package/dist/runtime/stream-protocol.js.map +1 -0
- package/dist/runtime/svg-attributes.js +1 -0
- package/dist/runtime/svg-attributes.js.map +1 -1
- package/dist/runtime/to-vnode.js +7 -11
- package/dist/runtime/to-vnode.js.map +1 -1
- package/dist/runtime/vnode.d.ts +11 -5
- package/dist/runtime/vnode.js +6 -3
- package/dist/runtime/vnode.js.map +1 -1
- package/dist/server/stream.d.ts +2 -0
- package/dist/server/stream.js +154 -114
- package/dist/server/stream.js.map +1 -1
- package/dist/style/css-mixin.d.ts +2 -1
- package/dist/style/css-mixin.js.map +1 -1
- package/dist/style/index.d.ts +1 -1
- package/dist/style/layers.d.ts +2 -0
- package/dist/style/layers.js +3 -0
- package/dist/style/layers.js.map +1 -0
- package/dist/style/stylesheet.d.ts +13 -11
- package/dist/style/stylesheet.js +69 -8
- package/dist/style/stylesheet.js.map +1 -1
- package/dist/theme/contract.d.ts +24 -222
- package/dist/theme/contract.js +2 -2
- package/dist/theme/contract.js.map +1 -1
- package/dist/theme/glyph-contract.d.ts +1 -3
- package/dist/theme/glyph-contract.js.map +1 -1
- package/dist/theme/presets/rmx-01/index.d.ts +4 -2
- package/dist/theme/presets/rmx-01/index.js.map +1 -1
- package/dist/theme/runtime.js +4 -1
- package/dist/theme/runtime.js.map +1 -1
- package/dist/utils/scroll-lock.d.ts +3 -3
- package/dist/utils/scroll-lock.js.map +1 -1
- package/package.json +3 -3
- package/src/animation/README.md +316 -0
- package/src/animation/animate-layout-mixin.ts +79 -71
- package/src/animation/spring.ts +21 -9
- package/src/components/accordion/README.md +166 -0
- package/src/components/accordion/accordion.tsx +14 -14
- package/src/components/accordion/demos/card.demo.tsx +113 -0
- package/src/components/accordion/demos/multiple.demo.tsx +56 -0
- package/src/components/accordion/demos/overview.demo.tsx +56 -0
- package/src/components/anchor/README.md +153 -0
- package/src/components/anchor/anchor.ts +1 -1
- package/src/components/breadcrumbs/README.md +55 -0
- package/src/components/breadcrumbs/breadcrumbs.tsx +1 -3
- package/src/components/breadcrumbs/demos/basic.demo.tsx +17 -0
- package/src/components/breadcrumbs/demos/separator.demo.tsx +18 -0
- package/src/components/button/README.md +4 -4
- package/src/components/button/button.tsx +118 -20
- package/src/components/button/demos/aliases.demo.tsx +27 -0
- package/src/components/button/demos/basic.demo.tsx +30 -0
- package/src/components/button/demos/states.demo.tsx +52 -0
- package/src/components/combobox/README.md +1 -1
- package/src/components/combobox/combobox.tsx +37 -21
- package/src/components/combobox/demos/overview.demo.tsx +199 -0
- package/src/components/glyph/README.md +72 -0
- package/src/components/glyph/glyph.tsx +2 -2
- package/src/components/listbox/README.md +115 -0
- package/src/components/listbox/demos/overview.demo.tsx +101 -0
- package/src/components/listbox/listbox.ts +106 -110
- package/src/components/menu/README.md +96 -0
- package/src/components/menu/demos/bubbling.demo.tsx +34 -0
- package/src/components/menu/demos/overview.demo.tsx +76 -0
- package/src/components/menu/menu.tsx +61 -55
- package/src/components/popover/README.md +3 -3
- package/src/components/popover/demos/overview.demo.tsx +143 -0
- package/src/components/popover/popover.ts +90 -79
- package/src/components/select/README.md +107 -0
- package/src/components/select/demos/deconstructed.demo.tsx +95 -0
- package/src/components/select/demos/overview.demo.tsx +51 -0
- package/src/components/select/select.tsx +53 -36
- package/src/components/tabs/tabs.tsx +10 -5
- package/src/index.ts +2 -1
- package/src/runtime/component.ts +122 -88
- package/src/runtime/core/attributes.ts +118 -0
- package/src/runtime/core/children.ts +42 -0
- package/src/runtime/core/props.ts +187 -0
- package/src/runtime/core/vnode.ts +48 -0
- package/src/runtime/create-element.ts +2 -1
- package/src/runtime/diff-dom.ts +59 -12
- package/src/runtime/diff-props.ts +2 -187
- package/src/runtime/dom.ts +20 -9
- package/src/runtime/frame.ts +71 -55
- package/src/runtime/jsx.ts +3 -30
- package/src/runtime/mixins/link-mixin.ts +88 -86
- package/src/runtime/mixins/mixin.ts +18 -5
- package/src/runtime/mixins/on-mixin.ts +20 -12
- package/src/runtime/mixins/ref-mixin.ts +4 -5
- package/src/runtime/navigation.ts +10 -1
- package/src/runtime/reconcile.ts +563 -223
- package/src/runtime/run.ts +17 -1
- package/src/runtime/scheduler.ts +20 -20
- package/src/runtime/stream-protocol.ts +27 -0
- package/src/runtime/svg-attributes.ts +1 -0
- package/src/runtime/to-vnode.ts +7 -10
- package/src/runtime/vnode.ts +16 -9
- package/src/server/README.md +90 -0
- package/src/server/stream.ts +176 -124
- package/src/style/css-mixin.ts +6 -1
- package/src/style/index.ts +1 -2
- package/src/style/layers.ts +2 -0
- package/src/style/stylesheet.ts +88 -11
- package/src/test/README.md +107 -0
- package/src/test/utils.ts +3 -1
- package/src/theme/README.md +103 -0
- package/src/theme/contract.ts +37 -5
- package/src/theme/glyph-contract.ts +3 -1
- package/src/theme/presets/rmx-01/index.ts +4 -2
- package/src/theme/runtime.ts +4 -1
- package/src/utils/scroll-lock/README.md +33 -0
- package/src/utils/scroll-lock.ts +7 -3
|
@@ -1,200 +1,15 @@
|
|
|
1
1
|
import { invariant } from './invariant.ts'
|
|
2
|
-
import { createStyleManager
|
|
2
|
+
import { createStyleManager } from '../style/index.ts'
|
|
3
3
|
import type { StyleManager } from '../style/index.ts'
|
|
4
|
-
import type { ElementProps } from './jsx.ts'
|
|
5
|
-
import { normalizeSvgAttribute } from './svg-attributes.ts'
|
|
6
|
-
|
|
7
|
-
const SVG_NS = 'http://www.w3.org/2000/svg'
|
|
8
4
|
|
|
9
5
|
let globalStyleManager =
|
|
10
6
|
typeof window !== 'undefined' ? createStyleManager() : (null as unknown as StyleManager)
|
|
11
7
|
|
|
12
8
|
export { type StyleManager }
|
|
9
|
+
export { patchHostProps as diffHostProps } from './core/props.ts'
|
|
13
10
|
|
|
14
11
|
export let defaultStyleManager: StyleManager = globalStyleManager
|
|
15
12
|
|
|
16
|
-
// Preact excludes certain attributes from the property path due to browser quirks
|
|
17
|
-
const ATTRIBUTE_FALLBACK_NAMES = new Set([
|
|
18
|
-
'width',
|
|
19
|
-
'height',
|
|
20
|
-
'href',
|
|
21
|
-
'list',
|
|
22
|
-
'form',
|
|
23
|
-
'tabIndex',
|
|
24
|
-
'download',
|
|
25
|
-
'rowSpan',
|
|
26
|
-
'colSpan',
|
|
27
|
-
'role',
|
|
28
|
-
'popover',
|
|
29
|
-
])
|
|
30
|
-
|
|
31
|
-
// Determine if we should use the property path for a given name.
|
|
32
|
-
// Also acts as a type guard to allow bracket assignment without casts.
|
|
33
|
-
function canUseProperty(
|
|
34
|
-
dom: Element,
|
|
35
|
-
name: string,
|
|
36
|
-
isSvg: boolean,
|
|
37
|
-
): dom is Element & Record<string, unknown> {
|
|
38
|
-
if (isSvg) return false
|
|
39
|
-
if (ATTRIBUTE_FALLBACK_NAMES.has(name)) return false
|
|
40
|
-
return name in dom
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function isFrameworkProp(name: string): boolean {
|
|
44
|
-
return (
|
|
45
|
-
name === 'children' ||
|
|
46
|
-
name === 'mix' ||
|
|
47
|
-
name === 'key' ||
|
|
48
|
-
name === 'animate' ||
|
|
49
|
-
name === 'innerHTML'
|
|
50
|
-
)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// TODO: would rather actually diff el.style object directly instead of writing
|
|
54
|
-
// to the style attribute
|
|
55
|
-
function serializeStyleObject(style: Record<string, unknown>): string {
|
|
56
|
-
let parts: string[] = []
|
|
57
|
-
for (let [key, value] of Object.entries(style)) {
|
|
58
|
-
if (value == null) continue
|
|
59
|
-
if (typeof value === 'boolean') continue
|
|
60
|
-
if (typeof value === 'number' && !Number.isFinite(value)) continue
|
|
61
|
-
|
|
62
|
-
let cssKey = key.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`)
|
|
63
|
-
|
|
64
|
-
let cssValue = Array.isArray(value)
|
|
65
|
-
? (value as unknown[]).join(', ')
|
|
66
|
-
: normalizeCssValue(key, value)
|
|
67
|
-
|
|
68
|
-
parts.push(`${cssKey}: ${cssValue};`)
|
|
69
|
-
}
|
|
70
|
-
return parts.join(' ')
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function normalizePropName(name: string, isSvg: boolean): { ns?: string; attr: string } {
|
|
74
|
-
// aria-/data- pass through
|
|
75
|
-
if (name.startsWith('aria-') || name.startsWith('data-')) return { attr: name }
|
|
76
|
-
|
|
77
|
-
// DOM property -> HTML mappings
|
|
78
|
-
if (name === 'className') return { attr: 'class' }
|
|
79
|
-
if (!isSvg) {
|
|
80
|
-
if (name === 'htmlFor') return { attr: 'for' }
|
|
81
|
-
if (name === 'tabIndex') return { attr: 'tabindex' }
|
|
82
|
-
if (name === 'acceptCharset') return { attr: 'accept-charset' }
|
|
83
|
-
if (name === 'httpEquiv') return { attr: 'http-equiv' }
|
|
84
|
-
return { attr: name.toLowerCase() }
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return normalizeSvgAttribute(name)
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function toLocalName(attrName: string): string {
|
|
91
|
-
let separatorIndex = attrName.indexOf(':')
|
|
92
|
-
if (separatorIndex === -1) return attrName
|
|
93
|
-
return attrName.slice(separatorIndex + 1)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function clearRuntimePropertyOnRemoval(dom: Element & Record<string, unknown>, name: string): void {
|
|
97
|
-
try {
|
|
98
|
-
if (name === 'value' || name === 'defaultValue') {
|
|
99
|
-
dom[name] = ''
|
|
100
|
-
return
|
|
101
|
-
}
|
|
102
|
-
if (name === 'checked' || name === 'defaultChecked' || name === 'selected') {
|
|
103
|
-
dom[name] = false
|
|
104
|
-
return
|
|
105
|
-
}
|
|
106
|
-
if (name === 'selectedIndex') {
|
|
107
|
-
dom[name] = -1
|
|
108
|
-
}
|
|
109
|
-
} catch {}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function getMergedClassName(props: ElementProps): string | undefined {
|
|
113
|
-
let classAttr = typeof props.class === 'string' ? props.class : ''
|
|
114
|
-
let className = typeof props.className === 'string' ? props.className : ''
|
|
115
|
-
let mergedClassName =
|
|
116
|
-
classAttr && className ? `${classAttr} ${className}` : classAttr || className
|
|
117
|
-
return mergedClassName || undefined
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export function diffHostProps(curr: ElementProps, next: ElementProps, dom: Element) {
|
|
121
|
-
let isSvg = dom.namespaceURI === SVG_NS
|
|
122
|
-
let currClassName = getMergedClassName(curr)
|
|
123
|
-
let nextClassName = getMergedClassName(next)
|
|
124
|
-
|
|
125
|
-
if (currClassName !== nextClassName) {
|
|
126
|
-
if (nextClassName) {
|
|
127
|
-
dom.setAttribute('class', nextClassName)
|
|
128
|
-
} else {
|
|
129
|
-
dom.removeAttribute('class')
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Removals
|
|
134
|
-
for (let name in curr) {
|
|
135
|
-
if (isFrameworkProp(name)) continue
|
|
136
|
-
if (name === 'class' || name === 'className') continue
|
|
137
|
-
if (!(name in next) || next[name] == null) {
|
|
138
|
-
// Clear runtime state for form-like props where removing the attribute is not enough.
|
|
139
|
-
if (canUseProperty(dom, name, isSvg)) {
|
|
140
|
-
clearRuntimePropertyOnRemoval(dom, name)
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
let { ns, attr } = normalizePropName(name, isSvg)
|
|
144
|
-
if (ns) dom.removeAttributeNS(ns, toLocalName(attr))
|
|
145
|
-
else dom.removeAttribute(attr)
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Additions/updates
|
|
150
|
-
for (let name in next) {
|
|
151
|
-
if (isFrameworkProp(name)) continue
|
|
152
|
-
if (name === 'class' || name === 'className') continue
|
|
153
|
-
let nextValue = next[name]
|
|
154
|
-
if (nextValue == null) continue
|
|
155
|
-
let prevValue = curr[name]
|
|
156
|
-
if (prevValue !== nextValue) {
|
|
157
|
-
let { ns, attr } = normalizePropName(name, isSvg)
|
|
158
|
-
|
|
159
|
-
// Object style: serialize to attribute for now
|
|
160
|
-
if (
|
|
161
|
-
attr === 'style' &&
|
|
162
|
-
typeof nextValue === 'object' &&
|
|
163
|
-
nextValue &&
|
|
164
|
-
!Array.isArray(nextValue)
|
|
165
|
-
) {
|
|
166
|
-
dom.setAttribute('style', serializeStyleObject(nextValue))
|
|
167
|
-
continue
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// Prefer property assignment when possible (HTML only, not SVG)
|
|
171
|
-
if (canUseProperty(dom, name, isSvg)) {
|
|
172
|
-
try {
|
|
173
|
-
dom[name] = nextValue == null ? '' : nextValue
|
|
174
|
-
continue
|
|
175
|
-
} catch {}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// Attribute path
|
|
179
|
-
if (typeof nextValue === 'function') {
|
|
180
|
-
// Never serialize functions as attribute values
|
|
181
|
-
continue
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
let isAriaOrData = name.startsWith('aria-') || name.startsWith('data-')
|
|
185
|
-
if (nextValue != null && (nextValue !== false || isAriaOrData)) {
|
|
186
|
-
// Special-case popover: true => presence only
|
|
187
|
-
let attrValue = name === 'popover' && nextValue === true ? '' : String(nextValue)
|
|
188
|
-
if (ns) dom.setAttributeNS(ns, attr, attrValue)
|
|
189
|
-
else dom.setAttribute(attr, attrValue)
|
|
190
|
-
} else {
|
|
191
|
-
if (ns) dom.removeAttributeNS(ns, toLocalName(attr))
|
|
192
|
-
else dom.removeAttribute(attr)
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
13
|
/**
|
|
199
14
|
* Reset the global style state. For testing only - not exported from index.ts.
|
|
200
15
|
*/
|
package/src/runtime/dom.ts
CHANGED
|
@@ -9,6 +9,7 @@ import type { MixInput } from './mixins/mixin.ts'
|
|
|
9
9
|
* - Copyright (c) 2015-present Jason Miller
|
|
10
10
|
*/
|
|
11
11
|
type Booleanish = boolean | 'true' | 'false'
|
|
12
|
+
type TranslateValue = 'yes' | 'no'
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Layout animation configuration for FLIP-based position animations.
|
|
@@ -109,6 +110,8 @@ export interface SVGProps<eventTarget extends EventTarget = SVGElement>
|
|
|
109
110
|
attributeName?: Trackable<string | undefined>
|
|
110
111
|
/** The `attributeType` SVG attribute. */
|
|
111
112
|
attributeType?: Trackable<string | undefined>
|
|
113
|
+
/** The `autoReverse` SVG attribute. */
|
|
114
|
+
autoReverse?: Trackable<Booleanish | undefined>
|
|
112
115
|
/** The `azimuth` SVG attribute. */
|
|
113
116
|
azimuth?: Trackable<number | string | undefined>
|
|
114
117
|
/** The `baseFrequency` SVG attribute. */
|
|
@@ -212,7 +215,7 @@ export interface SVGProps<eventTarget extends EventTarget = SVGElement>
|
|
|
212
215
|
/** The `exponent` SVG attribute. */
|
|
213
216
|
exponent?: Trackable<number | string | undefined>
|
|
214
217
|
/** The `externalResourcesRequired` SVG attribute. */
|
|
215
|
-
externalResourcesRequired?: Trackable<
|
|
218
|
+
externalResourcesRequired?: Trackable<Booleanish | undefined>
|
|
216
219
|
/** The `fill` SVG attribute. */
|
|
217
220
|
fill?: Trackable<string | undefined>
|
|
218
221
|
/** The `fillOpacity` SVG attribute. */
|
|
@@ -238,7 +241,7 @@ export interface SVGProps<eventTarget extends EventTarget = SVGElement>
|
|
|
238
241
|
/** The `flood-opacity` SVG attribute. */
|
|
239
242
|
'flood-opacity'?: Trackable<number | string | undefined>
|
|
240
243
|
/** The `focusable` SVG attribute. */
|
|
241
|
-
focusable?: Trackable<
|
|
244
|
+
focusable?: Trackable<Booleanish | undefined>
|
|
242
245
|
/** The `fontFamily` SVG attribute. */
|
|
243
246
|
fontFamily?: Trackable<string | undefined>
|
|
244
247
|
/** The `font-family` SVG attribute. */
|
|
@@ -446,7 +449,7 @@ export interface SVGProps<eventTarget extends EventTarget = SVGElement>
|
|
|
446
449
|
/** The `pointsAtZ` SVG attribute. */
|
|
447
450
|
pointsAtZ?: Trackable<number | string | undefined>
|
|
448
451
|
/** The `preserveAlpha` SVG attribute. */
|
|
449
|
-
preserveAlpha?: Trackable<
|
|
452
|
+
preserveAlpha?: Trackable<Booleanish | undefined>
|
|
450
453
|
/** The `preserveAspectRatio` SVG attribute. */
|
|
451
454
|
preserveAspectRatio?: Trackable<string | undefined>
|
|
452
455
|
/** The `primitiveUnits` SVG attribute. */
|
|
@@ -1263,7 +1266,7 @@ export interface AllHTMLProps<eventTarget extends EventTarget = EventTarget>
|
|
|
1263
1266
|
/** The `decoding` HTML attribute. */
|
|
1264
1267
|
decoding?: Trackable<'sync' | 'async' | 'auto' | undefined>
|
|
1265
1268
|
/** The `draggable` HTML attribute. */
|
|
1266
|
-
draggable?: Trackable<
|
|
1269
|
+
draggable?: Trackable<Booleanish | undefined>
|
|
1267
1270
|
/** The `encType` HTML attribute. */
|
|
1268
1271
|
encType?: Trackable<string | undefined>
|
|
1269
1272
|
/** The `enctype` HTML attribute. */
|
|
@@ -1487,7 +1490,9 @@ export interface AllHTMLProps<eventTarget extends EventTarget = EventTarget>
|
|
|
1487
1490
|
/** The `span` HTML attribute. */
|
|
1488
1491
|
span?: Trackable<number | undefined>
|
|
1489
1492
|
/** The `spellcheck` HTML attribute. */
|
|
1490
|
-
spellcheck?: Trackable<
|
|
1493
|
+
spellcheck?: Trackable<Booleanish | undefined>
|
|
1494
|
+
/** The `spellCheck` HTML attribute. */
|
|
1495
|
+
spellCheck?: Trackable<Booleanish | undefined>
|
|
1491
1496
|
/** The `src` HTML attribute. */
|
|
1492
1497
|
src?: Trackable<string | undefined>
|
|
1493
1498
|
/** The `srcDoc` HTML attribute. */
|
|
@@ -1551,7 +1556,7 @@ export interface AllHTMLProps<eventTarget extends EventTarget = EventTarget>
|
|
|
1551
1556
|
/** The `results` HTML attribute. */
|
|
1552
1557
|
results?: Trackable<number | undefined>
|
|
1553
1558
|
/** The `translate` HTML attribute. */
|
|
1554
|
-
translate?: Trackable<
|
|
1559
|
+
translate?: Trackable<TranslateValue | undefined>
|
|
1555
1560
|
|
|
1556
1561
|
// RDFa Attributes
|
|
1557
1562
|
/** The `about` HTML attribute. */
|
|
@@ -1632,7 +1637,7 @@ export interface HTMLProps<eventTarget extends EventTarget = EventTarget>
|
|
|
1632
1637
|
/** The `dir` HTML attribute. */
|
|
1633
1638
|
dir?: Trackable<'auto' | 'rtl' | 'ltr' | undefined>
|
|
1634
1639
|
/** The `draggable` HTML attribute. */
|
|
1635
|
-
draggable?: Trackable<
|
|
1640
|
+
draggable?: Trackable<Booleanish | undefined>
|
|
1636
1641
|
/** The `enterkeyhint` HTML attribute. */
|
|
1637
1642
|
enterkeyhint?: Trackable<
|
|
1638
1643
|
'enter' | 'done' | 'go' | 'next' | 'previous' | 'search' | 'send' | undefined
|
|
@@ -1662,7 +1667,9 @@ export interface HTMLProps<eventTarget extends EventTarget = EventTarget>
|
|
|
1662
1667
|
/** The `slot` HTML attribute. */
|
|
1663
1668
|
slot?: Trackable<string | undefined>
|
|
1664
1669
|
/** The `spellcheck` HTML attribute. */
|
|
1665
|
-
spellcheck?: Trackable<
|
|
1670
|
+
spellcheck?: Trackable<Booleanish | undefined>
|
|
1671
|
+
/** The `spellCheck` HTML attribute. */
|
|
1672
|
+
spellCheck?: Trackable<Booleanish | undefined>
|
|
1666
1673
|
/** The `style` HTML attribute. */
|
|
1667
1674
|
style?: Trackable<string | StyleProps | undefined>
|
|
1668
1675
|
/** The `tabindex` HTML attribute. */
|
|
@@ -1672,7 +1679,7 @@ export interface HTMLProps<eventTarget extends EventTarget = EventTarget>
|
|
|
1672
1679
|
/** The `title` HTML attribute. */
|
|
1673
1680
|
title?: Trackable<string | undefined>
|
|
1674
1681
|
/** The `translate` HTML attribute. */
|
|
1675
|
-
translate?: Trackable<
|
|
1682
|
+
translate?: Trackable<TranslateValue | undefined>
|
|
1676
1683
|
|
|
1677
1684
|
// WAI-ARIA Attributes
|
|
1678
1685
|
// Most elements only allow a subset of roles and so this
|
|
@@ -3418,6 +3425,10 @@ export interface TemplateHTMLProps<eventTarget extends EventTarget = HTMLTemplat
|
|
|
3418
3425
|
*/
|
|
3419
3426
|
export interface TextareaHTMLProps<eventTarget extends EventTarget = HTMLTextAreaElement>
|
|
3420
3427
|
extends HTMLProps<eventTarget> {
|
|
3428
|
+
/** Textarea content comes from `value` or `defaultValue`. */
|
|
3429
|
+
children?: never
|
|
3430
|
+
/** Textarea content comes from `value` or `defaultValue`. */
|
|
3431
|
+
innerHTML?: never
|
|
3421
3432
|
/** The `autocomplete` HTML attribute. */
|
|
3422
3433
|
autocomplete?: Trackable<string | undefined>
|
|
3423
3434
|
/** The `autoComplete` HTML attribute. */
|
package/src/runtime/frame.ts
CHANGED
|
@@ -8,6 +8,7 @@ import type { Scheduler, VirtualRoot } from './vdom.ts'
|
|
|
8
8
|
import { createRangeRoot, createRoot } from './vdom.ts'
|
|
9
9
|
import { diffNodes } from './diff-dom.ts'
|
|
10
10
|
import { createStyleManager, type StyleManager } from '../style/index.ts'
|
|
11
|
+
import { findFlushMarker, type FlushKind } from './stream-protocol.ts'
|
|
11
12
|
|
|
12
13
|
type FrameRoot = [Comment, Comment] | Element | Document | DocumentFragment
|
|
13
14
|
|
|
@@ -39,12 +40,31 @@ type FrameMarkerData = FrameData & {
|
|
|
39
40
|
type PendingClientEntries = Map<Comment, [Comment, RemixElement]>
|
|
40
41
|
|
|
41
42
|
/**
|
|
42
|
-
* Loads a client
|
|
43
|
+
* Loads a named client-entry export for hydration.
|
|
44
|
+
*
|
|
45
|
+
* @param moduleUrl Browser-resolvable URL for the module that contains the client entry.
|
|
46
|
+
* @param exportName Named export to read from the loaded module.
|
|
47
|
+
* @returns The exported component function, or a promise for it.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* run({
|
|
52
|
+
* async loadModule(moduleUrl, exportName) {
|
|
53
|
+
* let mod = await import(moduleUrl)
|
|
54
|
+
* return mod[exportName]
|
|
55
|
+
* },
|
|
56
|
+
* })
|
|
57
|
+
* ```
|
|
43
58
|
*/
|
|
44
59
|
export type LoadModule = (moduleUrl: string, exportName: string) => Promise<Function> | Function
|
|
45
60
|
|
|
46
61
|
/**
|
|
47
|
-
* Resolves
|
|
62
|
+
* Resolves content for a browser-loaded frame.
|
|
63
|
+
*
|
|
64
|
+
* @param src Source string from the `<Frame src>` prop.
|
|
65
|
+
* @param signal Abort signal for the active frame load or reload.
|
|
66
|
+
* @param target Optional name of the frame being reloaded.
|
|
67
|
+
* @returns HTML, a stream of HTML bytes, or Remix node content to render into the frame.
|
|
48
68
|
*/
|
|
49
69
|
export type ResolveFrame = (
|
|
50
70
|
src: string,
|
|
@@ -138,6 +158,7 @@ export type Frame = {
|
|
|
138
158
|
}
|
|
139
159
|
|
|
140
160
|
type RenderOptions = {
|
|
161
|
+
flushKind?: FlushKind
|
|
141
162
|
initialHydrationTracker?: InitialHydrationTracker
|
|
142
163
|
signal?: AbortSignal
|
|
143
164
|
}
|
|
@@ -211,9 +232,9 @@ export function createFrame(root: FrameRoot, init: FrameInit): Frame {
|
|
|
211
232
|
if (options?.signal?.aborted) return
|
|
212
233
|
|
|
213
234
|
if (content instanceof ReadableStream) {
|
|
214
|
-
await renderFrameStream(content, container.doc, async (html) => {
|
|
235
|
+
await renderFrameStream(content, container.doc, async (html, flushKind) => {
|
|
215
236
|
if (options?.signal?.aborted) return
|
|
216
|
-
await render(html, options)
|
|
237
|
+
await render(html, { ...options, flushKind })
|
|
217
238
|
})
|
|
218
239
|
return
|
|
219
240
|
}
|
|
@@ -237,39 +258,42 @@ export function createFrame(root: FrameRoot, init: FrameInit): Frame {
|
|
|
237
258
|
contentRoot = undefined
|
|
238
259
|
}
|
|
239
260
|
|
|
261
|
+
if (typeof content === 'string') {
|
|
262
|
+
let flushed = await consumeFlushBatches(content, async (html, flushKind) => {
|
|
263
|
+
await render(html, { ...options, flushKind })
|
|
264
|
+
})
|
|
265
|
+
if (flushed.applied) {
|
|
266
|
+
if (flushed.remainder !== '') {
|
|
267
|
+
await render(flushed.remainder, { ...options, flushKind: 'fragment' })
|
|
268
|
+
}
|
|
269
|
+
return
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
240
273
|
let htmlContent = typeof content === 'string' ? stripDoctypeMarkup(content) : undefined
|
|
241
274
|
|
|
242
275
|
let isFullDocumentReload =
|
|
243
276
|
container.root instanceof Document &&
|
|
244
277
|
htmlContent !== undefined &&
|
|
245
|
-
|
|
278
|
+
options?.flushKind === 'document'
|
|
246
279
|
|
|
247
280
|
if (isFullDocumentReload && htmlContent !== undefined) {
|
|
248
|
-
// Full-document reload should tear down existing hydrated roots and subframes
|
|
249
|
-
// before diffing fresh HTML, otherwise stale component instances can survive
|
|
250
|
-
// on detached DOM nodes.
|
|
251
|
-
let previousBodyNodes = Array.from(container.doc.body.childNodes)
|
|
252
|
-
removeVirtualRoots(previousBodyNodes)
|
|
253
|
-
disposeSubFrames(previousBodyNodes, context)
|
|
254
281
|
let parsed = new DOMParser().parseFromString(htmlContent, 'text/html')
|
|
255
282
|
mergeRmxDataFromDocument(context.data, parsed)
|
|
256
|
-
context.styleManager.
|
|
257
|
-
context.styleManager.adoptServerStyles(
|
|
283
|
+
context.styleManager.replaceServerStyles(
|
|
258
284
|
collectFrameServerStyleTags(createElementContainer(parsed)),
|
|
259
285
|
)
|
|
260
286
|
|
|
261
287
|
syncElementAttributes(container.doc.documentElement, parsed.documentElement)
|
|
262
|
-
syncElementAttributes(container.doc.head, parsed.head)
|
|
263
|
-
syncElementAttributes(container.doc.body, parsed.body)
|
|
264
288
|
|
|
265
|
-
diffNodes(
|
|
289
|
+
diffNodes([container.doc.head], [parsed.head], {
|
|
266
290
|
...context,
|
|
267
|
-
regionParent: container.doc.
|
|
291
|
+
regionParent: container.doc.documentElement,
|
|
268
292
|
regionTailRef: null,
|
|
269
293
|
})
|
|
270
|
-
diffNodes(
|
|
294
|
+
diffNodes([container.doc.body], [parsed.body], {
|
|
271
295
|
...context,
|
|
272
|
-
regionParent: container.doc.
|
|
296
|
+
regionParent: container.doc.documentElement,
|
|
273
297
|
regionTailRef: null,
|
|
274
298
|
})
|
|
275
299
|
|
|
@@ -282,8 +306,7 @@ export function createFrame(root: FrameRoot, init: FrameInit): Frame {
|
|
|
282
306
|
|
|
283
307
|
let fragment =
|
|
284
308
|
htmlContent !== undefined ? createFragmentFromString(container.doc, htmlContent) : content
|
|
285
|
-
context.styleManager.
|
|
286
|
-
context.styleManager.adoptServerStyles(
|
|
309
|
+
context.styleManager.replaceServerStyles(
|
|
287
310
|
collectFrameServerStyleTags(createElementContainer(fragment)),
|
|
288
311
|
)
|
|
289
312
|
removeEmptyHeads(fragment)
|
|
@@ -344,8 +367,7 @@ export function createFrame(root: FrameRoot, init: FrameInit): Frame {
|
|
|
344
367
|
async function hydrateInitial(): Promise<void> {
|
|
345
368
|
let initialHydrationTracker = createInitialHydrationTracker()
|
|
346
369
|
|
|
347
|
-
context.styleManager.
|
|
348
|
-
context.styleManager.adoptServerStyles(collectFrameServerStyleTags(container))
|
|
370
|
+
context.styleManager.replaceServerStyles(collectFrameServerStyleTags(container))
|
|
349
371
|
createSubFrames(container.childNodes, context)
|
|
350
372
|
scheduleHydrationInContainer(container, context, initialHydrationTracker)
|
|
351
373
|
|
|
@@ -986,13 +1008,12 @@ function extractTemplatesFromBuffer(
|
|
|
986
1008
|
async function renderFrameStream(
|
|
987
1009
|
stream: ReadableStream<Uint8Array>,
|
|
988
1010
|
doc: Document,
|
|
989
|
-
applyHtml: (html: string) => Promise<void>,
|
|
1011
|
+
applyHtml: (html: string, flushKind: FlushKind) => Promise<void>,
|
|
990
1012
|
): Promise<void> {
|
|
991
1013
|
let reader = stream.getReader()
|
|
992
1014
|
let decoder = new TextDecoder()
|
|
993
1015
|
let buffer = ''
|
|
994
1016
|
let html = ''
|
|
995
|
-
let appliedLength = 0
|
|
996
1017
|
let appliedOnce = false
|
|
997
1018
|
|
|
998
1019
|
try {
|
|
@@ -1006,13 +1027,9 @@ async function renderFrameStream(
|
|
|
1006
1027
|
|
|
1007
1028
|
if (parsed.html !== '') {
|
|
1008
1029
|
html += parsed.html
|
|
1009
|
-
let
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
}
|
|
1013
|
-
await applyHtml(html)
|
|
1014
|
-
appliedLength = html.length
|
|
1015
|
-
appliedOnce = true
|
|
1030
|
+
let flushed = await consumeFlushBatches(html, applyHtml)
|
|
1031
|
+
appliedOnce = flushed.applied || appliedOnce
|
|
1032
|
+
html = flushed.remainder
|
|
1016
1033
|
}
|
|
1017
1034
|
}
|
|
1018
1035
|
|
|
@@ -1025,21 +1042,40 @@ async function renderFrameStream(
|
|
|
1025
1042
|
buffer = ''
|
|
1026
1043
|
}
|
|
1027
1044
|
|
|
1028
|
-
if (html !== ''
|
|
1029
|
-
await applyHtml(html)
|
|
1045
|
+
if (html !== '') {
|
|
1046
|
+
await applyHtml(html, 'fragment')
|
|
1030
1047
|
appliedOnce = true
|
|
1031
1048
|
}
|
|
1032
1049
|
|
|
1033
1050
|
// A frame stream can legitimately resolve to empty content. Ensure the
|
|
1034
1051
|
// existing frame region is cleared instead of treated as a no-op.
|
|
1035
1052
|
if (html === '' && !appliedOnce) {
|
|
1036
|
-
await applyHtml('')
|
|
1053
|
+
await applyHtml('', 'fragment')
|
|
1037
1054
|
}
|
|
1038
1055
|
} finally {
|
|
1039
1056
|
reader.releaseLock()
|
|
1040
1057
|
}
|
|
1041
1058
|
}
|
|
1042
1059
|
|
|
1060
|
+
async function consumeFlushBatches(
|
|
1061
|
+
html: string,
|
|
1062
|
+
applyHtml: (html: string, flushKind: FlushKind) => Promise<void>,
|
|
1063
|
+
): Promise<{ applied: boolean; remainder: string }> {
|
|
1064
|
+
let applied = false
|
|
1065
|
+
let cursor = 0
|
|
1066
|
+
let marker = findFlushMarker(html, cursor)
|
|
1067
|
+
|
|
1068
|
+
while (marker) {
|
|
1069
|
+
let batch = html.slice(cursor, marker.index)
|
|
1070
|
+
await applyHtml(batch, marker.kind)
|
|
1071
|
+
applied = true
|
|
1072
|
+
cursor = marker.endIndex
|
|
1073
|
+
marker = findFlushMarker(html, cursor)
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
return { applied, remainder: html.slice(cursor) }
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1043
1079
|
type FrameContainer = {
|
|
1044
1080
|
doc: Document
|
|
1045
1081
|
root: ParentNode
|
|
@@ -1104,11 +1140,6 @@ function isRemixNodeFrameContent(content: InternalFrameContent): content is Remi
|
|
|
1104
1140
|
)
|
|
1105
1141
|
}
|
|
1106
1142
|
|
|
1107
|
-
function isFullDocumentHtml(content: string): boolean {
|
|
1108
|
-
let trimmed = content.trimStart()
|
|
1109
|
-
return /^<!doctype html\b/i.test(trimmed) || /^<html[\s>]/i.test(trimmed)
|
|
1110
|
-
}
|
|
1111
|
-
|
|
1112
1143
|
type HydrationMarker = {
|
|
1113
1144
|
id: string
|
|
1114
1145
|
start: Comment
|
|
@@ -1201,18 +1232,3 @@ function findEndMarker(
|
|
|
1201
1232
|
|
|
1202
1233
|
throw new Error('End marker not found')
|
|
1203
1234
|
}
|
|
1204
|
-
|
|
1205
|
-
function collectHtmlMarkerSummary(html: string): Record<string, number> {
|
|
1206
|
-
return {
|
|
1207
|
-
frameStarts: html.match(/<!--\s*rmx:f:/g)?.length ?? 0,
|
|
1208
|
-
frameEnds: html.match(/<!--\s*\/rmx:f\s*-->/g)?.length ?? 0,
|
|
1209
|
-
hydrationStarts: html.match(/<!--\s*rmx:h:/g)?.length ?? 0,
|
|
1210
|
-
hydrationEnds: html.match(/<!--\s*\/rmx:h\s*-->/g)?.length ?? 0,
|
|
1211
|
-
}
|
|
1212
|
-
}
|
|
1213
|
-
|
|
1214
|
-
function hasBalancedMarkerSummary(summary: Record<string, number>): boolean {
|
|
1215
|
-
return (
|
|
1216
|
-
summary.frameStarts === summary.frameEnds && summary.hydrationStarts === summary.hydrationEnds
|
|
1217
|
-
)
|
|
1218
|
-
}
|
package/src/runtime/jsx.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type * as dom from './dom.d.ts'
|
|
2
2
|
import type { Handle, RenderFn } from './component.ts'
|
|
3
|
+
import { createRemixElement } from './core/vnode.ts'
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Any valid element type accepted by JSX or {@link import('./create-element.ts').createElement}.
|
|
@@ -43,7 +44,7 @@ export type Renderable = RemixElement | string | number | bigint | boolean | nul
|
|
|
43
44
|
* Particularly useful for `props.children`.
|
|
44
45
|
*
|
|
45
46
|
* ```tsx
|
|
46
|
-
* function MyComponent(
|
|
47
|
+
* function MyComponent(handle: Handle<{ children: RemixNode }>) {}
|
|
47
48
|
* ```
|
|
48
49
|
*/
|
|
49
50
|
export type RemixNode = Renderable | RemixNode[]
|
|
@@ -102,7 +103,7 @@ export type Props<T extends keyof JSX.IntrinsicElements> = NormalizeMixProp<
|
|
|
102
103
|
*/
|
|
103
104
|
export function jsx(type: ElementType, props: ElementProps, key?: string): RemixElement
|
|
104
105
|
export function jsx(type: ElementType, props: ElementProps, key?: string): RemixElement {
|
|
105
|
-
return
|
|
106
|
+
return createRemixElement(type, props, key)
|
|
106
107
|
}
|
|
107
108
|
|
|
108
109
|
export { jsx as jsxDEV, jsx as jsxs }
|
|
@@ -367,31 +368,3 @@ declare global {
|
|
|
367
368
|
IntrinsicHTMLElements {}
|
|
368
369
|
}
|
|
369
370
|
}
|
|
370
|
-
|
|
371
|
-
function normalizeElementProps(props: ElementProps | null | undefined): ElementProps {
|
|
372
|
-
if (!props) return {}
|
|
373
|
-
if (!('mix' in props)) return props
|
|
374
|
-
|
|
375
|
-
let { mix, ...rest } = props
|
|
376
|
-
let normalizedMix = normalizeMixValue(mix)
|
|
377
|
-
return normalizedMix === undefined ? rest : { ...rest, mix: normalizedMix }
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
function normalizeMixValue(mix: unknown): unknown[] | undefined {
|
|
381
|
-
if (!mix) return undefined
|
|
382
|
-
|
|
383
|
-
let normalizedMix: unknown[] = []
|
|
384
|
-
flattenMixValue(mix, normalizedMix)
|
|
385
|
-
return normalizedMix.length === 0 ? undefined : normalizedMix
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
function flattenMixValue(mix: unknown, out: unknown[]): void {
|
|
389
|
-
if (!mix) return
|
|
390
|
-
if (!Array.isArray(mix)) {
|
|
391
|
-
out.push(mix)
|
|
392
|
-
return
|
|
393
|
-
}
|
|
394
|
-
for (let item of mix) {
|
|
395
|
-
flattenMixValue(item, out)
|
|
396
|
-
}
|
|
397
|
-
}
|