Skip to content

Commit 27add9e

Browse files
committed
feat: introduce @vue-jsx-vapor/runtime
1 parent dc64b7f commit 27add9e

File tree

19 files changed

+1055
-659
lines changed

19 files changed

+1055
-659
lines changed

.gitignore

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,5 +82,3 @@ dist
8282

8383
# vitepress
8484
cache
85-
86-
jsx-runtime

packages/runtime/package.json

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"name": "@vue-jsx-vapor/runtime",
3+
"version": "2.5.4-beta.1",
4+
"description": "Vue JSX Vapor Runtime",
5+
"type": "module",
6+
"keywords": [
7+
"vue",
8+
"jsx",
9+
"vapor",
10+
"runtime"
11+
],
12+
"license": "MIT",
13+
"homepage": "https://github.com/vuejs/vue-jsx-vapor#readme",
14+
"bugs": {
15+
"url": "https://github.com/vuejs/vue-jsx-vapor/issues"
16+
},
17+
"repository": {
18+
"type": "git",
19+
"url": "git+https://github.com/vuejs/vue-jsx-vapor.git"
20+
},
21+
"files": [
22+
"dist"
23+
],
24+
"main": "dist/index.cjs",
25+
"module": "dist/index.js",
26+
"types": "dist/index.d.ts",
27+
"exports": {
28+
".": {
29+
"types": "./dist/index.d.ts",
30+
"jsx-vapor-dev": "./src/index.ts",
31+
"require": "./dist/index.cjs",
32+
"import": "./dist/index.js"
33+
},
34+
"./*": "./*"
35+
},
36+
"scripts": {
37+
"build": "tsdown",
38+
"dev": "DEV=true tsdown",
39+
"release": "bumpp && npm publish",
40+
"test": "vitest"
41+
},
42+
"peerDependencies": {
43+
"vue": "^3.6.0-alpha.2"
44+
},
45+
"devDependencies": {
46+
"csstype": "^3.1.3"
47+
}
48+
}

packages/runtime/src/block.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { createTextNode, isFragment, isVaporComponent, type Block } from 'vue'
2+
3+
type NodeChildAtom = Block | string | number | boolean | null | undefined | void
4+
5+
export type NodeArrayChildren = Array<NodeArrayChildren | NodeChildAtom>
6+
7+
export type NodeChild = NodeChildAtom | NodeArrayChildren
8+
9+
export function normalizeNode(node: NodeChild): Block {
10+
if (node == null || typeof node === 'boolean') {
11+
return document.createComment('')
12+
} else if (Array.isArray(node) && node.length) {
13+
return node.map(normalizeNode)
14+
} else if (isBlock(node)) {
15+
return node
16+
} else {
17+
// strings and numbers
18+
return createTextNode(String(node))
19+
}
20+
}
21+
22+
export function isBlock(val: NonNullable<unknown>): val is Block {
23+
return (
24+
val instanceof Node ||
25+
Array.isArray(val) ||
26+
isVaporComponent(val) ||
27+
isFragment(val)
28+
)
29+
}

packages/runtime/src/component.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import {
2+
createComponent as _createComponent,
3+
createComponentWithFallback as _createComponentWithFallback,
4+
Fragment,
5+
type VaporComponent,
6+
} from 'vue'
7+
import { normalizeNode } from './block'
8+
import { getCurrentInstance } from './helpers'
9+
10+
type Tail<T extends any[]> = T extends [any, ...infer R] ? R : never
11+
12+
export const createComponent = (
13+
type: VaporComponent | typeof Fragment,
14+
...args: Tail<Parameters<typeof _createComponent>>
15+
) => {
16+
return createProxyComponent(_createComponent, type, ...args)
17+
}
18+
19+
export const createComponentWithFallback = (
20+
type: VaporComponent | typeof Fragment,
21+
...args: Tail<Parameters<typeof _createComponentWithFallback>>
22+
) => createProxyComponent(_createComponentWithFallback, type, ...args)
23+
24+
const createProxyComponent = (
25+
createComponent:
26+
| typeof _createComponent
27+
| typeof _createComponentWithFallback,
28+
type: VaporComponent | typeof Fragment,
29+
props: any,
30+
...args: any[]
31+
) => {
32+
if (type === Fragment) {
33+
type = (_, { slots }) => slots.default()
34+
props = null
35+
}
36+
37+
const i = getCurrentInstance()
38+
if (typeof type === 'function') {
39+
type = new Proxy(type, {
40+
apply(target, ctx, args) {
41+
return normalizeNode(Reflect.apply(target, ctx, args))
42+
},
43+
get(target, p, receiver) {
44+
if ((i && (i.appContext as any)).vapor && p === '__vapor') {
45+
return true
46+
}
47+
return Reflect.get(target, p, receiver)
48+
},
49+
})
50+
} else if (type.__vapor && type.setup) {
51+
type.setup = new Proxy(type.setup, {
52+
apply(target, ctx, args) {
53+
return normalizeNode(Reflect.apply(target, ctx, args))
54+
},
55+
})
56+
}
57+
58+
return createComponent(type as VaporComponent, props, ...args)
59+
}

packages/vue-jsx-vapor/src/core/h.ts renamed to packages/runtime/src/h.ts

Lines changed: 31 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,22 @@
11
/* eslint-disable prefer-rest-params */
2-
import {
3-
createTextNode,
4-
type Block,
5-
type Component,
6-
type ComponentOptions,
7-
type ConcreteComponent,
8-
type DefineComponent,
9-
type EmitsOptions,
10-
type Fragment,
11-
type FunctionalComponent,
12-
type RawSlots,
13-
type Suspense,
14-
type SuspenseProps,
15-
type Teleport,
16-
type TeleportProps,
17-
type VNodeRef,
2+
import { isBlock, type NodeArrayChildren, type NodeChild } from './block'
3+
import { createComponentWithFallback } from './component'
4+
import type {
5+
Block,
6+
Component,
7+
ComponentOptions,
8+
ConcreteComponent,
9+
DefineComponent,
10+
EmitsOptions,
11+
Fragment,
12+
FunctionalComponent,
13+
RawSlots,
14+
Suspense,
15+
SuspenseProps,
16+
Teleport,
17+
TeleportProps,
18+
VNodeRef,
1819
} from 'vue'
19-
import { createComponentWithFallback, isBlock } from './runtime'
20-
21-
type NodeChildAtom = Block | string | number | boolean | null | undefined | void
22-
23-
type NodeArrayChildren = Array<NodeArrayChildren | NodeChildAtom>
24-
25-
type RawChildren = NodeChildAtom | NodeArrayChildren
26-
27-
function normalizeNode(node: RawChildren): Block {
28-
if (node == null || typeof node === 'boolean') {
29-
return []
30-
} else if (Array.isArray(node) && node.length) {
31-
return node.map(normalizeNode)
32-
} else if (isBlock(node)) {
33-
return node
34-
} else {
35-
// strings and numbers
36-
return createTextNode(String(node))
37-
}
38-
}
3920

4021
// fake constructor type returned from `defineComponent`
4122
interface Constructor<P = any> {
@@ -63,20 +44,20 @@ type ResolveProps<T> = T extends null | undefined ? T : () => T | T
6344
// element
6445
export function h<K extends keyof HTMLElementTagNameMap>(
6546
type: K,
66-
children?: RawChildren,
47+
children?: NodeChild,
6748
): Block
6849
export function h<K extends keyof HTMLElementTagNameMap>(
6950
type: K,
7051
props?: ResolveProps<RawProps & HTMLElementEventHandler> | null,
71-
children?: RawChildren | RawSlots,
52+
children?: NodeChild | RawSlots,
7253
): Block
7354

7455
// custom element
75-
export function h(type: string, children?: RawChildren): Block
56+
export function h(type: string, children?: NodeChild): Block
7657
export function h(
7758
type: string,
7859
props?: ResolveProps<RawProps> | null,
79-
children?: RawChildren | RawSlots,
60+
children?: NodeChild | RawSlots,
8061
): Block
8162

8263
// text/comment
@@ -102,27 +83,27 @@ export function h(
10283
export function h(
10384
type: typeof Teleport,
10485
props: RawProps & TeleportProps,
105-
children: RawChildren | RawSlots,
86+
children: NodeChild | RawSlots,
10687
): Block
10788

10889
// suspense
109-
export function h(type: typeof Suspense, children?: RawChildren): Block
90+
export function h(type: typeof Suspense, children?: NodeChild): Block
11091
export function h(
11192
type: typeof Suspense,
11293
props?: ResolveProps<RawProps & SuspenseProps> | null,
113-
children?: RawChildren | RawSlots,
94+
children?: NodeChild | RawSlots,
11495
): Block
11596

11697
// functional component
117-
export function h(type: FunctionalComponent, children?: RawChildren): Block
98+
export function h(type: FunctionalComponent, children?: NodeChild): Block
11899
export function h<
119100
P,
120101
E extends EmitsOptions = {},
121102
S extends Record<string, any> = any,
122103
>(
123104
type: FunctionalComponent<P, E, S>,
124105
props?: ResolveProps<(RawProps & P) | ({} extends P ? null : never)>,
125-
children?: RawChildren | IfAny<S, RawSlots, S>,
106+
children?: NodeChild | IfAny<S, RawSlots, S>,
126107
): Block
127108

128109
// catch all types
@@ -134,7 +115,7 @@ export function h(
134115
| ComponentOptions
135116
| Constructor
136117
| DefineComponent,
137-
children?: RawChildren,
118+
children?: NodeChild,
138119
): Block
139120
export function h<P>(
140121
type:
@@ -145,7 +126,7 @@ export function h<P>(
145126
| Constructor<P>
146127
| DefineComponent<P>,
147128
props?: ResolveProps<(RawProps & P) | ({} extends P ? null : never)>,
148-
children?: RawChildren | RawSlots,
129+
children?: NodeChild | RawSlots,
149130
): Block
150131

151132
export function h(type: any, propsOrChildren?: any, children?: any) {
@@ -159,7 +140,7 @@ export function h(type: any, propsOrChildren?: any, children?: any) {
159140
// single block without props
160141
if (isBlock(propsOrChildren)) {
161142
return createComponentWithFallback(type, null, {
162-
default: () => normalizeNode(propsOrChildren),
143+
default: () => propsOrChildren,
163144
})
164145
}
165146

@@ -168,7 +149,7 @@ export function h(type: any, propsOrChildren?: any, children?: any) {
168149
} else {
169150
// omit props
170151
return createComponentWithFallback(type, null, {
171-
default: () => normalizeNode(propsOrChildren),
152+
default: () => propsOrChildren,
172153
})
173154
}
174155
} else {
@@ -182,7 +163,7 @@ export function h(type: any, propsOrChildren?: any, children?: any) {
182163
? typeof children === 'object' && !Array.isArray(children)
183164
? children
184165
: {
185-
default: () => normalizeNode(children),
166+
default: () => children,
186167
}
187168
: undefined,
188169
)

packages/runtime/src/helpers.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { proxyRefs, toRefs, useAttrs, type GenericComponentInstance } from 'vue'
2+
import * as Vue from 'vue'
3+
4+
export function getCurrentInstance(): GenericComponentInstance | null {
5+
// @ts-ignore
6+
return Vue.currentInstance || Vue.getCurrentInstance()
7+
}
8+
9+
/**
10+
* Returns the props of the current component instance.
11+
*
12+
* @example
13+
* ```tsx
14+
* import { useProps } from 'vue-jsx-vapor'
15+
*
16+
* defineComponent(({ foo = '' })=>{
17+
* const props = useProps() // { foo: '' }
18+
* })
19+
* ```
20+
*/
21+
export function useProps() {
22+
const i = getCurrentInstance()
23+
return i!.props
24+
}
25+
26+
/**
27+
* Returns the merged props and attrs of the current component.\
28+
* Equivalent to `useProps()` + `useAttrs()`.
29+
*
30+
* @example
31+
* ```tsx
32+
* import { useFullProps } from 'vue-jsx-vapor'
33+
*
34+
* defineComponent((props) => {
35+
* const fullProps = useFullProps() // = useAttrs() + useProps()
36+
* })
37+
*/
38+
export function useFullProps() {
39+
return proxyRefs({
40+
...toRefs(useProps()),
41+
...toRefs(useAttrs()),
42+
})
43+
}

packages/runtime/src/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export { shallowRef as useRef } from 'vue'
2+
export * from './jsx'
3+
export * from './h'
4+
export * from './node'
5+
export * from './block'
6+
export * from './component'
7+
export * from './helpers'

packages/vue-jsx-vapor/src/jsx-runtime/dom.ts renamed to packages/runtime/src/jsx.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ export interface CSSProperties
4646
type Booleanish = boolean | 'true' | 'false'
4747
type Numberish = number | string
4848

49+
interface HTMLWebViewElement extends HTMLElement {}
50+
4951
// All the WAI-ARIA 1.1 attributes from https://www.w3.org/TR/wai-aria-1.1/
5052
export interface AriaAttributes {
5153
/** Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application. */
@@ -1656,4 +1658,3 @@ export interface TransitionEvent<T = Element>
16561658
export type TransitionEventHandler<T = Element> = EventHandler<
16571659
TransitionEvent<T>
16581660
>
1659-

0 commit comments

Comments
 (0)