@vidact/runtime 0.2.0-beta.0 → 0.2.0-beta.4
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/CHANGELOG.md +37 -0
- package/README.md +1 -1
- package/dist/actions.d.ts +32 -30
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +251 -266
- package/dist/actions.js.map +1 -1
- package/dist/async.d.ts +20 -17
- package/dist/async.d.ts.map +1 -1
- package/dist/async.js +18 -17
- package/dist/async.js.map +1 -1
- package/dist/compiled/async-resource.d.ts +9 -6
- package/dist/compiled/async-resource.d.ts.map +1 -1
- package/dist/compiled/async-resource.js +69 -77
- package/dist/compiled/async-resource.js.map +1 -1
- package/dist/compiled/core.d.ts +136 -147
- package/dist/compiled/core.d.ts.map +1 -1
- package/dist/compiled/core.js +2669 -2985
- package/dist/compiled/core.js.map +1 -1
- package/dist/compiled/types.d.ts +44 -56
- package/dist/compiled/types.d.ts.map +1 -1
- package/dist/compiled/types.js +10 -6
- package/dist/compiled/types.js.map +1 -1
- package/dist/compiled/validation.d.ts +4 -1
- package/dist/compiled/validation.d.ts.map +1 -1
- package/dist/compiled/validation.js +17 -20
- package/dist/compiled/validation.js.map +1 -1
- package/dist/component-spread.d.ts +5 -3
- package/dist/component-spread.d.ts.map +1 -1
- package/dist/component-spread.js +49 -67
- package/dist/component-spread.js.map +1 -1
- package/dist/concurrent.d.ts +20 -18
- package/dist/concurrent.d.ts.map +1 -1
- package/dist/concurrent.js +191 -210
- package/dist/concurrent.js.map +1 -1
- package/dist/direct-dom.d.ts +17 -12
- package/dist/direct-dom.d.ts.map +1 -1
- package/dist/direct-dom.js +187 -221
- package/dist/direct-dom.js.map +1 -1
- package/dist/dom/attributes.d.ts +9 -6
- package/dist/dom/attributes.d.ts.map +1 -1
- package/dist/dom/attributes.js +65 -47
- package/dist/dom/attributes.js.map +1 -1
- package/dist/dom/events.d.ts +5 -2
- package/dist/dom/events.d.ts.map +1 -1
- package/dist/dom/events.js +53 -65
- package/dist/dom/events.js.map +1 -1
- package/dist/dom/forms.d.ts +9 -6
- package/dist/dom/forms.d.ts.map +1 -1
- package/dist/dom/forms.js +152 -198
- package/dist/dom/forms.js.map +1 -1
- package/dist/dom/intrinsic.d.ts +17 -15
- package/dist/dom/intrinsic.d.ts.map +1 -1
- package/dist/dom/intrinsic.js +48 -50
- package/dist/dom/intrinsic.js.map +1 -1
- package/dist/dom/namespace.d.ts +4 -1
- package/dist/dom/namespace.d.ts.map +1 -1
- package/dist/dom/namespace.js +25 -28
- package/dist/dom/namespace.js.map +1 -1
- package/dist/dom/namespaces.d.ts +11 -8
- package/dist/dom/namespaces.d.ts.map +1 -1
- package/dist/dom/namespaces.js +14 -12
- package/dist/dom/namespaces.js.map +1 -1
- package/dist/dom/properties.d.ts +18 -16
- package/dist/dom/properties.d.ts.map +1 -1
- package/dist/dom/properties.js +273 -296
- package/dist/dom/properties.js.map +1 -1
- package/dist/dom/style-properties.d.ts +4 -1
- package/dist/dom/style-properties.d.ts.map +1 -1
- package/dist/dom/style-properties.js +49 -45
- package/dist/dom/style-properties.js.map +1 -1
- package/dist/dom/styles.d.ts +5 -2
- package/dist/dom/styles.d.ts.map +1 -1
- package/dist/dom/styles.js +47 -67
- package/dist/dom/styles.js.map +1 -1
- package/dist/dom-forms.d.ts +4 -1
- package/dist/dom-forms.d.ts.map +1 -1
- package/dist/dom-forms.js +16 -13
- package/dist/dom-forms.js.map +1 -1
- package/dist/dom-styles.d.ts +4 -1
- package/dist/dom-styles.d.ts.map +1 -1
- package/dist/dom-styles.js +10 -7
- package/dist/dom-styles.js.map +1 -1
- package/dist/framework-hydrate.d.ts +20 -17
- package/dist/framework-hydrate.d.ts.map +1 -1
- package/dist/framework-hydrate.js +128 -146
- package/dist/framework-hydrate.js.map +1 -1
- package/dist/framework-protocol.d.ts +27 -25
- package/dist/framework-protocol.d.ts.map +1 -1
- package/dist/framework-protocol.js +173 -211
- package/dist/framework-protocol.js.map +1 -1
- package/dist/framework.d.ts +34 -32
- package/dist/framework.d.ts.map +1 -1
- package/dist/framework.js +74 -93
- package/dist/framework.js.map +1 -1
- package/dist/hydrate.d.ts +11 -8
- package/dist/hydrate.d.ts.map +1 -1
- package/dist/hydrate.js +13 -9
- package/dist/hydrate.js.map +1 -1
- package/dist/hydration-bridge.d.ts +61 -58
- package/dist/hydration-bridge.d.ts.map +1 -1
- package/dist/hydration-bridge.js +67 -66
- package/dist/hydration-bridge.js.map +1 -1
- package/dist/hydration.d.ts +31 -28
- package/dist/hydration.d.ts.map +1 -1
- package/dist/hydration.js +376 -462
- package/dist/hydration.js.map +1 -1
- package/dist/index.d.ts +13 -13
- package/dist/index.js +11 -13
- package/dist/indexed-list.d.ts +8 -5
- package/dist/indexed-list.d.ts.map +1 -1
- package/dist/indexed-list.js +14 -7
- package/dist/indexed-list.js.map +1 -1
- package/dist/jsx-runtime.d.ts +10 -8
- package/dist/jsx-runtime.d.ts.map +1 -1
- package/dist/jsx-runtime.js +28 -23
- package/dist/jsx-runtime.js.map +1 -1
- package/dist/keyed-list.d.ts +13 -14
- package/dist/keyed-list.d.ts.map +1 -1
- package/dist/keyed-list.js +132 -160
- package/dist/keyed-list.js.map +1 -1
- package/dist/metadata.d.ts +6 -3
- package/dist/metadata.d.ts.map +1 -1
- package/dist/metadata.js +131 -164
- package/dist/metadata.js.map +1 -1
- package/dist/nested-prop.d.ts +4 -2
- package/dist/nested-prop.d.ts.map +1 -1
- package/dist/nested-prop.js +17 -16
- package/dist/nested-prop.js.map +1 -1
- package/dist/profiling.d.ts +11 -8
- package/dist/profiling.d.ts.map +1 -1
- package/dist/profiling.js +17 -17
- package/dist/profiling.js.map +1 -1
- package/dist/protocol.d.ts +5 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +8 -5
- package/dist/protocol.js.map +1 -1
- package/dist/raw-html.d.ts +5 -2
- package/dist/raw-html.d.ts.map +1 -1
- package/dist/raw-html.js +86 -146
- package/dist/raw-html.js.map +1 -1
- package/dist/ref.d.ts +8 -3
- package/dist/ref.d.ts.map +1 -1
- package/dist/ref.js +10 -2
- package/dist/ref.js.map +1 -1
- package/dist/renderable-protocol.d.ts +26 -8
- package/dist/renderable-protocol.d.ts.map +1 -1
- package/dist/renderable-protocol.js +30 -9
- package/dist/renderable-protocol.js.map +1 -1
- package/dist/renderable.d.ts +27 -22
- package/dist/renderable.d.ts.map +1 -1
- package/dist/renderable.js +141 -133
- package/dist/renderable.js.map +1 -1
- package/dist/retained-ui.d.ts +9 -6
- package/dist/retained-ui.d.ts.map +1 -1
- package/dist/retained-ui.js +12 -10
- package/dist/retained-ui.js.map +1 -1
- package/dist/root.d.ts +18 -15
- package/dist/root.d.ts.map +1 -1
- package/dist/root.js +73 -85
- package/dist/root.js.map +1 -1
- package/dist/scheduler.d.ts +10 -8
- package/dist/scheduler.d.ts.map +1 -1
- package/dist/scheduler.js +97 -105
- package/dist/scheduler.js.map +1 -1
- package/dist/server-framework.d.ts +45 -42
- package/dist/server-framework.d.ts.map +1 -1
- package/dist/server-framework.js +209 -217
- package/dist/server-framework.js.map +1 -1
- package/dist/server.d.ts +130 -128
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +592 -706
- package/dist/server.js.map +1 -1
- package/dist/shared/promise.d.ts +6 -3
- package/dist/shared/promise.d.ts.map +1 -1
- package/dist/shared/promise.js +21 -19
- package/dist/shared/promise.js.map +1 -1
- package/dist/source-mask.d.ts +9 -6
- package/dist/source-mask.d.ts.map +1 -1
- package/dist/source-mask.js +45 -63
- package/dist/source-mask.js.map +1 -1
- package/dist/spread.d.ts +5 -2
- package/dist/spread.d.ts.map +1 -1
- package/dist/spread.js +79 -99
- package/dist/spread.js.map +1 -1
- package/dist/state-slot.d.ts +18 -15
- package/dist/state-slot.d.ts.map +1 -1
- package/dist/state-slot.js +43 -42
- package/dist/state-slot.js.map +1 -1
- package/dist/testing.d.ts +9 -6
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +16 -12
- package/dist/testing.js.map +1 -1
- package/package.json +8 -7
- package/src/actions.ts +415 -0
- package/src/async.ts +78 -0
- package/src/compiled/async-resource.ts +113 -0
- package/src/compiled/core.ts +4026 -0
- package/src/compiled/types.ts +96 -0
- package/src/compiled/validation.ts +23 -0
- package/src/component-spread.ts +86 -0
- package/src/concurrent.ts +310 -0
- package/src/direct-dom.ts +365 -0
- package/src/dom/attributes.ts +55 -0
- package/src/dom/events.ts +93 -0
- package/src/dom/forms.ts +220 -0
- package/src/dom/intrinsic.ts +94 -0
- package/src/dom/namespace.ts +30 -0
- package/src/dom/namespaces.ts +14 -0
- package/src/dom/properties.ts +355 -0
- package/src/dom/style-properties.ts +46 -0
- package/src/dom/styles.ts +86 -0
- package/src/dom-forms.ts +23 -0
- package/src/dom-styles.ts +11 -0
- package/src/env.d.ts +6 -0
- package/src/framework-hydrate.ts +224 -0
- package/src/framework-protocol.ts +335 -0
- package/src/framework.ts +161 -0
- package/src/hydrate.ts +38 -0
- package/src/hydration-bridge.ts +183 -0
- package/src/hydration.ts +556 -0
- package/src/index.ts +92 -0
- package/src/indexed-list.ts +20 -0
- package/src/jsx-runtime.ts +55 -0
- package/src/keyed-list.ts +233 -0
- package/src/metadata.ts +212 -0
- package/src/nested-prop.ts +27 -0
- package/src/profiling.ts +43 -0
- package/src/protocol.ts +8 -0
- package/src/raw-html.ts +206 -0
- package/src/ref.ts +13 -0
- package/src/renderable-protocol.ts +63 -0
- package/src/renderable.ts +283 -0
- package/src/retained-ui.ts +19 -0
- package/src/root.ts +122 -0
- package/src/scheduler.ts +136 -0
- package/src/server-framework.ts +397 -0
- package/src/server.ts +1143 -0
- package/src/shared/promise.ts +28 -0
- package/src/source-mask.ts +83 -0
- package/src/spread.ts +131 -0
- package/src/state-slot.ts +76 -0
- package/src/testing.ts +27 -0
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import { validateRawHtmlRelatedProp } from '../raw-html.ts'
|
|
2
|
+
import {
|
|
3
|
+
MATHML_NAMESPACE,
|
|
4
|
+
SVG_NAMESPACE,
|
|
5
|
+
XLINK_NAMESPACE,
|
|
6
|
+
XML_NAMESPACE,
|
|
7
|
+
XMLNS_NAMESPACE,
|
|
8
|
+
} from './namespaces.ts'
|
|
9
|
+
|
|
10
|
+
const DEV = typeof __VIDACT_DEV__ === 'undefined' || __VIDACT_DEV__
|
|
11
|
+
const UNSAFE_HTML = typeof __VIDACT_UNSAFE_HTML__ === 'undefined' || __VIDACT_UNSAFE_HTML__
|
|
12
|
+
|
|
13
|
+
const booleanAttributes = new Set([
|
|
14
|
+
'allowFullScreen',
|
|
15
|
+
'async',
|
|
16
|
+
'autoFocus',
|
|
17
|
+
'autoPlay',
|
|
18
|
+
'controls',
|
|
19
|
+
'default',
|
|
20
|
+
'defer',
|
|
21
|
+
'disabled',
|
|
22
|
+
'disablePictureInPicture',
|
|
23
|
+
'disableRemotePlayback',
|
|
24
|
+
'formNoValidate',
|
|
25
|
+
'hidden',
|
|
26
|
+
'inert',
|
|
27
|
+
'itemScope',
|
|
28
|
+
'loop',
|
|
29
|
+
'noModule',
|
|
30
|
+
'noValidate',
|
|
31
|
+
'open',
|
|
32
|
+
'playsInline',
|
|
33
|
+
'readOnly',
|
|
34
|
+
'required',
|
|
35
|
+
'reversed',
|
|
36
|
+
])
|
|
37
|
+
const booleanishStringAttributes = new Set(['contentEditable', 'draggable', 'spellCheck'])
|
|
38
|
+
const overloadedBooleanAttributes = new Set(['capture', 'download'])
|
|
39
|
+
const mathBooleanishStringAttributes = new Set([
|
|
40
|
+
'accent',
|
|
41
|
+
'accentunder',
|
|
42
|
+
'displaystyle',
|
|
43
|
+
'fence',
|
|
44
|
+
'largeop',
|
|
45
|
+
'movablelimits',
|
|
46
|
+
'separator',
|
|
47
|
+
'stretchy',
|
|
48
|
+
'symmetric',
|
|
49
|
+
])
|
|
50
|
+
const svgBooleanishStringAttributes = new Set(['focusable', 'preserveAlpha'])
|
|
51
|
+
|
|
52
|
+
const kebabCaseSvgAttributes = new Set([
|
|
53
|
+
'accentHeight',
|
|
54
|
+
'alignmentBaseline',
|
|
55
|
+
'arabicForm',
|
|
56
|
+
'baselineShift',
|
|
57
|
+
'capHeight',
|
|
58
|
+
'clipPath',
|
|
59
|
+
'clipRule',
|
|
60
|
+
'colorInterpolation',
|
|
61
|
+
'colorInterpolationFilters',
|
|
62
|
+
'colorProfile',
|
|
63
|
+
'colorRendering',
|
|
64
|
+
'dominantBaseline',
|
|
65
|
+
'enableBackground',
|
|
66
|
+
'fillOpacity',
|
|
67
|
+
'fillRule',
|
|
68
|
+
'floodColor',
|
|
69
|
+
'floodOpacity',
|
|
70
|
+
'fontFamily',
|
|
71
|
+
'fontSize',
|
|
72
|
+
'fontSizeAdjust',
|
|
73
|
+
'fontStretch',
|
|
74
|
+
'fontStyle',
|
|
75
|
+
'fontVariant',
|
|
76
|
+
'fontWeight',
|
|
77
|
+
'glyphName',
|
|
78
|
+
'glyphOrientationHorizontal',
|
|
79
|
+
'glyphOrientationVertical',
|
|
80
|
+
'horizAdvX',
|
|
81
|
+
'horizOriginX',
|
|
82
|
+
'imageRendering',
|
|
83
|
+
'letterSpacing',
|
|
84
|
+
'lightingColor',
|
|
85
|
+
'markerEnd',
|
|
86
|
+
'markerMid',
|
|
87
|
+
'markerStart',
|
|
88
|
+
'overlinePosition',
|
|
89
|
+
'overlineThickness',
|
|
90
|
+
'paintOrder',
|
|
91
|
+
'pointerEvents',
|
|
92
|
+
'renderingIntent',
|
|
93
|
+
'shapeRendering',
|
|
94
|
+
'stopColor',
|
|
95
|
+
'stopOpacity',
|
|
96
|
+
'strikethroughPosition',
|
|
97
|
+
'strikethroughThickness',
|
|
98
|
+
'strokeDasharray',
|
|
99
|
+
'strokeDashoffset',
|
|
100
|
+
'strokeLinecap',
|
|
101
|
+
'strokeLinejoin',
|
|
102
|
+
'strokeMiterlimit',
|
|
103
|
+
'strokeOpacity',
|
|
104
|
+
'strokeWidth',
|
|
105
|
+
'textAnchor',
|
|
106
|
+
'textDecoration',
|
|
107
|
+
'textRendering',
|
|
108
|
+
'transformOrigin',
|
|
109
|
+
'underlinePosition',
|
|
110
|
+
'underlineThickness',
|
|
111
|
+
'unicodeBidi',
|
|
112
|
+
'unicodeRange',
|
|
113
|
+
'unitsPerEm',
|
|
114
|
+
'vAlphabetic',
|
|
115
|
+
'vHanging',
|
|
116
|
+
'vIdeographic',
|
|
117
|
+
'vMathematical',
|
|
118
|
+
'vectorEffect',
|
|
119
|
+
'vertAdvY',
|
|
120
|
+
'vertOriginX',
|
|
121
|
+
'vertOriginY',
|
|
122
|
+
'wordSpacing',
|
|
123
|
+
'writingMode',
|
|
124
|
+
'xHeight',
|
|
125
|
+
])
|
|
126
|
+
|
|
127
|
+
type DomPropHandler = (element: Element, name: string, value: unknown) => boolean
|
|
128
|
+
|
|
129
|
+
export interface FormDomCapability {
|
|
130
|
+
readonly applyProp: DomPropHandler
|
|
131
|
+
readonly ensureControlledRestoration: (element: Element) => () => void
|
|
132
|
+
readonly isControlledProp: (element: Element, name: string) => boolean
|
|
133
|
+
readonly isReactChangeEvent: (element: Element, eventName: string) => boolean
|
|
134
|
+
readonly restoreControlledState: (element: Element) => void
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
type StyleDomCapability = (element: Element, value: unknown) => void
|
|
138
|
+
|
|
139
|
+
let formCapability: FormDomCapability | undefined
|
|
140
|
+
let styleCapability: StyleDomCapability | undefined
|
|
141
|
+
const NOOP = (): void => {}
|
|
142
|
+
|
|
143
|
+
/** @internal */
|
|
144
|
+
export function installFormDomCapability(capability: FormDomCapability): void {
|
|
145
|
+
formCapability = capability
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** @internal */
|
|
149
|
+
export function installStyleDomCapability(capability: StyleDomCapability): void {
|
|
150
|
+
styleCapability = capability
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** @internal */
|
|
154
|
+
export function ensureControlledFormRestoration(element: Element): () => void {
|
|
155
|
+
return formCapability?.ensureControlledRestoration(element) ?? NOOP
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** @internal */
|
|
159
|
+
export function isControlledFormProp(element: Element, name: string): boolean {
|
|
160
|
+
return formCapability?.isControlledProp(element, name) ?? false
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** @internal */
|
|
164
|
+
export function isReactFormChangeEvent(element: Element, eventName: string): boolean {
|
|
165
|
+
return formCapability?.isReactChangeEvent(element, eventName) ?? false
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** @internal */
|
|
169
|
+
export function restoreControlledFormState(element: Element): void {
|
|
170
|
+
formCapability?.restoreControlledState(element)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export let applyDomProp = applyBaseDomProp
|
|
174
|
+
|
|
175
|
+
export function installDomPropHandler(handler: DomPropHandler): void {
|
|
176
|
+
const fallback = applyDomProp
|
|
177
|
+
applyDomProp = (element, name, value) => {
|
|
178
|
+
if (!handler(element, name, value)) fallback(element, name, value)
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/** @internal Specialized capabilities may own a prop while reusing the base policy. */
|
|
183
|
+
export function applyBaseDomProp(element: Element, name: string, value: unknown): void {
|
|
184
|
+
if (typeof value === 'symbol') {
|
|
185
|
+
throw new TypeError(DEV ? `DOM prop ${name} cannot receive a symbol value` : 'V105')
|
|
186
|
+
}
|
|
187
|
+
if (name === 'dangerouslySetInnerHTML') {
|
|
188
|
+
throw new Error(
|
|
189
|
+
DEV ? 'dangerouslySetInnerHTML must be handled as an owned opaque subtree' : 'V401',
|
|
190
|
+
)
|
|
191
|
+
}
|
|
192
|
+
if (name === 'style') {
|
|
193
|
+
if (styleCapability === undefined) {
|
|
194
|
+
throw new Error(DEV ? 'style prop requires the DOM style capability' : 'V503')
|
|
195
|
+
}
|
|
196
|
+
styleCapability(element, value)
|
|
197
|
+
return
|
|
198
|
+
}
|
|
199
|
+
if (formCapability?.applyProp(element, name, value)) return
|
|
200
|
+
if (name.startsWith('data-') || name.startsWith('aria-')) {
|
|
201
|
+
applyStringAttribute(element, name, value)
|
|
202
|
+
return
|
|
203
|
+
}
|
|
204
|
+
if (element.namespaceURI === SVG_NAMESPACE || element.namespaceURI === MATHML_NAMESPACE) {
|
|
205
|
+
applyNamespacedAttribute(element, name, value)
|
|
206
|
+
return
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const attribute = htmlAttributeName(name)
|
|
210
|
+
if (value === null || value === undefined) {
|
|
211
|
+
element.removeAttribute(attribute)
|
|
212
|
+
if (isCustomElement(element) && name in element) Reflect.set(element, name, null)
|
|
213
|
+
validateRawHtmlProp(element, name)
|
|
214
|
+
return
|
|
215
|
+
}
|
|
216
|
+
if (booleanishStringAttributes.has(name)) {
|
|
217
|
+
element.setAttribute(attribute, String(value))
|
|
218
|
+
return
|
|
219
|
+
}
|
|
220
|
+
if (overloadedBooleanAttributes.has(name)) {
|
|
221
|
+
if (value === false) element.removeAttribute(attribute)
|
|
222
|
+
else element.setAttribute(attribute, value === true ? '' : String(value))
|
|
223
|
+
return
|
|
224
|
+
}
|
|
225
|
+
if (booleanAttributes.has(name)) {
|
|
226
|
+
if (name in element) {
|
|
227
|
+
const next = Boolean(value)
|
|
228
|
+
if (!Object.is(Reflect.get(element, name), next)) Reflect.set(element, name, next)
|
|
229
|
+
} else if (value) element.setAttribute(attribute, '')
|
|
230
|
+
else element.removeAttribute(attribute)
|
|
231
|
+
return
|
|
232
|
+
}
|
|
233
|
+
if (typeof value === 'boolean') {
|
|
234
|
+
element.removeAttribute(attribute)
|
|
235
|
+
return
|
|
236
|
+
}
|
|
237
|
+
const serialized = String(value)
|
|
238
|
+
if (element.getAttribute(attribute) === serialized) {
|
|
239
|
+
validateRawHtmlProp(element, name)
|
|
240
|
+
return
|
|
241
|
+
}
|
|
242
|
+
if (name in element) {
|
|
243
|
+
const current = Reflect.get(element, name)
|
|
244
|
+
if (
|
|
245
|
+
!isCustomElement(element) &&
|
|
246
|
+
(Object.is(current, value) || String(current) === serialized)
|
|
247
|
+
) {
|
|
248
|
+
validateRawHtmlProp(element, name)
|
|
249
|
+
return
|
|
250
|
+
}
|
|
251
|
+
if (Reflect.set(element, name, value)) {
|
|
252
|
+
validateRawHtmlProp(element, name)
|
|
253
|
+
return
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
if (element.getAttribute(attribute) !== serialized) {
|
|
257
|
+
element.setAttribute(attribute, serialized)
|
|
258
|
+
}
|
|
259
|
+
validateRawHtmlProp(element, name)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function applyStringAttribute(element: Element, name: string, value: unknown): void {
|
|
263
|
+
if (value === null || value === undefined) element.removeAttribute(name)
|
|
264
|
+
else {
|
|
265
|
+
if (typeof value === 'symbol') {
|
|
266
|
+
throw new TypeError(`cannot apply a Symbol value to DOM attribute ${name}`)
|
|
267
|
+
}
|
|
268
|
+
let serialized: string
|
|
269
|
+
try {
|
|
270
|
+
serialized = String(value)
|
|
271
|
+
} catch (cause) {
|
|
272
|
+
const detail = Array.isArray(value)
|
|
273
|
+
? value.map((item) => (typeof item === 'symbol' ? String(item) : typeof item)).join(',')
|
|
274
|
+
: typeof value
|
|
275
|
+
throw new TypeError(`cannot serialize DOM attribute ${name} from ${detail}`, { cause })
|
|
276
|
+
}
|
|
277
|
+
if (element.getAttribute(name) !== serialized) element.setAttribute(name, serialized)
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function applyNamespacedAttribute(element: Element, name: string, value: unknown): void {
|
|
282
|
+
const descriptor = namespacedAttribute(name)
|
|
283
|
+
if (value === null || value === undefined) {
|
|
284
|
+
if (descriptor.namespace === null) element.removeAttribute(descriptor.qualifiedName)
|
|
285
|
+
else element.removeAttributeNS(descriptor.namespace, descriptor.localName)
|
|
286
|
+
return
|
|
287
|
+
}
|
|
288
|
+
if (
|
|
289
|
+
(element.namespaceURI === MATHML_NAMESPACE && mathBooleanishStringAttributes.has(name)) ||
|
|
290
|
+
(element.namespaceURI === SVG_NAMESPACE && svgBooleanishStringAttributes.has(name))
|
|
291
|
+
) {
|
|
292
|
+
element.setAttribute(descriptor.qualifiedName, String(value))
|
|
293
|
+
return
|
|
294
|
+
}
|
|
295
|
+
if (value === false) {
|
|
296
|
+
if (descriptor.namespace === null) element.removeAttribute(descriptor.qualifiedName)
|
|
297
|
+
else element.removeAttributeNS(descriptor.namespace, descriptor.localName)
|
|
298
|
+
return
|
|
299
|
+
}
|
|
300
|
+
const serialized = value === true ? '' : String(value)
|
|
301
|
+
if (descriptor.namespace === null) element.setAttribute(descriptor.qualifiedName, serialized)
|
|
302
|
+
else element.setAttributeNS(descriptor.namespace, descriptor.qualifiedName, serialized)
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function namespacedAttribute(name: string): {
|
|
306
|
+
namespace: string | null
|
|
307
|
+
qualifiedName: string
|
|
308
|
+
localName: string
|
|
309
|
+
} {
|
|
310
|
+
if (name.startsWith('xlink') && name.length > 5) {
|
|
311
|
+
const localName = lowerInitial(name.slice(5))
|
|
312
|
+
return { namespace: XLINK_NAMESPACE, qualifiedName: `xlink:${localName}`, localName }
|
|
313
|
+
}
|
|
314
|
+
if (name === 'xmlnsXlink') {
|
|
315
|
+
return {
|
|
316
|
+
namespace: XMLNS_NAMESPACE,
|
|
317
|
+
qualifiedName: 'xmlns:xlink',
|
|
318
|
+
localName: 'xlink',
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
if (name.startsWith('xml') && name.length > 3) {
|
|
322
|
+
const localName = lowerInitial(name.slice(3))
|
|
323
|
+
return { namespace: XML_NAMESPACE, qualifiedName: `xml:${localName}`, localName }
|
|
324
|
+
}
|
|
325
|
+
const qualifiedName = svgAttributeName(name)
|
|
326
|
+
return { namespace: null, qualifiedName, localName: qualifiedName }
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function svgAttributeName(name: string): string {
|
|
330
|
+
if (name === 'className') return 'class'
|
|
331
|
+
if (name === 'crossOrigin') return 'crossorigin'
|
|
332
|
+
if (name === 'tabIndex') return 'tabindex'
|
|
333
|
+
if (!kebabCaseSvgAttributes.has(name)) return name
|
|
334
|
+
return name.replace(/[A-Z]/g, (character) => `-${character.toLowerCase()}`)
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function htmlAttributeName(name: string): string {
|
|
338
|
+
if (name === 'className') return 'class'
|
|
339
|
+
if (name === 'htmlFor') return 'for'
|
|
340
|
+
if (name === 'acceptCharset') return 'accept-charset'
|
|
341
|
+
if (name === 'httpEquiv') return 'http-equiv'
|
|
342
|
+
return name
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function isCustomElement(element: Element): element is HTMLElement {
|
|
346
|
+
return element instanceof HTMLElement && element.localName.includes('-')
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function validateRawHtmlProp(element: Element, name: string): void {
|
|
350
|
+
if (UNSAFE_HTML && element instanceof HTMLElement) validateRawHtmlRelatedProp(element, name)
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function lowerInitial(value: string): string {
|
|
354
|
+
return `${value.charAt(0).toLowerCase()}${value.slice(1)}`
|
|
355
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export const UNITLESS_STYLE_PROPERTIES: ReadonlySet<string> = new Set([
|
|
2
|
+
'animationIterationCount',
|
|
3
|
+
'aspectRatio',
|
|
4
|
+
'borderImageOutset',
|
|
5
|
+
'borderImageSlice',
|
|
6
|
+
'borderImageWidth',
|
|
7
|
+
'boxFlex',
|
|
8
|
+
'boxFlexGroup',
|
|
9
|
+
'boxOrdinalGroup',
|
|
10
|
+
'columnCount',
|
|
11
|
+
'columns',
|
|
12
|
+
'fillOpacity',
|
|
13
|
+
'flex',
|
|
14
|
+
'flexGrow',
|
|
15
|
+
'flexNegative',
|
|
16
|
+
'flexOrder',
|
|
17
|
+
'flexPositive',
|
|
18
|
+
'flexShrink',
|
|
19
|
+
'floodOpacity',
|
|
20
|
+
'fontWeight',
|
|
21
|
+
'gridArea',
|
|
22
|
+
'gridColumn',
|
|
23
|
+
'gridColumnEnd',
|
|
24
|
+
'gridColumnSpan',
|
|
25
|
+
'gridColumnStart',
|
|
26
|
+
'gridRow',
|
|
27
|
+
'gridRowEnd',
|
|
28
|
+
'gridRowSpan',
|
|
29
|
+
'gridRowStart',
|
|
30
|
+
'lineClamp',
|
|
31
|
+
'lineHeight',
|
|
32
|
+
'opacity',
|
|
33
|
+
'order',
|
|
34
|
+
'orphans',
|
|
35
|
+
'scale',
|
|
36
|
+
'stopOpacity',
|
|
37
|
+
'strokeDasharray',
|
|
38
|
+
'strokeDashoffset',
|
|
39
|
+
'strokeMiterlimit',
|
|
40
|
+
'strokeOpacity',
|
|
41
|
+
'strokeWidth',
|
|
42
|
+
'tabSize',
|
|
43
|
+
'widows',
|
|
44
|
+
'zIndex',
|
|
45
|
+
'zoom',
|
|
46
|
+
])
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { isHydrating } from '../hydration-bridge.ts'
|
|
2
|
+
import { UNITLESS_STYLE_PROPERTIES } from './style-properties.ts'
|
|
3
|
+
|
|
4
|
+
const DEV = typeof __VIDACT_DEV__ === 'undefined' || __VIDACT_DEV__
|
|
5
|
+
let retainedUiEnabled = typeof __VIDACT_RETAINED_UI__ !== 'undefined' && __VIDACT_RETAINED_UI__
|
|
6
|
+
|
|
7
|
+
/** @internal */
|
|
8
|
+
export function enableRetainedUiStyles(): void {
|
|
9
|
+
retainedUiEnabled = true
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const appliedStyleNames = new WeakMap<Element, Set<string>>()
|
|
13
|
+
|
|
14
|
+
export function applyStyleProp(element: Element, value: unknown): void {
|
|
15
|
+
const style = Reflect.get(element, 'style')
|
|
16
|
+
if (!(style instanceof CSSStyleDeclaration)) {
|
|
17
|
+
throw new TypeError(
|
|
18
|
+
DEV ? 'style is only supported on elements with CSS style declarations' : 'V501',
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
if (value !== null && value !== undefined && typeof value !== 'object') {
|
|
22
|
+
throw new TypeError(DEV ? 'style prop expects an object, null, or undefined' : 'V502')
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const previous = appliedStyleNames.get(element) ?? new Set<string>()
|
|
26
|
+
const nextEntries =
|
|
27
|
+
value === null || value === undefined ? [] : Object.entries(value as Record<string, unknown>)
|
|
28
|
+
const nextNames = new Set<string>()
|
|
29
|
+
for (const [name] of nextEntries) nextNames.add(name)
|
|
30
|
+
|
|
31
|
+
for (const name of previous) {
|
|
32
|
+
if (!nextNames.has(name)) setStyleValue(style, name, '')
|
|
33
|
+
}
|
|
34
|
+
for (const [name, next] of nextEntries) {
|
|
35
|
+
const serialized = serializeStyleValue(name, next)
|
|
36
|
+
if (
|
|
37
|
+
!retainedUiEnabled ||
|
|
38
|
+
!isHydrating() ||
|
|
39
|
+
hydrationStyleValue(element, style, name) !== serialized
|
|
40
|
+
) {
|
|
41
|
+
setStyleValue(style, name, serialized)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (nextNames.size === 0) {
|
|
46
|
+
appliedStyleNames.delete(element)
|
|
47
|
+
if (element.getAttribute('style') === '') element.removeAttribute('style')
|
|
48
|
+
} else {
|
|
49
|
+
appliedStyleNames.set(element, nextNames)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function hydrationStyleValue(element: Element, style: CSSStyleDeclaration, name: string): string {
|
|
54
|
+
if (
|
|
55
|
+
name === 'display' &&
|
|
56
|
+
style.display === 'none' &&
|
|
57
|
+
style.getPropertyPriority('display') === 'important'
|
|
58
|
+
) {
|
|
59
|
+
const cssText = element.getAttribute('style')
|
|
60
|
+
const hiddenDeclaration = 'display:none!important'
|
|
61
|
+
if (cssText?.endsWith(hiddenDeclaration)) {
|
|
62
|
+
const authored = document.createElement('div').style
|
|
63
|
+
authored.cssText = cssText.slice(0, -hiddenDeclaration.length)
|
|
64
|
+
return authored.display
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (name.startsWith('--') || name.includes('-')) return style.getPropertyValue(name)
|
|
68
|
+
return String(Reflect.get(style, name === 'float' ? 'cssFloat' : name) ?? '')
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function serializeStyleValue(name: string, value: unknown): string {
|
|
72
|
+
if (value === null || value === undefined || typeof value === 'boolean' || value === '') return ''
|
|
73
|
+
if (name.startsWith('--')) return String(value).trim()
|
|
74
|
+
if (typeof value === 'number' && value !== 0 && !UNITLESS_STYLE_PROPERTIES.has(name)) {
|
|
75
|
+
return `${value}px`
|
|
76
|
+
}
|
|
77
|
+
return String(value).trim()
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function setStyleValue(style: CSSStyleDeclaration, name: string, value: string): void {
|
|
81
|
+
if (name.startsWith('--') || name.includes('-')) {
|
|
82
|
+
style.setProperty(name, value)
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
Reflect.set(style, name === 'float' ? 'cssFloat' : name, value)
|
|
86
|
+
}
|
package/src/dom-forms.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {
|
|
2
|
+
applyFormProp,
|
|
3
|
+
ensureControlledFormRestoration,
|
|
4
|
+
isControlledFormProp,
|
|
5
|
+
isReactFormChangeEvent,
|
|
6
|
+
restoreControlledFormState,
|
|
7
|
+
} from './dom/forms.ts'
|
|
8
|
+
import { installFormDomCapability } from './dom/properties.ts'
|
|
9
|
+
|
|
10
|
+
let enabled = false
|
|
11
|
+
|
|
12
|
+
/** @internal Compiler-injected activation for form-specific DOM behavior. */
|
|
13
|
+
export function enableDomForms(): void {
|
|
14
|
+
if (enabled) return
|
|
15
|
+
enabled = true
|
|
16
|
+
installFormDomCapability({
|
|
17
|
+
applyProp: applyFormProp,
|
|
18
|
+
ensureControlledRestoration: ensureControlledFormRestoration,
|
|
19
|
+
isControlledProp: isControlledFormProp,
|
|
20
|
+
isReactChangeEvent: isReactFormChangeEvent,
|
|
21
|
+
restoreControlledState: restoreControlledFormState,
|
|
22
|
+
})
|
|
23
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { installStyleDomCapability } from './dom/properties.ts'
|
|
2
|
+
import { applyStyleProp } from './dom/styles.ts'
|
|
3
|
+
|
|
4
|
+
let enabled = false
|
|
5
|
+
|
|
6
|
+
/** @internal Compiler-injected activation for object-valued style props. */
|
|
7
|
+
export function enableDomStyles(): void {
|
|
8
|
+
if (enabled) return
|
|
9
|
+
enabled = true
|
|
10
|
+
installStyleDomCapability(applyStyleProp)
|
|
11
|
+
}
|
package/src/env.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// oxlint-disable-next-line no-underscore-dangle -- Compiler/runtime production define.
|
|
2
|
+
/* oxlint-disable no-underscore-dangle -- Runtime build constants intentionally use reserved global names. */
|
|
3
|
+
|
|
4
|
+
declare const __VIDACT_DEV__: boolean
|
|
5
|
+
declare const __VIDACT_UNSAFE_HTML__: boolean
|
|
6
|
+
declare const __VIDACT_RETAINED_UI__: boolean
|