@remix-run/ui 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -10
- package/dist/animation/animate-layout-mixin.js +66 -66
- package/dist/animation/animate-layout-mixin.js.map +1 -1
- package/dist/animation/spring.d.ts +6 -35
- package/dist/animation/spring.js +9 -8
- package/dist/animation/spring.js.map +1 -1
- package/dist/components/accordion/accordion.d.ts +7 -7
- package/dist/components/accordion/accordion.js +0 -2
- package/dist/components/accordion/accordion.js.map +1 -1
- package/dist/components/accordion/demos/card.demo.d.ts +6 -0
- package/dist/components/accordion/demos/card.demo.js +58 -0
- package/dist/components/accordion/demos/card.demo.js.map +1 -0
- package/dist/components/accordion/demos/multiple.demo.d.ts +6 -0
- package/dist/components/accordion/demos/multiple.demo.js +19 -0
- package/dist/components/accordion/demos/multiple.demo.js.map +1 -0
- package/dist/components/accordion/demos/overview.demo.d.ts +6 -0
- package/dist/components/accordion/demos/overview.demo.js +19 -0
- package/dist/components/accordion/demos/overview.demo.js.map +1 -0
- package/dist/components/breadcrumbs/breadcrumbs.d.ts +1 -1
- package/dist/components/breadcrumbs/breadcrumbs.js +0 -2
- package/dist/components/breadcrumbs/breadcrumbs.js.map +1 -1
- package/dist/components/breadcrumbs/demos/basic.demo.d.ts +5 -0
- package/dist/components/breadcrumbs/demos/basic.demo.js +14 -0
- package/dist/components/breadcrumbs/demos/basic.demo.js.map +1 -0
- package/dist/components/breadcrumbs/demos/separator.demo.d.ts +5 -0
- package/dist/components/breadcrumbs/demos/separator.demo.js +14 -0
- package/dist/components/breadcrumbs/demos/separator.demo.js.map +1 -0
- package/dist/components/button/button.d.ts +86 -4
- package/dist/components/button/button.js +63 -3
- package/dist/components/button/button.js.map +1 -1
- package/dist/components/button/demos/aliases.demo.d.ts +6 -0
- package/dist/components/button/demos/aliases.demo.js +18 -0
- package/dist/components/button/demos/aliases.demo.js.map +1 -0
- package/dist/components/button/demos/basic.demo.d.ts +6 -0
- package/dist/components/button/demos/basic.demo.js +19 -0
- package/dist/components/button/demos/basic.demo.js.map +1 -0
- package/dist/components/button/demos/states.demo.d.ts +6 -0
- package/dist/components/button/demos/states.demo.js +29 -0
- package/dist/components/button/demos/states.demo.js.map +1 -0
- package/dist/components/combobox/combobox.d.ts +11 -11
- package/dist/components/combobox/combobox.js +0 -2
- package/dist/components/combobox/combobox.js.map +1 -1
- package/dist/components/combobox/demos/overview.demo.d.ts +6 -0
- package/dist/components/combobox/demos/overview.demo.js +153 -0
- package/dist/components/combobox/demos/overview.demo.js.map +1 -0
- package/dist/components/listbox/demos/overview.demo.d.ts +6 -0
- package/dist/components/listbox/demos/overview.demo.js +64 -0
- package/dist/components/listbox/demos/overview.demo.js.map +1 -0
- package/dist/components/listbox/listbox.d.ts +4 -9
- package/dist/components/listbox/listbox.js +21 -33
- package/dist/components/listbox/listbox.js.map +1 -1
- package/dist/components/menu/demos/bubbling.demo.d.ts +5 -0
- package/dist/components/menu/demos/bubbling.demo.js +15 -0
- package/dist/components/menu/demos/bubbling.demo.js.map +1 -0
- package/dist/components/menu/demos/overview.demo.d.ts +6 -0
- package/dist/components/menu/demos/overview.demo.js +32 -0
- package/dist/components/menu/demos/overview.demo.js.map +1 -0
- package/dist/components/menu/menu.d.ts +15 -24
- package/dist/components/menu/menu.js +23 -38
- package/dist/components/menu/menu.js.map +1 -1
- package/dist/components/popover/demos/overview.demo.d.ts +6 -0
- package/dist/components/popover/demos/overview.demo.js +64 -0
- package/dist/components/popover/demos/overview.demo.js.map +1 -0
- package/dist/components/popover/popover.d.ts +5 -5
- package/dist/components/popover/popover.js.map +1 -1
- package/dist/components/select/demos/deconstructed.demo.d.ts +6 -0
- package/dist/components/select/demos/deconstructed.demo.js +53 -0
- package/dist/components/select/demos/deconstructed.demo.js.map +1 -0
- package/dist/components/select/demos/overview.demo.d.ts +5 -0
- package/dist/components/select/demos/overview.demo.js +27 -0
- package/dist/components/select/demos/overview.demo.js.map +1 -0
- package/dist/components/select/select.d.ts +11 -11
- package/dist/components/select/select.js +17 -26
- package/dist/components/select/select.js.map +1 -1
- package/dist/components/tabs/tabs.d.ts +6 -6
- package/dist/components/tabs/tabs.js +0 -2
- package/dist/components/tabs/tabs.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js.map +1 -1
- package/dist/interactions/keydown/keydown.d.ts +1 -1
- package/dist/interactions/outside-click/outside-click-mixin.d.ts +2 -1
- package/dist/interactions/typeahead/typeahead-mixin.d.ts +3 -1
- package/dist/runtime/component.d.ts +18 -12
- package/dist/runtime/component.js +93 -80
- package/dist/runtime/component.js.map +1 -1
- package/dist/runtime/core/attributes.d.ts +14 -0
- package/dist/runtime/core/attributes.js +103 -0
- package/dist/runtime/core/attributes.js.map +1 -0
- package/dist/runtime/core/children.d.ts +7 -0
- package/dist/runtime/core/children.js +30 -0
- package/dist/runtime/core/children.js.map +1 -0
- package/dist/runtime/core/props.d.ts +9 -0
- package/dist/runtime/core/props.js +170 -0
- package/dist/runtime/core/props.js.map +1 -0
- package/dist/runtime/core/vnode.d.ts +3 -0
- package/dist/runtime/core/vnode.js +39 -0
- package/dist/runtime/core/vnode.js.map +1 -0
- package/dist/runtime/create-element.js +2 -1
- package/dist/runtime/create-element.js.map +1 -1
- package/dist/runtime/diff-dom.js +47 -14
- package/dist/runtime/diff-dom.js.map +1 -1
- package/dist/runtime/diff-props.d.ts +1 -2
- package/dist/runtime/diff-props.js +2 -181
- package/dist/runtime/diff-props.js.map +1 -1
- package/dist/runtime/dom.d.ts +20 -9
- package/dist/runtime/frame.d.ts +23 -2
- package/dist/runtime/frame.js +41 -47
- package/dist/runtime/frame.js.map +1 -1
- package/dist/runtime/jsx.d.ts +1 -1
- package/dist/runtime/jsx.js +2 -28
- package/dist/runtime/jsx.js.map +1 -1
- package/dist/runtime/mixins/link-mixin.d.ts +5 -1
- package/dist/runtime/mixins/link-mixin.js.map +1 -1
- package/dist/runtime/mixins/mixin.d.ts +2 -1
- package/dist/runtime/mixins/mixin.js +9 -4
- package/dist/runtime/mixins/mixin.js.map +1 -1
- package/dist/runtime/mixins/on-mixin.d.ts +15 -4
- package/dist/runtime/mixins/on-mixin.js +9 -2
- package/dist/runtime/mixins/on-mixin.js.map +1 -1
- package/dist/runtime/mixins/ref-mixin.d.ts +2 -1
- package/dist/runtime/mixins/ref-mixin.js.map +1 -1
- package/dist/runtime/navigation.js +9 -1
- package/dist/runtime/navigation.js.map +1 -1
- package/dist/runtime/reconcile.d.ts +1 -1
- package/dist/runtime/reconcile.js +452 -197
- package/dist/runtime/reconcile.js.map +1 -1
- package/dist/runtime/run.d.ts +17 -2
- package/dist/runtime/run.js.map +1 -1
- package/dist/runtime/scheduler.d.ts +10 -10
- package/dist/runtime/scheduler.js +1 -1
- package/dist/runtime/scheduler.js.map +1 -1
- package/dist/runtime/stream-protocol.d.ts +8 -0
- package/dist/runtime/stream-protocol.js +20 -0
- package/dist/runtime/stream-protocol.js.map +1 -0
- package/dist/runtime/svg-attributes.js +1 -0
- package/dist/runtime/svg-attributes.js.map +1 -1
- package/dist/runtime/to-vnode.js +7 -11
- package/dist/runtime/to-vnode.js.map +1 -1
- package/dist/runtime/vnode.d.ts +11 -5
- package/dist/runtime/vnode.js +6 -3
- package/dist/runtime/vnode.js.map +1 -1
- package/dist/server/stream.d.ts +2 -0
- package/dist/server/stream.js +154 -114
- package/dist/server/stream.js.map +1 -1
- package/dist/style/css-mixin.d.ts +2 -1
- package/dist/style/css-mixin.js.map +1 -1
- package/dist/style/index.d.ts +1 -1
- package/dist/style/layers.d.ts +2 -0
- package/dist/style/layers.js +3 -0
- package/dist/style/layers.js.map +1 -0
- package/dist/style/stylesheet.d.ts +13 -11
- package/dist/style/stylesheet.js +69 -8
- package/dist/style/stylesheet.js.map +1 -1
- package/dist/theme/contract.d.ts +24 -222
- package/dist/theme/contract.js +2 -2
- package/dist/theme/contract.js.map +1 -1
- package/dist/theme/glyph-contract.d.ts +1 -3
- package/dist/theme/glyph-contract.js.map +1 -1
- package/dist/theme/presets/rmx-01/index.d.ts +4 -2
- package/dist/theme/presets/rmx-01/index.js.map +1 -1
- package/dist/theme/runtime.js +4 -1
- package/dist/theme/runtime.js.map +1 -1
- package/dist/utils/scroll-lock.d.ts +3 -3
- package/dist/utils/scroll-lock.js.map +1 -1
- package/package.json +3 -3
- package/src/animation/README.md +316 -0
- package/src/animation/animate-layout-mixin.ts +79 -71
- package/src/animation/spring.ts +21 -9
- package/src/components/accordion/README.md +166 -0
- package/src/components/accordion/accordion.tsx +14 -14
- package/src/components/accordion/demos/card.demo.tsx +113 -0
- package/src/components/accordion/demos/multiple.demo.tsx +56 -0
- package/src/components/accordion/demos/overview.demo.tsx +56 -0
- package/src/components/anchor/README.md +153 -0
- package/src/components/anchor/anchor.ts +1 -1
- package/src/components/breadcrumbs/README.md +55 -0
- package/src/components/breadcrumbs/breadcrumbs.tsx +1 -3
- package/src/components/breadcrumbs/demos/basic.demo.tsx +17 -0
- package/src/components/breadcrumbs/demos/separator.demo.tsx +18 -0
- package/src/components/button/README.md +4 -4
- package/src/components/button/button.tsx +118 -20
- package/src/components/button/demos/aliases.demo.tsx +27 -0
- package/src/components/button/demos/basic.demo.tsx +30 -0
- package/src/components/button/demos/states.demo.tsx +52 -0
- package/src/components/combobox/README.md +1 -1
- package/src/components/combobox/combobox.tsx +37 -21
- package/src/components/combobox/demos/overview.demo.tsx +199 -0
- package/src/components/glyph/README.md +72 -0
- package/src/components/glyph/glyph.tsx +2 -2
- package/src/components/listbox/README.md +115 -0
- package/src/components/listbox/demos/overview.demo.tsx +101 -0
- package/src/components/listbox/listbox.ts +106 -110
- package/src/components/menu/README.md +96 -0
- package/src/components/menu/demos/bubbling.demo.tsx +34 -0
- package/src/components/menu/demos/overview.demo.tsx +76 -0
- package/src/components/menu/menu.tsx +61 -55
- package/src/components/popover/README.md +3 -3
- package/src/components/popover/demos/overview.demo.tsx +143 -0
- package/src/components/popover/popover.ts +90 -79
- package/src/components/select/README.md +107 -0
- package/src/components/select/demos/deconstructed.demo.tsx +95 -0
- package/src/components/select/demos/overview.demo.tsx +51 -0
- package/src/components/select/select.tsx +53 -36
- package/src/components/tabs/tabs.tsx +10 -5
- package/src/index.ts +2 -1
- package/src/runtime/component.ts +122 -88
- package/src/runtime/core/attributes.ts +118 -0
- package/src/runtime/core/children.ts +42 -0
- package/src/runtime/core/props.ts +187 -0
- package/src/runtime/core/vnode.ts +48 -0
- package/src/runtime/create-element.ts +2 -1
- package/src/runtime/diff-dom.ts +59 -12
- package/src/runtime/diff-props.ts +2 -187
- package/src/runtime/dom.ts +20 -9
- package/src/runtime/frame.ts +71 -55
- package/src/runtime/jsx.ts +3 -30
- package/src/runtime/mixins/link-mixin.ts +88 -86
- package/src/runtime/mixins/mixin.ts +18 -5
- package/src/runtime/mixins/on-mixin.ts +20 -12
- package/src/runtime/mixins/ref-mixin.ts +4 -5
- package/src/runtime/navigation.ts +10 -1
- package/src/runtime/reconcile.ts +563 -223
- package/src/runtime/run.ts +17 -1
- package/src/runtime/scheduler.ts +20 -20
- package/src/runtime/stream-protocol.ts +27 -0
- package/src/runtime/svg-attributes.ts +1 -0
- package/src/runtime/to-vnode.ts +7 -10
- package/src/runtime/vnode.ts +16 -9
- package/src/server/README.md +90 -0
- package/src/server/stream.ts +176 -124
- package/src/style/css-mixin.ts +6 -1
- package/src/style/index.ts +1 -2
- package/src/style/layers.ts +2 -0
- package/src/style/stylesheet.ts +88 -11
- package/src/test/README.md +107 -0
- package/src/test/utils.ts +3 -1
- package/src/theme/README.md +103 -0
- package/src/theme/contract.ts +37 -5
- package/src/theme/glyph-contract.ts +3 -1
- package/src/theme/presets/rmx-01/index.ts +4 -2
- package/src/theme/runtime.ts +4 -1
- package/src/utils/scroll-lock/README.md +33 -0
- package/src/utils/scroll-lock.ts +7 -3
|
@@ -1,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> => ({
|
|
@@ -598,7 +606,6 @@ class MixinHandleImpl
|
|
|
598
606
|
this.#activeScope = scope
|
|
599
607
|
if (!scope) return
|
|
600
608
|
if (this.#scopeTargets.has(scope)) return
|
|
601
|
-
this.#scopeSignals.set(scope, new AbortController())
|
|
602
609
|
this.#scopeTargets.set(scope, new TypedEventTarget<MixinHandleEventMap<Element>>())
|
|
603
610
|
this.#scopePhaseCounts.set(scope, { beforeUpdate: 0, commit: 0 })
|
|
604
611
|
}
|
|
@@ -616,8 +623,11 @@ class MixinHandleImpl
|
|
|
616
623
|
this.#decrementGlobalPhaseCount('beforeUpdate', scopePhaseCounts.beforeUpdate)
|
|
617
624
|
this.#decrementGlobalPhaseCount('commit', scopePhaseCounts.commit)
|
|
618
625
|
}
|
|
619
|
-
this.#scopeSignals.get(scope)
|
|
620
|
-
|
|
626
|
+
let controller = this.#scopeSignals.get(scope)
|
|
627
|
+
if (controller) {
|
|
628
|
+
controller.abort()
|
|
629
|
+
this.#scopeSignals.delete(scope)
|
|
630
|
+
}
|
|
621
631
|
this.#scopePhaseCounts.delete(scope)
|
|
622
632
|
this.#scopeTargets.delete(scope)
|
|
623
633
|
if (this.#activeScope === scope) {
|
|
@@ -646,7 +656,10 @@ class MixinHandleImpl
|
|
|
646
656
|
|
|
647
657
|
#getScopeSignal(scope: symbol) {
|
|
648
658
|
let controller = this.#scopeSignals.get(scope)
|
|
649
|
-
|
|
659
|
+
if (!controller) {
|
|
660
|
+
controller = new AbortController()
|
|
661
|
+
this.#scopeSignals.set(scope, controller)
|
|
662
|
+
}
|
|
650
663
|
return controller.signal
|
|
651
664
|
}
|
|
652
665
|
|
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
import { createMixin } from './mixin.ts'
|
|
1
|
+
import { createMixin, type MixinType } from './mixin.ts'
|
|
2
2
|
import type { ElementProps } from '../jsx.ts'
|
|
3
3
|
import type { MixinDescriptor } from './mixin.ts'
|
|
4
|
-
import type {
|
|
5
|
-
EventType as AddEventType,
|
|
6
|
-
ListenerFor as AddEventListenerFor,
|
|
7
|
-
} from '../event-listeners.ts'
|
|
8
|
-
|
|
9
|
-
export type { Dispatched } from '../event-listeners.ts'
|
|
4
|
+
import type { EnsureEvent, EventMap } from '../event-listeners.ts'
|
|
10
5
|
|
|
11
6
|
type SignaledListener<event extends Event> = (
|
|
12
7
|
event: event,
|
|
13
8
|
signal: AbortSignal,
|
|
14
9
|
) => void | Promise<void>
|
|
15
10
|
|
|
16
|
-
type EventType<target extends Element> =
|
|
11
|
+
type EventType<target extends Element> = string & keyof EventMap<target>
|
|
12
|
+
|
|
17
13
|
type ListenerFor<target extends Element, type extends EventType<target>> = SignaledListener<
|
|
18
|
-
|
|
14
|
+
EnsureEvent<EventMap<target>[type], target>
|
|
19
15
|
>
|
|
16
|
+
export type OnMixinDescriptor = {
|
|
17
|
+
type: typeof onMixinType
|
|
18
|
+
args: [type: string, handler: SignaledListener<Event>, captureBoolean?: boolean]
|
|
19
|
+
}
|
|
20
20
|
|
|
21
|
-
const
|
|
21
|
+
const onMixinType: MixinType<
|
|
22
22
|
Element,
|
|
23
23
|
[type: string, handler: SignaledListener<Event>, captureBoolean?: boolean],
|
|
24
24
|
ElementProps
|
|
25
|
-
>(
|
|
25
|
+
> = (handle) => {
|
|
26
26
|
let currentHandler: SignaledListener<Event> = () => {}
|
|
27
27
|
let currentType = ''
|
|
28
28
|
let currentCapture = false
|
|
@@ -61,7 +61,15 @@ const onMixin = createMixin<
|
|
|
61
61
|
|
|
62
62
|
return handle.element
|
|
63
63
|
}
|
|
64
|
-
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const onMixin = createMixin(onMixinType)
|
|
67
|
+
|
|
68
|
+
export function isOnMixinDescriptor(descriptor: unknown): descriptor is OnMixinDescriptor {
|
|
69
|
+
if (!descriptor || typeof descriptor !== 'object') return false
|
|
70
|
+
let candidate = descriptor as { type?: unknown; args?: unknown }
|
|
71
|
+
return candidate.type === onMixinType && Array.isArray(candidate.args)
|
|
72
|
+
}
|
|
65
73
|
|
|
66
74
|
/**
|
|
67
75
|
* Attaches a typed DOM event handler through the mixin system.
|
|
@@ -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
|
+
})
|
|
@@ -65,7 +65,11 @@ export function startNavigationListenerImpl(
|
|
|
65
65
|
navigation.addEventListener(
|
|
66
66
|
'navigate',
|
|
67
67
|
(event) => {
|
|
68
|
-
|
|
68
|
+
// Safari seems to incorrectly set canIntercept to true for sub-domain navigations, so
|
|
69
|
+
// we do a host check ourselves/. The spec is clear that a different host should prevent
|
|
70
|
+
// interception so this is likely a bug in Safari:
|
|
71
|
+
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#can-have-its-url-rewritten
|
|
72
|
+
if (!event.canIntercept || isCrossOriginDestination(event)) return
|
|
69
73
|
|
|
70
74
|
let state = getRuntimeNavigationState(event)
|
|
71
75
|
if (!state) return
|
|
@@ -98,6 +102,11 @@ function isRuntimeNavigation(info: unknown): info is NavigationState {
|
|
|
98
102
|
return typeof info === 'object' && info != null && '$rmx' in info
|
|
99
103
|
}
|
|
100
104
|
|
|
105
|
+
function isCrossOriginDestination(event: NavigateEvent): boolean {
|
|
106
|
+
let destination = new URL(event.destination.url)
|
|
107
|
+
return destination.origin !== window.location.origin
|
|
108
|
+
}
|
|
109
|
+
|
|
101
110
|
function getRuntimeNavigationState(event: NavigateEvent): NavigationState | undefined {
|
|
102
111
|
if (event.navigationType === 'traverse') {
|
|
103
112
|
return getTraverseNavigationState(event)
|