@remix-run/ui 0.1.2 → 0.3.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 +9 -7
- package/dist/animation/demos/animation.demo.d.ts +5 -0
- package/dist/animation/demos/animation.demo.js +92 -0
- package/dist/animation/demos/animation.demo.js.map +1 -0
- package/dist/animation/demos/aspect-ratio.d.ts +2 -0
- package/dist/animation/demos/aspect-ratio.js +69 -0
- package/dist/animation/demos/aspect-ratio.js.map +1 -0
- package/dist/animation/demos/bouncy-switch.d.ts +2 -0
- package/dist/animation/demos/bouncy-switch.js +36 -0
- package/dist/animation/demos/bouncy-switch.js.map +1 -0
- package/dist/animation/demos/color-interpolation.d.ts +1 -0
- package/dist/animation/demos/color-interpolation.js +53 -0
- package/dist/animation/demos/color-interpolation.js.map +1 -0
- package/dist/animation/demos/cube.d.ts +2 -0
- package/dist/animation/demos/cube.js +86 -0
- package/dist/animation/demos/cube.js.map +1 -0
- package/dist/animation/demos/default-animate.d.ts +2 -0
- package/dist/animation/demos/default-animate.js +89 -0
- package/dist/animation/demos/default-animate.js.map +1 -0
- package/dist/animation/demos/drag-release.d.ts +24 -0
- package/dist/animation/demos/drag-release.js +96 -0
- package/dist/animation/demos/drag-release.js.map +1 -0
- package/dist/animation/demos/enter.d.ts +1 -0
- package/dist/animation/demos/enter.js +19 -0
- package/dist/animation/demos/enter.js.map +1 -0
- package/dist/animation/demos/exit.d.ts +2 -0
- package/dist/animation/demos/exit.js +58 -0
- package/dist/animation/demos/exit.js.map +1 -0
- package/dist/animation/demos/flip-toggle.d.ts +2 -0
- package/dist/animation/demos/flip-toggle.js +37 -0
- package/dist/animation/demos/flip-toggle.js.map +1 -0
- package/dist/animation/demos/hold-to-confirm.d.ts +13 -0
- package/dist/animation/demos/hold-to-confirm.js +211 -0
- package/dist/animation/demos/hold-to-confirm.js.map +1 -0
- package/dist/animation/demos/html-content.d.ts +2 -0
- package/dist/animation/demos/html-content.js +30 -0
- package/dist/animation/demos/html-content.js.map +1 -0
- package/dist/animation/demos/interruptible-keyframes.d.ts +1 -0
- package/dist/animation/demos/interruptible-keyframes.js +48 -0
- package/dist/animation/demos/interruptible-keyframes.js.map +1 -0
- package/dist/animation/demos/keyframes.d.ts +1 -0
- package/dist/animation/demos/keyframes.js +24 -0
- package/dist/animation/demos/keyframes.js.map +1 -0
- package/dist/animation/demos/material-ripple.d.ts +2 -0
- package/dist/animation/demos/material-ripple.js +127 -0
- package/dist/animation/demos/material-ripple.js.map +1 -0
- package/dist/animation/demos/mixin-presence-list.d.ts +2 -0
- package/dist/animation/demos/mixin-presence-list.js +88 -0
- package/dist/animation/demos/mixin-presence-list.js.map +1 -0
- package/dist/animation/demos/mixin-reclaim.d.ts +2 -0
- package/dist/animation/demos/mixin-reclaim.js +90 -0
- package/dist/animation/demos/mixin-reclaim.js.map +1 -0
- package/dist/animation/demos/multi-state-badge.d.ts +2 -0
- package/dist/animation/demos/multi-state-badge.js +231 -0
- package/dist/animation/demos/multi-state-badge.js.map +1 -0
- package/dist/animation/demos/press.d.ts +2 -0
- package/dist/animation/demos/press.js +63 -0
- package/dist/animation/demos/press.js.map +1 -0
- package/dist/animation/demos/reordering.d.ts +2 -0
- package/dist/animation/demos/reordering.js +50 -0
- package/dist/animation/demos/reordering.js.map +1 -0
- package/dist/animation/demos/rolling-square.d.ts +2 -0
- package/dist/animation/demos/rolling-square.js +42 -0
- package/dist/animation/demos/rolling-square.js.map +1 -0
- package/dist/animation/demos/rotate.d.ts +1 -0
- package/dist/animation/demos/rotate.js +18 -0
- package/dist/animation/demos/rotate.js.map +1 -0
- package/dist/animation/demos/shared-layout.d.ts +2 -0
- package/dist/animation/demos/shared-layout.js +114 -0
- package/dist/animation/demos/shared-layout.js.map +1 -0
- package/dist/animation/demos/spring.demo.d.ts +6 -0
- package/dist/animation/demos/spring.demo.js +304 -0
- package/dist/animation/demos/spring.demo.js.map +1 -0
- package/dist/animation/demos/transition-options.d.ts +1 -0
- package/dist/animation/demos/transition-options.js +21 -0
- package/dist/animation/demos/transition-options.js.map +1 -0
- package/dist/animation/spring.d.ts +24 -31
- package/dist/animation/spring.js +31 -8
- package/dist/animation/spring.js.map +1 -1
- package/dist/components/accordion/accordion.d.ts +6 -6
- package/dist/components/accordion/accordion.js.map +1 -1
- package/dist/components/accordion/demos/card.demo.d.ts +1 -0
- package/dist/components/accordion/demos/card.demo.js +1 -0
- package/dist/components/accordion/demos/card.demo.js.map +1 -1
- package/dist/components/accordion/demos/multiple.demo.d.ts +1 -0
- package/dist/components/accordion/demos/multiple.demo.js +1 -0
- package/dist/components/accordion/demos/multiple.demo.js.map +1 -1
- package/dist/components/accordion/demos/overview.demo.d.ts +1 -0
- package/dist/components/accordion/demos/overview.demo.js +1 -0
- package/dist/components/accordion/demos/overview.demo.js.map +1 -1
- package/dist/components/anchor/anchor.d.ts +8 -1
- package/dist/components/anchor/anchor.js +30 -11
- package/dist/components/anchor/anchor.js.map +1 -1
- package/dist/components/breadcrumbs/{demos/basic.demo.d.ts → basic.demo.d.ts} +1 -0
- package/dist/components/breadcrumbs/{demos/basic.demo.js → basic.demo.js} +1 -0
- package/dist/components/breadcrumbs/basic.demo.js.map +1 -0
- package/dist/components/breadcrumbs/breadcrumbs.d.ts +1 -1
- package/dist/components/breadcrumbs/{demos/separator.demo.d.ts → separator.demo.d.ts} +1 -0
- package/dist/components/breadcrumbs/{demos/separator.demo.js → separator.demo.js} +1 -0
- package/dist/components/breadcrumbs/separator.demo.js.map +1 -0
- package/dist/components/button/button.d.ts +4 -4
- package/dist/components/button/button.js +3 -1
- package/dist/components/button/button.js.map +1 -1
- package/dist/components/button/demos/aliases.demo.d.ts +1 -0
- package/dist/components/button/demos/aliases.demo.js +1 -0
- package/dist/components/button/demos/aliases.demo.js.map +1 -1
- package/dist/components/button/demos/basic.demo.d.ts +1 -0
- package/dist/components/button/demos/basic.demo.js +1 -0
- package/dist/components/button/demos/basic.demo.js.map +1 -1
- package/dist/components/button/demos/states.demo.d.ts +1 -0
- package/dist/components/button/demos/states.demo.js +1 -0
- package/dist/components/button/demos/states.demo.js.map +1 -1
- package/dist/components/combobox/combobox.d.ts +10 -10
- package/dist/components/combobox/combobox.js.map +1 -1
- package/dist/components/combobox/{demos/overview.demo.d.ts → overview.demo.d.ts} +1 -0
- package/dist/components/combobox/{demos/overview.demo.js → overview.demo.js} +1 -0
- package/dist/components/combobox/overview.demo.js.map +1 -0
- package/dist/components/listbox/listbox.d.ts +3 -3
- package/dist/components/listbox/listbox.js.map +1 -1
- package/dist/components/listbox/{demos/overview.demo.d.ts → overview.demo.d.ts} +1 -0
- package/dist/components/listbox/{demos/overview.demo.js → overview.demo.js} +1 -0
- package/dist/components/listbox/overview.demo.js.map +1 -0
- package/dist/components/menu/demos/bubbling.demo.d.ts +1 -0
- package/dist/components/menu/demos/bubbling.demo.js +1 -0
- package/dist/components/menu/demos/bubbling.demo.js.map +1 -1
- package/dist/components/menu/demos/context-trigger.demo.d.ts +7 -0
- package/dist/components/menu/demos/context-trigger.demo.js +87 -0
- package/dist/components/menu/demos/context-trigger.demo.js.map +1 -0
- package/dist/components/menu/demos/overview.demo.d.ts +1 -0
- package/dist/components/menu/demos/overview.demo.js +1 -0
- package/dist/components/menu/demos/overview.demo.js.map +1 -1
- package/dist/components/menu/menu.d.ts +15 -12
- package/dist/components/menu/menu.js +55 -0
- package/dist/components/menu/menu.js.map +1 -1
- package/dist/components/popover/{demos/overview.demo.d.ts → overview.demo.d.ts} +1 -0
- package/dist/components/popover/{demos/overview.demo.js → overview.demo.js} +1 -0
- package/dist/components/popover/overview.demo.js.map +1 -0
- package/dist/components/popover/popover.d.ts +7 -7
- package/dist/components/popover/popover.js +11 -4
- package/dist/components/popover/popover.js.map +1 -1
- package/dist/components/select/{demos/deconstructed.demo.d.ts → deconstructed.demo.d.ts} +1 -0
- package/dist/components/select/{demos/deconstructed.demo.js → deconstructed.demo.js} +1 -0
- package/dist/components/select/deconstructed.demo.js.map +1 -0
- package/dist/components/select/{demos/overview.demo.d.ts → overview.demo.d.ts} +1 -0
- package/dist/components/select/{demos/overview.demo.js → overview.demo.js} +1 -0
- package/dist/components/select/overview.demo.js.map +1 -0
- package/dist/components/select/select.d.ts +10 -10
- package/dist/components/select/select.js +1 -1
- package/dist/components/select/select.js.map +1 -1
- package/dist/components/tabs/tabs.d.ts +3 -3
- package/dist/index.d.ts +1 -1
- 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/client-entries.d.ts +1 -2
- package/dist/runtime/client-entries.js.map +1 -1
- package/dist/runtime/component.d.ts +20 -17
- package/dist/runtime/component.js +15 -6
- package/dist/runtime/component.js.map +1 -1
- package/dist/runtime/core/attributes.d.ts +3 -1
- package/dist/runtime/core/attributes.js +19 -1
- package/dist/runtime/core/attributes.js.map +1 -1
- package/dist/runtime/core/props.js +6 -5
- package/dist/runtime/core/props.js.map +1 -1
- package/dist/runtime/demos/basic.demo.d.ts +6 -0
- package/dist/runtime/demos/basic.demo.js +16 -0
- package/dist/runtime/demos/basic.demo.js.map +1 -0
- package/dist/runtime/demos/controlled-uncontrolled-values.demo.d.ts +6 -0
- package/dist/runtime/demos/controlled-uncontrolled-values.demo.js +77 -0
- package/dist/runtime/demos/controlled-uncontrolled-values.demo.js.map +1 -0
- package/dist/runtime/demos/keyed-list.demo.d.ts +6 -0
- package/dist/runtime/demos/keyed-list.demo.js +62 -0
- package/dist/runtime/demos/keyed-list.demo.js.map +1 -0
- package/dist/runtime/demos/readme.demo.d.ts +5 -0
- package/dist/runtime/demos/readme.demo.js +396 -0
- package/dist/runtime/demos/readme.demo.js.map +1 -0
- package/dist/runtime/diff-dom.js +194 -21
- package/dist/runtime/diff-dom.js.map +1 -1
- package/dist/runtime/dom.d.ts +16 -9
- package/dist/runtime/frame.d.ts +7 -0
- package/dist/runtime/frame.js +176 -41
- package/dist/runtime/frame.js.map +1 -1
- package/dist/runtime/jsx.d.ts +3 -4
- 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.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/reconcile.d.ts +1 -1
- package/dist/runtime/reconcile.js +19 -5
- package/dist/runtime/reconcile.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/svg-attributes.js +1 -0
- package/dist/runtime/svg-attributes.js.map +1 -1
- package/dist/runtime/to-vnode.js +2 -2
- package/dist/runtime/to-vnode.js.map +1 -1
- package/dist/runtime/vnode.d.ts +6 -1
- package/dist/runtime/vnode.js +4 -0
- package/dist/runtime/vnode.js.map +1 -1
- package/dist/server/stream.d.ts +2 -0
- package/dist/server/stream.js +82 -11
- 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/style.js +27 -10
- package/dist/style/style.js.map +1 -1
- package/dist/style/stylesheet.d.ts +13 -13
- 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/utils/scroll-lock.d.ts +3 -3
- package/dist/utils/scroll-lock.js.map +1 -1
- package/package.json +4 -4
- package/src/animation/README.md +7 -5
- package/src/animation/demos/animation.demo.tsx +194 -0
- package/src/animation/demos/aspect-ratio.tsx +120 -0
- package/src/animation/demos/bouncy-switch.tsx +47 -0
- package/src/animation/demos/color-interpolation.tsx +73 -0
- package/src/animation/demos/cube.tsx +116 -0
- package/src/animation/demos/default-animate.tsx +129 -0
- package/src/animation/demos/drag-release.ts +118 -0
- package/src/animation/demos/enter.tsx +22 -0
- package/src/animation/demos/exit.tsx +79 -0
- package/src/animation/demos/flip-toggle.tsx +46 -0
- package/src/animation/demos/hold-to-confirm.tsx +317 -0
- package/src/animation/demos/html-content.tsx +41 -0
- package/src/animation/demos/interruptible-keyframes.tsx +62 -0
- package/src/animation/demos/keyframes.tsx +29 -0
- package/src/animation/demos/material-ripple.tsx +158 -0
- package/src/animation/demos/mixin-presence-list.tsx +121 -0
- package/src/animation/demos/mixin-reclaim.tsx +125 -0
- package/src/animation/demos/multi-state-badge.tsx +426 -0
- package/src/animation/demos/press.tsx +67 -0
- package/src/animation/demos/reordering.tsx +65 -0
- package/src/animation/demos/rolling-square.tsx +57 -0
- package/src/animation/demos/rotate.tsx +21 -0
- package/src/animation/demos/shared-layout.tsx +211 -0
- package/src/animation/demos/spring.demo.tsx +385 -0
- package/src/animation/demos/transition-options.tsx +24 -0
- package/src/animation/spring.ts +43 -9
- package/src/components/accordion/accordion.tsx +7 -5
- package/src/components/accordion/demos/card.demo.tsx +1 -0
- package/src/components/accordion/demos/multiple.demo.tsx +1 -0
- package/src/components/accordion/demos/overview.demo.tsx +1 -0
- package/src/components/anchor/README.md +11 -3
- package/src/components/anchor/anchor.ts +54 -13
- package/src/components/breadcrumbs/{demos/basic.demo.tsx → basic.demo.tsx} +1 -0
- package/src/components/breadcrumbs/breadcrumbs.tsx +1 -1
- package/src/components/breadcrumbs/{demos/separator.demo.tsx → separator.demo.tsx} +1 -0
- package/src/components/button/button.tsx +30 -18
- package/src/components/button/demos/aliases.demo.tsx +1 -0
- package/src/components/button/demos/basic.demo.tsx +1 -0
- package/src/components/button/demos/states.demo.tsx +1 -0
- package/src/components/combobox/README.md +1 -1
- package/src/components/combobox/combobox.tsx +30 -12
- package/src/components/combobox/{demos/overview.demo.tsx → overview.demo.tsx} +1 -0
- package/src/components/glyph/glyph.tsx +2 -2
- package/src/components/listbox/listbox.ts +88 -83
- package/src/components/listbox/{demos/overview.demo.tsx → overview.demo.tsx} +1 -0
- package/src/components/menu/README.md +26 -2
- package/src/components/menu/demos/bubbling.demo.tsx +1 -0
- package/src/components/menu/demos/context-trigger.demo.tsx +133 -0
- package/src/components/menu/demos/overview.demo.tsx +1 -0
- package/src/components/menu/menu.tsx +100 -16
- package/src/components/popover/{demos/overview.demo.tsx → overview.demo.tsx} +1 -0
- package/src/components/popover/popover.ts +101 -81
- package/src/components/select/{demos/deconstructed.demo.tsx → deconstructed.demo.tsx} +1 -0
- package/src/components/select/{demos/overview.demo.tsx → overview.demo.tsx} +1 -0
- package/src/components/select/select.tsx +27 -10
- package/src/index.ts +1 -0
- package/src/runtime/client-entries.ts +1 -5
- package/src/runtime/component.ts +37 -15
- package/src/runtime/core/attributes.ts +21 -0
- package/src/runtime/core/props.ts +6 -4
- package/src/runtime/demos/basic.demo.tsx +21 -0
- package/src/runtime/demos/controlled-uncontrolled-values.demo.tsx +177 -0
- package/src/runtime/demos/keyed-list.demo.tsx +94 -0
- package/src/runtime/demos/readme.demo.tsx +702 -0
- package/src/runtime/diff-dom.ts +270 -20
- package/src/runtime/dom.ts +16 -9
- package/src/runtime/frame.ts +218 -41
- package/src/runtime/jsx.ts +7 -11
- package/src/runtime/mixins/link-mixin.ts +88 -86
- package/src/runtime/mixins/mixin.ts +9 -1
- package/src/runtime/mixins/ref-mixin.ts +4 -5
- package/src/runtime/reconcile.ts +23 -14
- package/src/runtime/scheduler.ts +20 -20
- package/src/runtime/svg-attributes.ts +1 -0
- package/src/runtime/to-vnode.ts +2 -2
- package/src/runtime/vnode.ts +10 -0
- package/src/server/README.md +4 -2
- package/src/server/stream.ts +84 -10
- package/src/style/css-mixin.ts +6 -1
- package/src/style/index.ts +1 -2
- package/src/style/style.ts +29 -10
- package/src/style/stylesheet.ts +14 -2
- 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/utils/scroll-lock.ts +7 -3
- package/dist/components/breadcrumbs/demos/basic.demo.js.map +0 -1
- package/dist/components/breadcrumbs/demos/separator.demo.js.map +0 -1
- package/dist/components/combobox/demos/overview.demo.js.map +0 -1
- package/dist/components/listbox/demos/overview.demo.js.map +0 -1
- package/dist/components/popover/demos/overview.demo.js.map +0 -1
- package/dist/components/select/demos/deconstructed.demo.js.map +0 -1
- package/dist/components/select/demos/overview.demo.js.map +0 -1
package/src/runtime/frame.ts
CHANGED
|
@@ -129,6 +129,7 @@ export type FrameContext = {
|
|
|
129
129
|
namedFrames: Map<string, FrameHandle>
|
|
130
130
|
regionTailRef?: ChildNode | null
|
|
131
131
|
regionParent?: ParentNode | null
|
|
132
|
+
signal?: AbortSignal
|
|
132
133
|
}
|
|
133
134
|
|
|
134
135
|
type FrameInit = {
|
|
@@ -153,6 +154,15 @@ export type Frame = {
|
|
|
153
154
|
render: (content: InternalFrameContent, options?: RenderOptions) => Promise<void>
|
|
154
155
|
ready: () => Promise<void>
|
|
155
156
|
flush: () => void
|
|
157
|
+
clearPendingTemplateWatch: () => void
|
|
158
|
+
isDisplayingResolvedContent: () => boolean
|
|
159
|
+
startInheritedReload: (signal?: AbortSignal) => void
|
|
160
|
+
updateMarker: (marker: FrameMarkerData, options?: RenderOptions) => Promise<void>
|
|
161
|
+
renderMarkerContent: (
|
|
162
|
+
marker: FrameMarkerData,
|
|
163
|
+
content: InternalFrameContent,
|
|
164
|
+
options?: RenderOptions,
|
|
165
|
+
) => Promise<void>
|
|
156
166
|
dispose: () => void
|
|
157
167
|
handle: FrameHandle
|
|
158
168
|
}
|
|
@@ -161,15 +171,21 @@ type RenderOptions = {
|
|
|
161
171
|
flushKind?: FlushKind
|
|
162
172
|
initialHydrationTracker?: InitialHydrationTracker
|
|
163
173
|
signal?: AbortSignal
|
|
174
|
+
contentStatus?: 'pending' | 'resolved'
|
|
164
175
|
}
|
|
165
176
|
|
|
166
177
|
export function createFrame(root: FrameRoot, init: FrameInit): Frame {
|
|
167
178
|
let container = createContainer(root)
|
|
168
|
-
let observers: MutationObserver[] = []
|
|
169
|
-
let subscriptions: Array<() => void> = []
|
|
170
179
|
let contentRoot: VirtualRoot | undefined
|
|
171
180
|
let reloadController: AbortController | undefined
|
|
172
181
|
let styleManager = init.styleManager ?? createStyleManager()
|
|
182
|
+
let currentMarker = init.marker
|
|
183
|
+
let displayedContentStatus: 'pending' | 'resolved' = init.marker?.status ?? 'resolved'
|
|
184
|
+
let pendingTemplateMarkerId: string | undefined
|
|
185
|
+
let pendingTemplateObserver: MutationObserver | undefined
|
|
186
|
+
let pendingTemplateUnsubscribe: (() => void) | undefined
|
|
187
|
+
let inheritedReloadPending = false
|
|
188
|
+
let inheritedReloadAbortUnsubscribe: (() => void) | undefined
|
|
173
189
|
|
|
174
190
|
// Merge any rmx-data found in the current document once at startup.
|
|
175
191
|
mergeRmxDataFromDocument(init.data, container.doc)
|
|
@@ -184,6 +200,7 @@ export function createFrame(root: FrameRoot, init: FrameInit): Frame {
|
|
|
184
200
|
let controller = new AbortController()
|
|
185
201
|
reloadController = controller
|
|
186
202
|
frame.dispatchEvent(new Event('reloadStart'))
|
|
203
|
+
startSubFrameInheritedReloads(getContentNodes(), controller.signal)
|
|
187
204
|
try {
|
|
188
205
|
let content = await init.resolveFrame(frame.src, controller.signal, frameName)
|
|
189
206
|
if (reloadController !== controller || controller.signal.aborted) return controller.signal
|
|
@@ -250,6 +267,7 @@ export function createFrame(root: FrameRoot, init: FrameInit): Frame {
|
|
|
250
267
|
|
|
251
268
|
if (options?.signal?.aborted) return
|
|
252
269
|
contentRoot.render(content)
|
|
270
|
+
displayedContentStatus = options?.contentStatus ?? 'resolved'
|
|
253
271
|
return
|
|
254
272
|
}
|
|
255
273
|
|
|
@@ -290,17 +308,20 @@ export function createFrame(root: FrameRoot, init: FrameInit): Frame {
|
|
|
290
308
|
...context,
|
|
291
309
|
regionParent: container.doc.documentElement,
|
|
292
310
|
regionTailRef: null,
|
|
311
|
+
signal: options?.signal,
|
|
293
312
|
})
|
|
294
313
|
diffNodes([container.doc.body], [parsed.body], {
|
|
295
314
|
...context,
|
|
296
315
|
regionParent: container.doc.documentElement,
|
|
297
316
|
regionTailRef: null,
|
|
317
|
+
signal: options?.signal,
|
|
298
318
|
})
|
|
299
319
|
|
|
300
320
|
let bodyContainer = createElementContainer(container.doc.body)
|
|
301
321
|
if (options?.signal?.aborted) return
|
|
302
322
|
scheduleHydrationInContainer(bodyContainer, context, options?.initialHydrationTracker)
|
|
303
|
-
createSubFrames(bodyContainer.childNodes, context)
|
|
323
|
+
await createSubFrames(bodyContainer.childNodes, context, options)
|
|
324
|
+
displayedContentStatus = options?.contentStatus ?? 'resolved'
|
|
304
325
|
return
|
|
305
326
|
}
|
|
306
327
|
|
|
@@ -320,11 +341,13 @@ export function createFrame(root: FrameRoot, init: FrameInit): Frame {
|
|
|
320
341
|
...context,
|
|
321
342
|
regionTailRef: container.regionTailRef,
|
|
322
343
|
regionParent: container.regionParent,
|
|
344
|
+
signal: options?.signal,
|
|
323
345
|
})
|
|
324
346
|
|
|
325
347
|
if (options?.signal?.aborted) return
|
|
326
348
|
scheduleHydrationInContainer(container, context, options?.initialHydrationTracker)
|
|
327
|
-
createSubFrames(container.childNodes, context)
|
|
349
|
+
await createSubFrames(container.childNodes, context, options)
|
|
350
|
+
displayedContentStatus = options?.contentStatus ?? 'resolved'
|
|
328
351
|
}
|
|
329
352
|
|
|
330
353
|
function createFrameContentRoot(): VirtualRoot {
|
|
@@ -368,30 +391,11 @@ export function createFrame(root: FrameRoot, init: FrameInit): Frame {
|
|
|
368
391
|
let initialHydrationTracker = createInitialHydrationTracker()
|
|
369
392
|
|
|
370
393
|
context.styleManager.replaceServerStyles(collectFrameServerStyleTags(container))
|
|
371
|
-
createSubFrames(container.childNodes, context)
|
|
394
|
+
await createSubFrames(container.childNodes, context)
|
|
372
395
|
scheduleHydrationInContainer(container, context, initialHydrationTracker)
|
|
373
396
|
|
|
374
|
-
if (
|
|
375
|
-
|
|
376
|
-
let early = consumeFrameTemplate(markerId) ?? getEarlyFrameContent(markerId)
|
|
377
|
-
if (early) {
|
|
378
|
-
await render(early, { initialHydrationTracker })
|
|
379
|
-
} else {
|
|
380
|
-
let observer = setupTemplateObserver()
|
|
381
|
-
let unsubscribe = subscribeFrameTemplate(markerId, async (fragment) => {
|
|
382
|
-
unsubscribe()
|
|
383
|
-
await render(fragment)
|
|
384
|
-
observer.disconnect()
|
|
385
|
-
})
|
|
386
|
-
subscriptions.push(unsubscribe)
|
|
387
|
-
let buffered = consumeFrameTemplate(markerId)
|
|
388
|
-
if (buffered) {
|
|
389
|
-
unsubscribe()
|
|
390
|
-
await render(buffered)
|
|
391
|
-
observer.disconnect()
|
|
392
|
-
}
|
|
393
|
-
observers.push(observer)
|
|
394
|
-
}
|
|
397
|
+
if (currentMarker?.status === 'pending') {
|
|
398
|
+
await watchPendingFrameTemplate(currentMarker, initialHydrationTracker)
|
|
395
399
|
}
|
|
396
400
|
|
|
397
401
|
initialHydrationTracker.finalize()
|
|
@@ -403,16 +407,7 @@ export function createFrame(root: FrameRoot, init: FrameInit): Frame {
|
|
|
403
407
|
reloadController = undefined
|
|
404
408
|
contentRoot?.dispose()
|
|
405
409
|
contentRoot = undefined
|
|
406
|
-
|
|
407
|
-
// Disconnect any MutationObservers waiting for templates.
|
|
408
|
-
for (let observer of observers) {
|
|
409
|
-
observer.disconnect()
|
|
410
|
-
}
|
|
411
|
-
observers.length = 0
|
|
412
|
-
for (let unsubscribe of subscriptions) {
|
|
413
|
-
unsubscribe()
|
|
414
|
-
}
|
|
415
|
-
subscriptions.length = 0
|
|
410
|
+
clearPendingFrameTemplateWatch()
|
|
416
411
|
|
|
417
412
|
// Remove hydrated virtual roots in this frame's region.
|
|
418
413
|
removeVirtualRoots(container.childNodes)
|
|
@@ -434,9 +429,173 @@ export function createFrame(root: FrameRoot, init: FrameInit): Frame {
|
|
|
434
429
|
render,
|
|
435
430
|
ready: () => readyPromise,
|
|
436
431
|
flush: () => context.scheduler.dequeue(),
|
|
432
|
+
clearPendingTemplateWatch: clearPendingFrameTemplateWatch,
|
|
433
|
+
isDisplayingResolvedContent: () => displayedContentStatus === 'resolved',
|
|
434
|
+
startInheritedReload,
|
|
435
|
+
updateMarker,
|
|
436
|
+
renderMarkerContent,
|
|
437
437
|
dispose,
|
|
438
438
|
handle: frame,
|
|
439
439
|
}
|
|
440
|
+
|
|
441
|
+
async function updateMarker(marker: FrameMarkerData, options?: RenderOptions): Promise<void> {
|
|
442
|
+
if (options?.signal?.aborted) return
|
|
443
|
+
let previousMarker = currentMarker
|
|
444
|
+
let isInheritedReload = previousMarker !== undefined && previousMarker.id !== marker.id
|
|
445
|
+
currentMarker = marker
|
|
446
|
+
|
|
447
|
+
if (isInheritedReload) {
|
|
448
|
+
startInheritedReload(options?.signal)
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
if (marker.status === 'pending') {
|
|
452
|
+
await watchPendingFrameTemplate(
|
|
453
|
+
marker,
|
|
454
|
+
options?.initialHydrationTracker,
|
|
455
|
+
options?.signal,
|
|
456
|
+
isInheritedReload
|
|
457
|
+
? () => {
|
|
458
|
+
completeInheritedReload()
|
|
459
|
+
}
|
|
460
|
+
: undefined,
|
|
461
|
+
)
|
|
462
|
+
} else {
|
|
463
|
+
clearPendingFrameTemplateWatch()
|
|
464
|
+
if (isInheritedReload && !options?.signal?.aborted) {
|
|
465
|
+
completeInheritedReload()
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
async function renderMarkerContent(
|
|
471
|
+
marker: FrameMarkerData,
|
|
472
|
+
content: InternalFrameContent,
|
|
473
|
+
options?: RenderOptions,
|
|
474
|
+
): Promise<void> {
|
|
475
|
+
if (options?.signal?.aborted) return
|
|
476
|
+
let previousMarker = currentMarker
|
|
477
|
+
let isInheritedReload = previousMarker !== undefined && previousMarker.id !== marker.id
|
|
478
|
+
currentMarker = marker
|
|
479
|
+
|
|
480
|
+
if (isInheritedReload) {
|
|
481
|
+
startInheritedReload(options?.signal)
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
clearPendingFrameTemplateWatch()
|
|
485
|
+
await render(content, { ...options, contentStatus: 'resolved' })
|
|
486
|
+
|
|
487
|
+
if (isInheritedReload && !options?.signal?.aborted) {
|
|
488
|
+
completeInheritedReload()
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
function startInheritedReload(signal?: AbortSignal): void {
|
|
493
|
+
if (signal?.aborted) return
|
|
494
|
+
if (!inheritedReloadPending) {
|
|
495
|
+
inheritedReloadPending = true
|
|
496
|
+
frame.dispatchEvent(new Event('reloadStart'))
|
|
497
|
+
startSubFrameInheritedReloads(getContentNodes(), signal)
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
inheritedReloadAbortUnsubscribe?.()
|
|
501
|
+
inheritedReloadAbortUnsubscribe = undefined
|
|
502
|
+
if (signal) {
|
|
503
|
+
let abort = () => completeInheritedReload()
|
|
504
|
+
signal.addEventListener('abort', abort, { once: true })
|
|
505
|
+
inheritedReloadAbortUnsubscribe = () => {
|
|
506
|
+
signal.removeEventListener('abort', abort)
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
function completeInheritedReload(): void {
|
|
512
|
+
if (!inheritedReloadPending) return
|
|
513
|
+
inheritedReloadPending = false
|
|
514
|
+
inheritedReloadAbortUnsubscribe?.()
|
|
515
|
+
inheritedReloadAbortUnsubscribe = undefined
|
|
516
|
+
frame.dispatchEvent(new Event('reloadComplete'))
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
function startSubFrameInheritedReloads(nodes: Node[], signal?: AbortSignal): void {
|
|
520
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
521
|
+
if (signal?.aborted) break
|
|
522
|
+
|
|
523
|
+
let node = nodes[i]
|
|
524
|
+
|
|
525
|
+
if (isFrameStart(node)) {
|
|
526
|
+
let end = findEndMarker(node, isFrameStart, isFrameEnd)
|
|
527
|
+
context.frameInstances.get(node)?.startInheritedReload(signal)
|
|
528
|
+
i = nodes.indexOf(end)
|
|
529
|
+
continue
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
if (node.childNodes && node.childNodes.length > 0) {
|
|
533
|
+
startSubFrameInheritedReloads(Array.from(node.childNodes), signal)
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
function clearPendingFrameTemplateWatch(): void {
|
|
539
|
+
pendingTemplateUnsubscribe?.()
|
|
540
|
+
pendingTemplateUnsubscribe = undefined
|
|
541
|
+
pendingTemplateObserver?.disconnect()
|
|
542
|
+
pendingTemplateObserver = undefined
|
|
543
|
+
pendingTemplateMarkerId = undefined
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
async function watchPendingFrameTemplate(
|
|
547
|
+
marker: FrameMarkerData,
|
|
548
|
+
initialHydrationTracker?: InitialHydrationTracker,
|
|
549
|
+
signal?: AbortSignal,
|
|
550
|
+
onResolved?: () => void,
|
|
551
|
+
): Promise<void> {
|
|
552
|
+
if (signal?.aborted) return
|
|
553
|
+
if (pendingTemplateMarkerId === marker.id) return
|
|
554
|
+
|
|
555
|
+
clearPendingFrameTemplateWatch()
|
|
556
|
+
pendingTemplateMarkerId = marker.id
|
|
557
|
+
|
|
558
|
+
let early = consumeFrameTemplate(marker.id) ?? getEarlyFrameContent(marker.id)
|
|
559
|
+
if (early) {
|
|
560
|
+
clearPendingFrameTemplateWatch()
|
|
561
|
+
await render(early, { initialHydrationTracker, signal, contentStatus: 'resolved' })
|
|
562
|
+
if (!signal?.aborted) onResolved?.()
|
|
563
|
+
return
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
if (signal?.aborted) {
|
|
567
|
+
clearPendingFrameTemplateWatch()
|
|
568
|
+
return
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
let observer = setupTemplateObserver()
|
|
572
|
+
pendingTemplateObserver = observer
|
|
573
|
+
let unsubscribe = subscribeFrameTemplate(marker.id, async (fragment) => {
|
|
574
|
+
if (signal?.aborted) return
|
|
575
|
+
if (pendingTemplateMarkerId !== marker.id) return
|
|
576
|
+
clearPendingFrameTemplateWatch()
|
|
577
|
+
await render(fragment, { signal, contentStatus: 'resolved' })
|
|
578
|
+
if (!signal?.aborted) onResolved?.()
|
|
579
|
+
})
|
|
580
|
+
pendingTemplateUnsubscribe = unsubscribe
|
|
581
|
+
|
|
582
|
+
signal?.addEventListener(
|
|
583
|
+
'abort',
|
|
584
|
+
() => {
|
|
585
|
+
if (pendingTemplateMarkerId === marker.id) {
|
|
586
|
+
clearPendingFrameTemplateWatch()
|
|
587
|
+
}
|
|
588
|
+
},
|
|
589
|
+
{ once: true },
|
|
590
|
+
)
|
|
591
|
+
|
|
592
|
+
let buffered = consumeFrameTemplate(marker.id)
|
|
593
|
+
if (buffered) {
|
|
594
|
+
clearPendingFrameTemplateWatch()
|
|
595
|
+
await render(buffered, { initialHydrationTracker, signal, contentStatus: 'resolved' })
|
|
596
|
+
if (!signal?.aborted) onResolved?.()
|
|
597
|
+
}
|
|
598
|
+
}
|
|
440
599
|
}
|
|
441
600
|
|
|
442
601
|
export function createFrameRuntime(init: {
|
|
@@ -752,16 +911,32 @@ function hydrateRegion(
|
|
|
752
911
|
root.render(vElement)
|
|
753
912
|
}
|
|
754
913
|
|
|
755
|
-
function createSubFrames(
|
|
914
|
+
async function createSubFrames(
|
|
915
|
+
nodes: Node[],
|
|
916
|
+
context: FrameContext,
|
|
917
|
+
options?: RenderOptions,
|
|
918
|
+
): Promise<void> {
|
|
919
|
+
let tasks: Promise<void>[] = []
|
|
920
|
+
|
|
756
921
|
for (let i = 0; i < nodes.length; i++) {
|
|
922
|
+
if (options?.signal?.aborted) break
|
|
923
|
+
|
|
757
924
|
let node = nodes[i]
|
|
758
925
|
|
|
759
926
|
if (isFrameStart(node)) {
|
|
760
927
|
let end = findEndMarker(node, isFrameStart, isFrameEnd)
|
|
928
|
+
let existingFrame = context.frameInstances.get(node)
|
|
929
|
+
let id = getFrameId(node)
|
|
930
|
+
let marker = context.data.f?.[id]
|
|
761
931
|
|
|
762
|
-
if (
|
|
763
|
-
|
|
764
|
-
|
|
932
|
+
if (existingFrame) {
|
|
933
|
+
if (marker) {
|
|
934
|
+
let frameMarker: FrameMarkerData = { ...marker, id }
|
|
935
|
+
tasks.push(existingFrame.updateMarker(frameMarker, options))
|
|
936
|
+
} else {
|
|
937
|
+
existingFrame.clearPendingTemplateWatch()
|
|
938
|
+
}
|
|
939
|
+
} else {
|
|
765
940
|
if (marker) {
|
|
766
941
|
let frameMarker: FrameMarkerData = { ...marker, id }
|
|
767
942
|
let subFrame = createFrame([node, end], {
|
|
@@ -788,9 +963,11 @@ function createSubFrames(nodes: Node[], context: FrameContext) {
|
|
|
788
963
|
}
|
|
789
964
|
|
|
790
965
|
if (node.childNodes && node.childNodes.length > 0) {
|
|
791
|
-
createSubFrames(Array.from(node.childNodes), context)
|
|
966
|
+
tasks.push(createSubFrames(Array.from(node.childNodes), context, options))
|
|
792
967
|
}
|
|
793
968
|
}
|
|
969
|
+
|
|
970
|
+
await Promise.all(tasks)
|
|
794
971
|
}
|
|
795
972
|
|
|
796
973
|
function isHydrationMarkerLive(marker: HydrationMarker, context: FrameContext): boolean {
|
package/src/runtime/jsx.ts
CHANGED
|
@@ -44,7 +44,7 @@ export type Renderable = RemixElement | string | number | bigint | boolean | nul
|
|
|
44
44
|
* Particularly useful for `props.children`.
|
|
45
45
|
*
|
|
46
46
|
* ```tsx
|
|
47
|
-
* function MyComponent(
|
|
47
|
+
* function MyComponent(handle: Handle<{ children: RemixNode }>) {}
|
|
48
48
|
* ```
|
|
49
49
|
*/
|
|
50
50
|
export type RemixNode = Renderable | RemixNode[]
|
|
@@ -77,10 +77,6 @@ type MixinElementType = ((
|
|
|
77
77
|
__rmxMixinElementType: string
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
type MergeComponentProps<handleProps, renderProps> = [handleProps] extends [Record<string, never>]
|
|
81
|
-
? renderProps
|
|
82
|
-
: handleProps & renderProps
|
|
83
|
-
|
|
84
80
|
/**
|
|
85
81
|
* Get the props for a specific element type.
|
|
86
82
|
*
|
|
@@ -120,7 +116,7 @@ declare global {
|
|
|
120
116
|
// host elements
|
|
121
117
|
| keyof IntrinsicElements
|
|
122
118
|
// Factory component
|
|
123
|
-
| ((handle: Handle<any, any>) => RenderFn
|
|
119
|
+
| ((handle: Handle<any, any>) => RenderFn)
|
|
124
120
|
// Mixin element used internally by mixin render callbacks
|
|
125
121
|
| MixinElementType
|
|
126
122
|
|
|
@@ -134,11 +130,11 @@ declare global {
|
|
|
134
130
|
|
|
135
131
|
type LibraryManagedAttributes<component, props> = component extends MixinElementType
|
|
136
132
|
? ExpandMixProp<Parameters<ReturnType<component>>[0]>
|
|
137
|
-
: component extends (
|
|
138
|
-
?
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
133
|
+
: component extends () => RenderFn
|
|
134
|
+
? ExpandMixProp<Record<string, never>>
|
|
135
|
+
: component extends (handle: Handle<infer P, any>) => RenderFn
|
|
136
|
+
? // It's a ComponentFactory - infer props from the handle
|
|
137
|
+
ExpandMixProp<P>
|
|
142
138
|
: // Otherwise use props as-is (simple function component)
|
|
143
139
|
ExpandMixProp<props>
|
|
144
140
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createMixin, renderMixinElement } from './mixin.ts'
|
|
1
|
+
import { createMixin, renderMixinElement, type MixinFactory } from './mixin.ts'
|
|
2
2
|
import { navigate } from '../navigation.ts'
|
|
3
3
|
import { on } from './on-mixin.ts'
|
|
4
4
|
import type { ElementProps } from '../jsx.ts'
|
|
@@ -21,108 +21,110 @@ const nativeLinkHostTypes = new Set(['a', 'area'])
|
|
|
21
21
|
/**
|
|
22
22
|
* Adds client-side navigation behavior to anchor-like elements.
|
|
23
23
|
*/
|
|
24
|
-
export const link
|
|
24
|
+
export const link: MixinFactory<
|
|
25
25
|
HTMLElement,
|
|
26
26
|
[href: string, options?: NavigationOptions],
|
|
27
27
|
LinkCurrentProps
|
|
28
|
-
>
|
|
29
|
-
|
|
28
|
+
> = createMixin<HTMLElement, [href: string, options?: NavigationOptions], LinkCurrentProps>(
|
|
29
|
+
(handle, hostType) => {
|
|
30
|
+
let suppressKeyboardClick = false
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
let nextProps = { ...props }
|
|
43
|
-
if (nextProps.role == null) {
|
|
44
|
-
nextProps.role = 'link'
|
|
45
|
-
}
|
|
46
|
-
if (nextProps.disabled === true && nextProps['aria-disabled'] == null) {
|
|
47
|
-
nextProps['aria-disabled'] = 'true'
|
|
48
|
-
}
|
|
49
|
-
if (hostType === 'button' && nextProps.type == null) {
|
|
50
|
-
nextProps.type = 'button'
|
|
51
|
-
}
|
|
52
|
-
if (
|
|
53
|
-
hostType !== 'button' &&
|
|
54
|
-
nextProps.tabIndex == null &&
|
|
55
|
-
nextProps.tabindex == null &&
|
|
56
|
-
nextProps.contentEditable == null &&
|
|
57
|
-
nextProps.contenteditable == null
|
|
58
|
-
) {
|
|
59
|
-
nextProps.tabIndex = 0
|
|
60
|
-
}
|
|
32
|
+
return (href, options, props: LinkCurrentProps) => {
|
|
33
|
+
if (nativeLinkHostTypes.has(hostType)) {
|
|
34
|
+
return renderMixinElement(handle.element, {
|
|
35
|
+
...(props ?? {}),
|
|
36
|
+
href,
|
|
37
|
+
...(options?.target == null ? {} : { 'rmx-target': options.target }),
|
|
38
|
+
...(options?.src == null ? {} : { 'rmx-src': options.src }),
|
|
39
|
+
...(options?.resetScroll === false ? { 'rmx-reset-scroll': 'false' } : {}),
|
|
40
|
+
})
|
|
41
|
+
}
|
|
61
42
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
43
|
+
let nextProps = { ...props }
|
|
44
|
+
if (nextProps.role == null) {
|
|
45
|
+
nextProps.role = 'link'
|
|
46
|
+
}
|
|
47
|
+
if (nextProps.disabled === true && nextProps['aria-disabled'] == null) {
|
|
48
|
+
nextProps['aria-disabled'] = 'true'
|
|
49
|
+
}
|
|
50
|
+
if (hostType === 'button' && nextProps.type == null) {
|
|
51
|
+
nextProps.type = 'button'
|
|
52
|
+
}
|
|
53
|
+
if (
|
|
54
|
+
hostType !== 'button' &&
|
|
55
|
+
nextProps.tabIndex == null &&
|
|
56
|
+
nextProps.tabindex == null &&
|
|
57
|
+
nextProps.contentEditable == null &&
|
|
58
|
+
nextProps.contenteditable == null
|
|
59
|
+
) {
|
|
60
|
+
nextProps.tabIndex = 0
|
|
61
|
+
}
|
|
71
62
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
63
|
+
return renderMixinElement(handle.element, {
|
|
64
|
+
...nextProps,
|
|
65
|
+
mix: [
|
|
66
|
+
on('click', (event) => {
|
|
67
|
+
if (event.detail === 0 && suppressKeyboardClick) {
|
|
68
|
+
suppressKeyboardClick = false
|
|
69
|
+
event.preventDefault()
|
|
70
|
+
return
|
|
71
|
+
}
|
|
78
72
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
73
|
+
suppressKeyboardClick = false
|
|
74
|
+
if (isDisabledElement(event.currentTarget)) {
|
|
75
|
+
event.preventDefault()
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
if (event.button !== 0) return
|
|
84
79
|
|
|
85
|
-
void navigate(href, options)
|
|
86
|
-
}),
|
|
87
|
-
on('auxclick', (event) => {
|
|
88
|
-
suppressKeyboardClick = false
|
|
89
|
-
if (isDisabledElement(event.currentTarget)) {
|
|
90
80
|
event.preventDefault()
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
81
|
+
if (event.metaKey || event.ctrlKey) {
|
|
82
|
+
globalThis.open(href, '_blank')
|
|
83
|
+
return
|
|
84
|
+
}
|
|
94
85
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if (event.key === 'Enter') {
|
|
100
|
-
if (event.repeat) return
|
|
86
|
+
void navigate(href, options)
|
|
87
|
+
}),
|
|
88
|
+
on('auxclick', (event) => {
|
|
89
|
+
suppressKeyboardClick = false
|
|
101
90
|
if (isDisabledElement(event.currentTarget)) {
|
|
102
91
|
event.preventDefault()
|
|
103
92
|
return
|
|
104
93
|
}
|
|
94
|
+
if (event.button !== 1) return
|
|
105
95
|
|
|
106
|
-
suppressKeyboardClick = hostType === 'button'
|
|
107
96
|
event.preventDefault()
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
97
|
+
globalThis.open(href, '_blank')
|
|
98
|
+
}),
|
|
99
|
+
on('keydown', (event) => {
|
|
100
|
+
if (event.key === 'Enter') {
|
|
101
|
+
if (event.repeat) return
|
|
102
|
+
if (isDisabledElement(event.currentTarget)) {
|
|
103
|
+
event.preventDefault()
|
|
104
|
+
return
|
|
105
|
+
}
|
|
111
106
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
107
|
+
suppressKeyboardClick = hostType === 'button'
|
|
108
|
+
event.preventDefault()
|
|
109
|
+
void navigate(href, options)
|
|
110
|
+
return
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (hostType === 'button' && event.key === ' ') {
|
|
114
|
+
suppressKeyboardClick = true
|
|
115
|
+
event.preventDefault()
|
|
116
|
+
}
|
|
117
|
+
}),
|
|
118
|
+
on('keyup', (event) => {
|
|
119
|
+
if (hostType === 'button' && event.key === ' ') {
|
|
120
|
+
event.preventDefault()
|
|
121
|
+
}
|
|
122
|
+
}),
|
|
123
|
+
],
|
|
124
|
+
})
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
)
|
|
126
128
|
|
|
127
129
|
function isDisabledElement(node: Element) {
|
|
128
130
|
return (
|
|
@@ -130,6 +130,14 @@ export type MixinDescriptor<
|
|
|
130
130
|
readonly __node?: (node: node) => void
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
+
export type MixinFactory<
|
|
134
|
+
node extends EventTarget = Element,
|
|
135
|
+
args extends unknown[] = [],
|
|
136
|
+
props extends ElementProps = ElementProps,
|
|
137
|
+
> = <boundNode extends node = node>(
|
|
138
|
+
...args: RebindTuple<args, node, boundNode>
|
|
139
|
+
) => MixinDescriptor<boundNode, RebindTuple<args, node, boundNode>, props>
|
|
140
|
+
|
|
133
141
|
type PreviousMixDepth = [0, 0, 1, 2, 3, 4]
|
|
134
142
|
type FalsyMixValue = false | 0 | 0n | '' | null | undefined
|
|
135
143
|
type NullableMixValue<descriptor> = descriptor | FalsyMixValue
|
|
@@ -244,7 +252,7 @@ export function createMixin<
|
|
|
244
252
|
node extends EventTarget = Element,
|
|
245
253
|
args extends unknown[] = [],
|
|
246
254
|
props extends ElementProps = ElementProps,
|
|
247
|
-
>(type: MixinType<node, args, props>) {
|
|
255
|
+
>(type: MixinType<node, args, props>): MixinFactory<node, args, props> {
|
|
248
256
|
return <boundNode extends node = node>(
|
|
249
257
|
...args: RebindTuple<args, node, boundNode>
|
|
250
258
|
): MixinDescriptor<boundNode, RebindTuple<args, node, boundNode>, props> => ({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createMixin } from './mixin.ts'
|
|
1
|
+
import { createMixin, type MixinFactory } from './mixin.ts'
|
|
2
2
|
import type { ElementProps } from '../jsx.ts'
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -9,8 +9,8 @@ export type RefCallback<node extends EventTarget> = (node: node, signal: AbortSi
|
|
|
9
9
|
/**
|
|
10
10
|
* Calls a callback when an element is inserted and aborts it when removed.
|
|
11
11
|
*/
|
|
12
|
-
export const ref
|
|
13
|
-
(handle) => {
|
|
12
|
+
export const ref: MixinFactory<Element, [callback: RefCallback<Element>], ElementProps> =
|
|
13
|
+
createMixin<Element, [callback: RefCallback<Element>], ElementProps>((handle) => {
|
|
14
14
|
let controller: AbortController | undefined
|
|
15
15
|
|
|
16
16
|
handle.addEventListener('insert', (event) => {
|
|
@@ -28,5 +28,4 @@ export const ref = createMixin<Element, [callback: RefCallback<Element>], Elemen
|
|
|
28
28
|
callback = nextCallback
|
|
29
29
|
return handle.element
|
|
30
30
|
}
|
|
31
|
-
}
|
|
32
|
-
)
|
|
31
|
+
})
|