@remix-run/ui 0.4.0 → 0.5.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 +74 -1
- package/dist/accordion/index.js +2 -2
- package/dist/accordion/primitives.d.ts +1 -1
- package/dist/accordion/primitives.js.map +1 -1
- package/dist/anchor/index.js.map +1 -1
- package/dist/animation/animate-layout-mixin.js +1 -1
- package/dist/animation/animate-layout-mixin.js.map +1 -1
- package/dist/animation/animate-mixins.js +2 -2
- package/dist/animation/animate-mixins.js.map +1 -1
- package/dist/animation/demos/color-interpolation.js +1 -1
- package/dist/animation/demos/color-interpolation.js.map +1 -1
- package/dist/animation/demos/drag-release.d.ts +1 -1
- package/dist/animation/demos/hold-to-confirm.d.ts +3 -3
- package/dist/animation/demos/material-ripple.js +1 -3
- package/dist/animation/demos/material-ripple.js.map +1 -1
- package/dist/animation/index.js +4 -4
- package/dist/animation/spring.js.map +1 -1
- package/dist/breadcrumbs/index.js +2 -2
- package/dist/button/index.js +25 -25
- package/dist/button/index.js.map +1 -1
- package/dist/checkbox/index.js +11 -9
- package/dist/checkbox/index.js.map +1 -1
- package/dist/combobox/index.js +4 -4
- package/dist/combobox/index.js.map +1 -1
- package/dist/combobox/primitives.d.ts +1 -1
- package/dist/combobox/primitives.js +5 -5
- package/dist/combobox/primitives.js.map +1 -1
- package/dist/dev/refresh.d.ts +1 -0
- package/dist/dev/refresh.js +2 -0
- package/dist/dev/refresh.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +14 -14
- package/dist/input/index.js +9 -9
- package/dist/input/index.js.map +1 -1
- package/dist/jsx-runtime.js +2 -2
- package/dist/listbox/index.js +2 -2
- package/dist/menu/hover-aim.js.map +1 -1
- package/dist/menu/index.js +3 -3
- package/dist/menu/primitives.d.ts +1 -1
- package/dist/menu/primitives.js +6 -6
- package/dist/menu/primitives.js.map +1 -1
- package/dist/popover/index.js +3 -3
- package/dist/popover/scroll-lock.js.map +1 -1
- package/dist/radio/index.js +7 -7
- package/dist/radio/index.js.map +1 -1
- package/dist/runtime/client-entry-boundary.d.ts +14 -0
- package/dist/runtime/client-entry-boundary.js +29 -0
- package/dist/runtime/client-entry-boundary.js.map +1 -0
- package/dist/runtime/component.d.ts +19 -4
- package/dist/runtime/component.js +39 -9
- package/dist/runtime/component.js.map +1 -1
- package/dist/runtime/core/attributes.js +36 -3
- package/dist/runtime/core/attributes.js.map +1 -1
- package/dist/runtime/core/children.d.ts +2 -0
- package/dist/runtime/core/children.js +26 -2
- package/dist/runtime/core/children.js.map +1 -1
- package/dist/runtime/core/props.js +2 -2
- package/dist/runtime/core/vnode.d.ts +3 -3
- package/dist/runtime/core/vnode.js +22 -1
- package/dist/runtime/core/vnode.js.map +1 -1
- package/dist/runtime/create-element.d.ts +2 -2
- package/dist/runtime/create-element.js +3 -2
- package/dist/runtime/create-element.js.map +1 -1
- package/dist/runtime/diff-dom.js +294 -219
- package/dist/runtime/diff-dom.js.map +1 -1
- package/dist/runtime/diff-props.js +3 -3
- package/dist/runtime/dom.d.ts +12 -0
- package/dist/runtime/element-function.d.ts +3 -0
- package/dist/runtime/element-function.js +2 -0
- package/dist/runtime/element-function.js.map +1 -0
- package/dist/runtime/form-navigation.d.ts +25 -0
- package/dist/runtime/form-navigation.js +132 -0
- package/dist/runtime/form-navigation.js.map +1 -0
- package/dist/runtime/frame-resolution.d.ts +5 -0
- package/dist/runtime/frame-resolution.js +10 -0
- package/dist/runtime/frame-resolution.js.map +1 -0
- package/dist/runtime/frame.d.ts +58 -15
- package/dist/runtime/frame.js +367 -114
- package/dist/runtime/frame.js.map +1 -1
- package/dist/runtime/jsx.d.ts +1 -1
- package/dist/runtime/jsx.js +1 -1
- package/dist/runtime/jsx.js.map +1 -1
- package/dist/runtime/key.d.ts +1 -0
- package/dist/runtime/key.js +2 -0
- package/dist/runtime/key.js.map +1 -0
- package/dist/runtime/mixins/attrs-mixin.js +2 -2
- package/dist/runtime/mixins/link-mixin.js +4 -3
- package/dist/runtime/mixins/link-mixin.js.map +1 -1
- package/dist/runtime/mixins/mixin.d.ts +15 -10
- package/dist/runtime/mixins/mixin.js +4 -4
- package/dist/runtime/mixins/mixin.js.map +1 -1
- package/dist/runtime/mixins/on-mixin.js +1 -1
- package/dist/runtime/mixins/ref-mixin.js +1 -1
- package/dist/runtime/navigation.d.ts +4 -1
- package/dist/runtime/navigation.js +157 -32
- package/dist/runtime/navigation.js.map +1 -1
- package/dist/runtime/reconcile.d.ts +11 -10
- package/dist/runtime/reconcile.js +549 -421
- package/dist/runtime/reconcile.js.map +1 -1
- package/dist/runtime/refresh.d.ts +28 -0
- package/dist/runtime/refresh.js +31 -0
- package/dist/runtime/refresh.js.map +1 -0
- package/dist/runtime/render.js +1 -1
- package/dist/runtime/render.js.map +1 -1
- package/dist/runtime/run.d.ts +3 -1
- package/dist/runtime/run.js +15 -7
- package/dist/runtime/run.js.map +1 -1
- package/dist/runtime/scheduler.js +8 -16
- package/dist/runtime/scheduler.js.map +1 -1
- package/dist/runtime/to-vnode.d.ts +2 -2
- package/dist/runtime/to-vnode.js +68 -20
- package/dist/runtime/to-vnode.js.map +1 -1
- package/dist/runtime/vdom.d.ts +4 -2
- package/dist/runtime/vdom.js +87 -42
- package/dist/runtime/vdom.js.map +1 -1
- package/dist/runtime/vnode.d.ts +138 -67
- package/dist/runtime/vnode.js +17 -12
- package/dist/runtime/vnode.js.map +1 -1
- package/dist/select/index.js +11 -11
- package/dist/select/index.js.map +1 -1
- package/dist/select/primitives.d.ts +1 -1
- package/dist/select/primitives.js +6 -6
- package/dist/server/stream.js +20 -27
- package/dist/server/stream.js.map +1 -1
- package/dist/shared/focus-styles.d.ts +1 -1
- package/dist/shared/focus-styles.js +1 -1
- package/dist/shared/focus-styles.js.map +1 -1
- package/dist/shared/listbox-popover-styles.js +1 -1
- package/dist/shared/style-values.js +26 -26
- package/dist/shared/style-values.js.map +1 -1
- package/dist/style/css-mixin.js +3 -3
- package/dist/style/index.js +2 -2
- package/dist/style/style.js +25 -6
- package/dist/style/style.js.map +1 -1
- package/dist/style/stylesheet.d.ts +0 -1
- package/dist/style/stylesheet.js +13 -54
- package/dist/style/stylesheet.js.map +1 -1
- package/dist/tabs/index.js +11 -11
- package/dist/tabs/index.js.map +1 -1
- package/dist/tabs/primitives.d.ts +1 -1
- package/dist/test.js +1 -1
- package/dist/toggle/index.js +9 -9
- package/dist/toggle/index.js.map +1 -1
- package/dist/toggle/primitives.d.ts +1 -1
- package/package.json +10 -7
- package/src/animation/animate-mixins.ts +3 -3
- package/src/animation/demos/color-interpolation.tsx +1 -1
- package/src/button/index.ts +24 -24
- package/src/checkbox/index.ts +10 -8
- package/src/combobox/index.tsx +1 -1
- package/src/dev/refresh.ts +1 -0
- package/src/index.ts +1 -1
- package/src/input/index.ts +8 -8
- package/src/radio/index.ts +6 -5
- package/src/runtime/client-entry-boundary.ts +54 -0
- package/src/runtime/component.ts +65 -16
- package/src/runtime/core/attributes.ts +35 -1
- package/src/runtime/core/children.ts +24 -2
- package/src/runtime/core/vnode.ts +25 -4
- package/src/runtime/create-element.ts +6 -5
- package/src/runtime/demos/readme.demo.tsx +4 -4
- package/src/runtime/diff-dom.ts +358 -243
- package/src/runtime/dom.ts +331 -214
- package/src/runtime/element-function.ts +1 -0
- package/src/runtime/event-listeners.ts +1 -1
- package/src/runtime/form-navigation.ts +184 -0
- package/src/runtime/frame-resolution.ts +13 -0
- package/src/runtime/frame.ts +482 -124
- package/src/runtime/jsx.ts +3 -5
- package/src/runtime/key.ts +1 -0
- package/src/runtime/mixins/link-mixin.ts +1 -0
- package/src/runtime/mixins/mixin.ts +21 -18
- package/src/runtime/navigation.ts +204 -30
- package/src/runtime/reconcile.ts +762 -759
- package/src/runtime/refresh.ts +46 -0
- package/src/runtime/run.ts +12 -2
- package/src/runtime/scheduler.ts +9 -29
- package/src/runtime/to-vnode.ts +85 -23
- package/src/runtime/vdom.ts +89 -70
- package/src/runtime/vnode.ts +192 -88
- package/src/select/index.tsx +9 -9
- package/src/server/stream.ts +22 -28
- package/src/shared/focus-styles.ts +1 -1
- package/src/shared/style-values.ts +26 -26
- package/src/style/style.ts +25 -6
- package/src/style/stylesheet.ts +32 -57
- package/src/tabs/index.tsx +12 -11
- package/src/test/README.md +151 -60
- package/src/toggle/index.tsx +9 -7
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type ElementFunction = ((...args: never[]) => unknown) & { readonly name?: string }
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
type SourceElementNavigateEvent = NavigateEvent & {
|
|
2
|
+
sourceElement?: Element | null
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
type FormNavigateEvent = SourceElementNavigateEvent & {
|
|
6
|
+
formData?: FormData | null
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
type SubmitterElement = HTMLButtonElement | HTMLInputElement
|
|
10
|
+
|
|
11
|
+
type PendingFormSubmission = {
|
|
12
|
+
submitter: SubmitterElement | null
|
|
13
|
+
formData?: FormData
|
|
14
|
+
timeout: ReturnType<typeof setTimeout>
|
|
15
|
+
removeFormDataListener(): void
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Browser-provided data for an intercepted form submission. */
|
|
19
|
+
export interface FormSubmission {
|
|
20
|
+
/** Submitted form entries for non-GET submissions, when available. */
|
|
21
|
+
formData: FormData | undefined
|
|
22
|
+
/** Effective form method, including submitter overrides. */
|
|
23
|
+
method: string
|
|
24
|
+
/** Effective form encoding type, including submitter overrides. */
|
|
25
|
+
encType: string
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Metadata and deferred submission data for an intercepted form navigation. */
|
|
29
|
+
export interface FormNavigation {
|
|
30
|
+
/** Checks the submitter before the form for a submission attribute. */
|
|
31
|
+
hasAttribute(name: string): boolean
|
|
32
|
+
/** Reads a submission attribute, preferring the submitter-specific name when provided. */
|
|
33
|
+
getAttribute(name: string, submitterName?: string): string | null
|
|
34
|
+
/** Resolves browser-generated data for a non-GET submission. */
|
|
35
|
+
getSubmission: (() => Promise<FormSubmission>) | undefined
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const PENDING_FORM_SUBMISSION_TIMEOUT = 1000
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Tracks native form events and resolves their corresponding Navigation API events.
|
|
42
|
+
*
|
|
43
|
+
* @param signal Signal used to stop tracking form events.
|
|
44
|
+
* @returns A function that resolves form metadata for a navigation event.
|
|
45
|
+
*/
|
|
46
|
+
export function createFormNavigationResolver(
|
|
47
|
+
signal: AbortSignal,
|
|
48
|
+
): (event: NavigateEvent) => FormNavigation | undefined {
|
|
49
|
+
let pendingFormSubmissions = new WeakMap<HTMLFormElement, PendingFormSubmission>()
|
|
50
|
+
|
|
51
|
+
// Cache the authoritative submitter for the matching `navigate` event and, for Chromium's
|
|
52
|
+
// non-POST-to-POST override case, the later `formdata` event. Unmatched submits expire.
|
|
53
|
+
document.addEventListener(
|
|
54
|
+
'submit',
|
|
55
|
+
(event) => {
|
|
56
|
+
let form = event.target
|
|
57
|
+
if (!(form instanceof HTMLFormElement)) return
|
|
58
|
+
|
|
59
|
+
let existing = pendingFormSubmissions.get(form)
|
|
60
|
+
if (existing) {
|
|
61
|
+
clearTimeout(existing.timeout)
|
|
62
|
+
existing.removeFormDataListener()
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
let eventSubmitter = event instanceof SubmitEvent ? event.submitter : null
|
|
66
|
+
let submitter =
|
|
67
|
+
eventSubmitter instanceof HTMLButtonElement || eventSubmitter instanceof HTMLInputElement
|
|
68
|
+
? eventSubmitter
|
|
69
|
+
: null
|
|
70
|
+
let removeFormDataListener = () => {}
|
|
71
|
+
let method = getFormMethod(form, submitter).toLowerCase()
|
|
72
|
+
// Chromium omits formData from the `navigate` event when a submitter overrides a non-POST form
|
|
73
|
+
// to POST, so we have to capture that via the `formdata` event so we can grab it from the
|
|
74
|
+
// `navigate` event handler
|
|
75
|
+
if (method === 'post' && form.method.toLowerCase() !== 'post') {
|
|
76
|
+
let onFormData = (event: FormDataEvent) => {
|
|
77
|
+
let pending = pendingFormSubmissions.get(form)
|
|
78
|
+
if (pending) pending.formData = event.formData
|
|
79
|
+
}
|
|
80
|
+
form.addEventListener('formdata', onFormData, { signal })
|
|
81
|
+
removeFormDataListener = () => form.removeEventListener('formdata', onFormData)
|
|
82
|
+
}
|
|
83
|
+
let pending: PendingFormSubmission = {
|
|
84
|
+
submitter,
|
|
85
|
+
timeout: setTimeout(() => {
|
|
86
|
+
if (pendingFormSubmissions.get(form) === pending) {
|
|
87
|
+
pendingFormSubmissions.delete(form)
|
|
88
|
+
}
|
|
89
|
+
pending.removeFormDataListener()
|
|
90
|
+
}, PENDING_FORM_SUBMISSION_TIMEOUT),
|
|
91
|
+
removeFormDataListener,
|
|
92
|
+
}
|
|
93
|
+
pendingFormSubmissions.set(form, pending)
|
|
94
|
+
},
|
|
95
|
+
{ capture: true, signal },
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
return (event) => {
|
|
99
|
+
let sourceElement = (event as SourceElementNavigateEvent).sourceElement
|
|
100
|
+
if (!(sourceElement instanceof Element)) return
|
|
101
|
+
|
|
102
|
+
let form = getSourceForm(sourceElement)
|
|
103
|
+
if (!form) return
|
|
104
|
+
|
|
105
|
+
let pending = pendingFormSubmissions.get(form)
|
|
106
|
+
let submitter = pending?.submitter ?? null
|
|
107
|
+
let method = getFormMethod(form, submitter)
|
|
108
|
+
let encType = getFormEncType(form, submitter)
|
|
109
|
+
let target = getSubmissionAttribute(form, submitter, 'target', 'formtarget')
|
|
110
|
+
if (method === 'dialog' || target?.toLowerCase() === '_blank') return
|
|
111
|
+
|
|
112
|
+
let formEvent = event as FormNavigateEvent
|
|
113
|
+
let clearPending = () => {
|
|
114
|
+
if (!pending) return
|
|
115
|
+
clearTimeout(pending.timeout)
|
|
116
|
+
pending.removeFormDataListener()
|
|
117
|
+
if (pendingFormSubmissions.get(form) === pending) {
|
|
118
|
+
pendingFormSubmissions.delete(form)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
let getSubmission: FormNavigation['getSubmission']
|
|
122
|
+
if (method.toLowerCase() === 'get') {
|
|
123
|
+
clearPending()
|
|
124
|
+
} else {
|
|
125
|
+
getSubmission = async () => {
|
|
126
|
+
// Chromium may dispatch `formdata` after `navigate` for submitter-overridden POSTs.
|
|
127
|
+
if (!formEvent.formData && pending && !pending.formData) {
|
|
128
|
+
await new Promise<void>((resolve) => setTimeout(resolve, 0))
|
|
129
|
+
}
|
|
130
|
+
clearPending()
|
|
131
|
+
return {
|
|
132
|
+
formData: formEvent.formData ?? pending?.formData,
|
|
133
|
+
method,
|
|
134
|
+
encType,
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
hasAttribute(name) {
|
|
140
|
+
return submitter?.hasAttribute(name) === true || form.hasAttribute(name)
|
|
141
|
+
},
|
|
142
|
+
getAttribute(name, submitterName) {
|
|
143
|
+
return getSubmissionAttribute(form, submitter, name, submitterName)
|
|
144
|
+
},
|
|
145
|
+
getSubmission,
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function getSourceForm(sourceElement: Element): HTMLFormElement | undefined {
|
|
151
|
+
// A form navigation's source element is the submitted form or its submit button.
|
|
152
|
+
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-navigateevent-sourceelement
|
|
153
|
+
if (sourceElement instanceof HTMLFormElement) return sourceElement
|
|
154
|
+
if (sourceElement instanceof HTMLButtonElement || sourceElement instanceof HTMLInputElement) {
|
|
155
|
+
return sourceElement.form ?? undefined
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function getSubmissionAttribute(
|
|
160
|
+
form: HTMLFormElement,
|
|
161
|
+
submitter: SubmitterElement | null,
|
|
162
|
+
name: string,
|
|
163
|
+
submitterName?: string,
|
|
164
|
+
): string | null {
|
|
165
|
+
submitterName ??= name
|
|
166
|
+
if (submitter?.hasAttribute(submitterName)) {
|
|
167
|
+
return submitter.getAttribute(submitterName)
|
|
168
|
+
}
|
|
169
|
+
return form.getAttribute(name)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function getFormMethod(form: HTMLFormElement, submitter: SubmitterElement | null): string {
|
|
173
|
+
if (submitter?.hasAttribute('formmethod')) {
|
|
174
|
+
return submitter.formMethod
|
|
175
|
+
}
|
|
176
|
+
return form.method
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function getFormEncType(form: HTMLFormElement, submitter: SubmitterElement | null): string {
|
|
180
|
+
if (submitter?.hasAttribute('formenctype')) {
|
|
181
|
+
return submitter.formEnctype
|
|
182
|
+
}
|
|
183
|
+
return form.enctype
|
|
184
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { FrameContent, FrameResolution } from './component.ts'
|
|
2
|
+
|
|
3
|
+
export async function unwrapFrameResolution(
|
|
4
|
+
resolution: FrameResolution,
|
|
5
|
+
): Promise<{ content: FrameContent; redirectedTo?: string }> {
|
|
6
|
+
if (!(resolution instanceof Response)) return { content: resolution }
|
|
7
|
+
|
|
8
|
+
let content = resolution.body ?? (await resolution.text())
|
|
9
|
+
return {
|
|
10
|
+
content,
|
|
11
|
+
redirectedTo: resolution.redirected && resolution.url ? resolution.url : undefined,
|
|
12
|
+
}
|
|
13
|
+
}
|