@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.
Files changed (189) hide show
  1. package/README.md +74 -1
  2. package/dist/accordion/index.js +2 -2
  3. package/dist/accordion/primitives.d.ts +1 -1
  4. package/dist/accordion/primitives.js.map +1 -1
  5. package/dist/anchor/index.js.map +1 -1
  6. package/dist/animation/animate-layout-mixin.js +1 -1
  7. package/dist/animation/animate-layout-mixin.js.map +1 -1
  8. package/dist/animation/animate-mixins.js +2 -2
  9. package/dist/animation/animate-mixins.js.map +1 -1
  10. package/dist/animation/demos/color-interpolation.js +1 -1
  11. package/dist/animation/demos/color-interpolation.js.map +1 -1
  12. package/dist/animation/demos/drag-release.d.ts +1 -1
  13. package/dist/animation/demos/hold-to-confirm.d.ts +3 -3
  14. package/dist/animation/demos/material-ripple.js +1 -3
  15. package/dist/animation/demos/material-ripple.js.map +1 -1
  16. package/dist/animation/index.js +4 -4
  17. package/dist/animation/spring.js.map +1 -1
  18. package/dist/breadcrumbs/index.js +2 -2
  19. package/dist/button/index.js +25 -25
  20. package/dist/button/index.js.map +1 -1
  21. package/dist/checkbox/index.js +11 -9
  22. package/dist/checkbox/index.js.map +1 -1
  23. package/dist/combobox/index.js +4 -4
  24. package/dist/combobox/index.js.map +1 -1
  25. package/dist/combobox/primitives.d.ts +1 -1
  26. package/dist/combobox/primitives.js +5 -5
  27. package/dist/combobox/primitives.js.map +1 -1
  28. package/dist/dev/refresh.d.ts +1 -0
  29. package/dist/dev/refresh.js +2 -0
  30. package/dist/dev/refresh.js.map +1 -0
  31. package/dist/index.d.ts +1 -1
  32. package/dist/index.js +14 -14
  33. package/dist/input/index.js +9 -9
  34. package/dist/input/index.js.map +1 -1
  35. package/dist/jsx-runtime.js +2 -2
  36. package/dist/listbox/index.js +2 -2
  37. package/dist/menu/hover-aim.js.map +1 -1
  38. package/dist/menu/index.js +3 -3
  39. package/dist/menu/primitives.d.ts +1 -1
  40. package/dist/menu/primitives.js +6 -6
  41. package/dist/menu/primitives.js.map +1 -1
  42. package/dist/popover/index.js +3 -3
  43. package/dist/popover/scroll-lock.js.map +1 -1
  44. package/dist/radio/index.js +7 -7
  45. package/dist/radio/index.js.map +1 -1
  46. package/dist/runtime/client-entry-boundary.d.ts +14 -0
  47. package/dist/runtime/client-entry-boundary.js +29 -0
  48. package/dist/runtime/client-entry-boundary.js.map +1 -0
  49. package/dist/runtime/component.d.ts +19 -4
  50. package/dist/runtime/component.js +39 -9
  51. package/dist/runtime/component.js.map +1 -1
  52. package/dist/runtime/core/attributes.js +36 -3
  53. package/dist/runtime/core/attributes.js.map +1 -1
  54. package/dist/runtime/core/children.d.ts +2 -0
  55. package/dist/runtime/core/children.js +26 -2
  56. package/dist/runtime/core/children.js.map +1 -1
  57. package/dist/runtime/core/props.js +2 -2
  58. package/dist/runtime/core/vnode.d.ts +3 -3
  59. package/dist/runtime/core/vnode.js +22 -1
  60. package/dist/runtime/core/vnode.js.map +1 -1
  61. package/dist/runtime/create-element.d.ts +2 -2
  62. package/dist/runtime/create-element.js +3 -2
  63. package/dist/runtime/create-element.js.map +1 -1
  64. package/dist/runtime/diff-dom.js +294 -219
  65. package/dist/runtime/diff-dom.js.map +1 -1
  66. package/dist/runtime/diff-props.js +3 -3
  67. package/dist/runtime/dom.d.ts +12 -0
  68. package/dist/runtime/element-function.d.ts +3 -0
  69. package/dist/runtime/element-function.js +2 -0
  70. package/dist/runtime/element-function.js.map +1 -0
  71. package/dist/runtime/form-navigation.d.ts +25 -0
  72. package/dist/runtime/form-navigation.js +132 -0
  73. package/dist/runtime/form-navigation.js.map +1 -0
  74. package/dist/runtime/frame-resolution.d.ts +5 -0
  75. package/dist/runtime/frame-resolution.js +10 -0
  76. package/dist/runtime/frame-resolution.js.map +1 -0
  77. package/dist/runtime/frame.d.ts +58 -15
  78. package/dist/runtime/frame.js +367 -114
  79. package/dist/runtime/frame.js.map +1 -1
  80. package/dist/runtime/jsx.d.ts +1 -1
  81. package/dist/runtime/jsx.js +1 -1
  82. package/dist/runtime/jsx.js.map +1 -1
  83. package/dist/runtime/key.d.ts +1 -0
  84. package/dist/runtime/key.js +2 -0
  85. package/dist/runtime/key.js.map +1 -0
  86. package/dist/runtime/mixins/attrs-mixin.js +2 -2
  87. package/dist/runtime/mixins/link-mixin.js +4 -3
  88. package/dist/runtime/mixins/link-mixin.js.map +1 -1
  89. package/dist/runtime/mixins/mixin.d.ts +15 -10
  90. package/dist/runtime/mixins/mixin.js +4 -4
  91. package/dist/runtime/mixins/mixin.js.map +1 -1
  92. package/dist/runtime/mixins/on-mixin.js +1 -1
  93. package/dist/runtime/mixins/ref-mixin.js +1 -1
  94. package/dist/runtime/navigation.d.ts +4 -1
  95. package/dist/runtime/navigation.js +157 -32
  96. package/dist/runtime/navigation.js.map +1 -1
  97. package/dist/runtime/reconcile.d.ts +11 -10
  98. package/dist/runtime/reconcile.js +549 -421
  99. package/dist/runtime/reconcile.js.map +1 -1
  100. package/dist/runtime/refresh.d.ts +28 -0
  101. package/dist/runtime/refresh.js +31 -0
  102. package/dist/runtime/refresh.js.map +1 -0
  103. package/dist/runtime/render.js +1 -1
  104. package/dist/runtime/render.js.map +1 -1
  105. package/dist/runtime/run.d.ts +3 -1
  106. package/dist/runtime/run.js +15 -7
  107. package/dist/runtime/run.js.map +1 -1
  108. package/dist/runtime/scheduler.js +8 -16
  109. package/dist/runtime/scheduler.js.map +1 -1
  110. package/dist/runtime/to-vnode.d.ts +2 -2
  111. package/dist/runtime/to-vnode.js +68 -20
  112. package/dist/runtime/to-vnode.js.map +1 -1
  113. package/dist/runtime/vdom.d.ts +4 -2
  114. package/dist/runtime/vdom.js +87 -42
  115. package/dist/runtime/vdom.js.map +1 -1
  116. package/dist/runtime/vnode.d.ts +138 -67
  117. package/dist/runtime/vnode.js +17 -12
  118. package/dist/runtime/vnode.js.map +1 -1
  119. package/dist/select/index.js +11 -11
  120. package/dist/select/index.js.map +1 -1
  121. package/dist/select/primitives.d.ts +1 -1
  122. package/dist/select/primitives.js +6 -6
  123. package/dist/server/stream.js +20 -27
  124. package/dist/server/stream.js.map +1 -1
  125. package/dist/shared/focus-styles.d.ts +1 -1
  126. package/dist/shared/focus-styles.js +1 -1
  127. package/dist/shared/focus-styles.js.map +1 -1
  128. package/dist/shared/listbox-popover-styles.js +1 -1
  129. package/dist/shared/style-values.js +26 -26
  130. package/dist/shared/style-values.js.map +1 -1
  131. package/dist/style/css-mixin.js +3 -3
  132. package/dist/style/index.js +2 -2
  133. package/dist/style/style.js +25 -6
  134. package/dist/style/style.js.map +1 -1
  135. package/dist/style/stylesheet.d.ts +0 -1
  136. package/dist/style/stylesheet.js +13 -54
  137. package/dist/style/stylesheet.js.map +1 -1
  138. package/dist/tabs/index.js +11 -11
  139. package/dist/tabs/index.js.map +1 -1
  140. package/dist/tabs/primitives.d.ts +1 -1
  141. package/dist/test.js +1 -1
  142. package/dist/toggle/index.js +9 -9
  143. package/dist/toggle/index.js.map +1 -1
  144. package/dist/toggle/primitives.d.ts +1 -1
  145. package/package.json +10 -7
  146. package/src/animation/animate-mixins.ts +3 -3
  147. package/src/animation/demos/color-interpolation.tsx +1 -1
  148. package/src/button/index.ts +24 -24
  149. package/src/checkbox/index.ts +10 -8
  150. package/src/combobox/index.tsx +1 -1
  151. package/src/dev/refresh.ts +1 -0
  152. package/src/index.ts +1 -1
  153. package/src/input/index.ts +8 -8
  154. package/src/radio/index.ts +6 -5
  155. package/src/runtime/client-entry-boundary.ts +54 -0
  156. package/src/runtime/component.ts +65 -16
  157. package/src/runtime/core/attributes.ts +35 -1
  158. package/src/runtime/core/children.ts +24 -2
  159. package/src/runtime/core/vnode.ts +25 -4
  160. package/src/runtime/create-element.ts +6 -5
  161. package/src/runtime/demos/readme.demo.tsx +4 -4
  162. package/src/runtime/diff-dom.ts +358 -243
  163. package/src/runtime/dom.ts +331 -214
  164. package/src/runtime/element-function.ts +1 -0
  165. package/src/runtime/event-listeners.ts +1 -1
  166. package/src/runtime/form-navigation.ts +184 -0
  167. package/src/runtime/frame-resolution.ts +13 -0
  168. package/src/runtime/frame.ts +482 -124
  169. package/src/runtime/jsx.ts +3 -5
  170. package/src/runtime/key.ts +1 -0
  171. package/src/runtime/mixins/link-mixin.ts +1 -0
  172. package/src/runtime/mixins/mixin.ts +21 -18
  173. package/src/runtime/navigation.ts +204 -30
  174. package/src/runtime/reconcile.ts +762 -759
  175. package/src/runtime/refresh.ts +46 -0
  176. package/src/runtime/run.ts +12 -2
  177. package/src/runtime/scheduler.ts +9 -29
  178. package/src/runtime/to-vnode.ts +85 -23
  179. package/src/runtime/vdom.ts +89 -70
  180. package/src/runtime/vnode.ts +192 -88
  181. package/src/select/index.tsx +9 -9
  182. package/src/server/stream.ts +22 -28
  183. package/src/shared/focus-styles.ts +1 -1
  184. package/src/shared/style-values.ts +26 -26
  185. package/src/style/style.ts +25 -6
  186. package/src/style/stylesheet.ts +32 -57
  187. package/src/tabs/index.tsx +12 -11
  188. package/src/test/README.md +151 -60
  189. package/src/toggle/index.tsx +9 -7
@@ -0,0 +1 @@
1
+ export type ElementFunction = ((...args: never[]) => unknown) & { readonly name?: string }
@@ -47,7 +47,7 @@ export type EventListeners<target extends EventTarget> = Partial<{
47
47
  [k in EventType<target>]: ListenerFor<target, k>
48
48
  }>
49
49
 
50
- // prettier-ignore
50
+ // oxfmt-ignore
51
51
  /**
52
52
  * Event map resolved for the given DOM or custom event target.
53
53
  */
@@ -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
+ }