quickwin 1.0.2 → 1.1.1
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.en.md +204 -204
- package/README.md +203 -203
- package/examples/PdfCanvas.tsx +83 -83
- package/examples/exec_server.ts +35 -35
- package/examples/pdf_preview2.ts +375 -375
- package/examples/pdf_viewer.tsx +279 -279
- package/examples/test_gallery.tsx +285 -285
- package/examples/test_react_lazy.tsx +63 -63
- package/examples/test_react_listbox.tsx +71 -71
- package/examples/test_root_window.tsx +41 -41
- package/examples/test_tab.tsx +75 -75
- package/examples/tray_demo.tsx +81 -81
- package/lib/assert.ts +6 -6
- package/lib/cache-utils.ts +40 -40
- package/lib/dumpRects.ts +25 -25
- package/lib/fetch.ts +502 -502
- package/lib/http-common.ts +399 -399
- package/lib/http-server.ts +424 -424
- package/lib/polyfill.ts +171 -171
- package/lib/react-qw/components/index.ts +17 -17
- package/lib/react-qw/index.ts +90 -90
- package/lib/react-qw/jsx.d.ts +34 -34
- package/lib/react-qw/layout.ts +111 -111
- package/lib/react-qw/props.ts +36 -36
- package/lib/react-qw/reconciler.ts +373 -373
- package/lib/stream.ts +21 -21
- package/lib/text-codec.ts +171 -171
- package/lib/text-measure.ts +54 -54
- package/lib/url.ts +201 -201
- package/lib/vendor/web-streams/ponyfill.d.mts +829 -829
- package/lib/vendor/web-streams/ponyfill.mjs +8 -8
- package/lib/websocket.js +8 -0
- package/lib/websocket.ts +563 -555
- package/package.json +50 -44
- package/qwin-nowasm-x86.exe +0 -0
- package/qwin-nowasm.exe +0 -0
- package/qwin-x86.exe +0 -0
- package/qwin.exe +0 -0
- package/test/run.ts +96 -96
- package/test/test_basic.ts +9 -9
- package/test/test_basic_fetch.ts +33 -33
- package/test/test_brotli.ts +52 -52
- package/test/test_fetch_cache.ts +187 -187
- package/test/test_ffi.ts +174 -174
- package/test/test_frame_encoding.ts +132 -132
- package/test/test_helper.ts +80 -80
- package/test/test_http_import.ts +74 -74
- package/test/test_http_server.ts +136 -136
- package/test/test_import_dir.ts +5 -5
- package/test/test_ipv6.ts +129 -129
- package/test/test_meta_url.ts +4 -4
- package/test/test_mupdf_render.ts +74 -74
- package/test/test_mupdf_twice.ts +81 -81
- package/test/test_mupdf_wasm.ts +30 -30
- package/test/test_net_event.ts +55 -55
- package/test/test_net_fetch.ts +238 -238
- package/test/test_net_websocket.ts +164 -164
- package/test/test_polyfill.ts +159 -159
- package/test/test_url.ts +183 -183
- package/test/test_wasm_basic.ts +73 -73
- package/test/test_wasm_import_global.ts +45 -45
- package/test/test_wasm_sjlj.ts +125 -125
- package/test/test_wasm_types.ts +124 -124
- package/test/test_worker.ts +24 -24
- package/test/test_worker_fetch.ts +27 -27
- package/test/test_worker_net.ts +54 -54
- package/test/test_worker_wasm_concurrent.ts +45 -45
- package/test/worker_fetch.ts +13 -13
- package/test/worker_helper.ts +1 -1
- package/test/worker_http.ts +20 -20
- package/test/worker_import_lib.ts +13 -13
- package/test/worker_module.ts +17 -17
- package/test/worker_wasm_concurrent.ts +22 -22
- package/tsconfig.json +27 -27
- package/vendor/mupdf-wasm/mupdf-wasm.d.ts +571 -571
- package/vendor/mupdf-wasm/mupdf-wasm.js +2749 -2749
- package/vendor/mupdf-wasm/mupdf.d.ts +939 -939
- package/vendor/mupdf-wasm/mupdf.js +3317 -3317
package/lib/react-qw/layout.ts
CHANGED
|
@@ -1,111 +1,111 @@
|
|
|
1
|
-
export type JustifyContent = 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly'
|
|
2
|
-
|
|
3
|
-
export interface FlexStyle {
|
|
4
|
-
flexDirection?: 'row' | 'column'
|
|
5
|
-
justifyContent?: JustifyContent
|
|
6
|
-
alignItems?: 'flex-start' | 'flex-end' | 'center' | 'stretch'
|
|
7
|
-
gap?: number
|
|
8
|
-
padding?: number
|
|
9
|
-
paddingTop?: number
|
|
10
|
-
paddingRight?: number
|
|
11
|
-
paddingBottom?: number
|
|
12
|
-
paddingLeft?: number
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
interface ChildStyle {
|
|
16
|
-
width?: number | 'auto'; height?: number | 'auto'
|
|
17
|
-
flexGrow?: number
|
|
18
|
-
alignSelf?: 'auto' | 'flex-start' | 'flex-end' | 'center' | 'stretch'
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
interface ChildInfo {
|
|
22
|
-
style: ChildStyle
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface LayoutResult {
|
|
26
|
-
x: number; y: number; width: number; height: number
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const DEFAULT_W = 100
|
|
30
|
-
const DEFAULT_H = 30
|
|
31
|
-
|
|
32
|
-
export function calculateFlexLayout(
|
|
33
|
-
flex: FlexStyle,
|
|
34
|
-
parentW: number,
|
|
35
|
-
parentH: number,
|
|
36
|
-
children: ChildInfo[]
|
|
37
|
-
): LayoutResult[] {
|
|
38
|
-
const dir = flex.flexDirection || 'column'
|
|
39
|
-
const gap = flex.gap ?? 0
|
|
40
|
-
const justify = flex.justifyContent || 'flex-start'
|
|
41
|
-
const align = flex.alignItems || 'stretch'
|
|
42
|
-
const isRow = dir === 'row'
|
|
43
|
-
const n = children.length
|
|
44
|
-
|
|
45
|
-
const mainSize: 'w' | 'h' = isRow ? 'w' : 'h'
|
|
46
|
-
const crossSize: 'w' | 'h' = isRow ? 'h' : 'w'
|
|
47
|
-
const mainPos: 'x' | 'y' = isRow ? 'x' : 'y'
|
|
48
|
-
const crossPos: 'x' | 'y' = isRow ? 'y' : 'x'
|
|
49
|
-
const mainDim: 'width' | 'height' = isRow ? 'width' : 'height'
|
|
50
|
-
const crossDim: 'width' | 'height' = isRow ? 'height' : 'width'
|
|
51
|
-
const pt = flex.paddingTop ?? flex.padding ?? 0
|
|
52
|
-
const pr = flex.paddingRight ?? flex.padding ?? 0
|
|
53
|
-
const pb = flex.paddingBottom ?? flex.padding ?? 0
|
|
54
|
-
const pl = flex.paddingLeft ?? flex.padding ?? 0
|
|
55
|
-
const mainPadding = isRow ? pl + pr : pt + pb
|
|
56
|
-
const crossPadding = isRow ? pt + pb : pl + pr
|
|
57
|
-
const parentMain = (isRow ? parentW : parentH) - mainPadding
|
|
58
|
-
const parentCross = (isRow ? parentH : parentW) - crossPadding
|
|
59
|
-
|
|
60
|
-
const sizes = children.map(c => ({
|
|
61
|
-
w: typeof c.style.width === 'number' ? c.style.width : DEFAULT_W,
|
|
62
|
-
h: typeof c.style.height === 'number' ? c.style.height : DEFAULT_H,
|
|
63
|
-
}))
|
|
64
|
-
|
|
65
|
-
const flexGrows = children.map(c => c.style.flexGrow ?? 0)
|
|
66
|
-
const totalGrow = flexGrows.reduce((s, g) => s + g, 0)
|
|
67
|
-
|
|
68
|
-
const baseMain = sizes.reduce((s, c) => s + c[mainSize], 0)
|
|
69
|
-
let freeGrow = parentMain - baseMain - Math.max(0, n - 1) * gap
|
|
70
|
-
if (totalGrow > 0 && freeGrow > 0) {
|
|
71
|
-
for (let i = 0; i < n; i++) {
|
|
72
|
-
sizes[i]![mainSize] += freeGrow * flexGrows[i]! / totalGrow
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const totalMain = sizes.reduce((s, c) => s + c[mainSize], 0)
|
|
77
|
-
const free = parentMain - totalMain - Math.max(0, n - 1) * gap
|
|
78
|
-
let offset = 0, extraGap = 0
|
|
79
|
-
if (justify === 'flex-end') offset = free
|
|
80
|
-
else if (justify === 'center') offset = Math.max(0, free / 2)
|
|
81
|
-
else if (justify === 'space-between' && n > 1) extraGap = free / (n - 1)
|
|
82
|
-
else if (justify === 'space-around') { extraGap = free / n; offset = extraGap / 2 }
|
|
83
|
-
else if (justify === 'space-evenly') { extraGap = free / (n + 1); offset = extraGap }
|
|
84
|
-
|
|
85
|
-
let cursor = offset
|
|
86
|
-
return sizes.map((sz, i) => {
|
|
87
|
-
const childCrossBase = sz[crossSize]
|
|
88
|
-
const childAlign = children[i]!.style.alignSelf ?? 'auto'
|
|
89
|
-
const effectiveAlign = childAlign === 'auto' ? align : childAlign
|
|
90
|
-
let childMain = sz[mainSize]
|
|
91
|
-
let childCross = childCrossBase
|
|
92
|
-
const res: LayoutResult = { x: 0, y: 0, width: 0, height: 0 }
|
|
93
|
-
res[mainPos] = cursor
|
|
94
|
-
res[crossPos] = 0
|
|
95
|
-
res[mainDim] = childMain
|
|
96
|
-
res[crossDim] = childCross
|
|
97
|
-
if (effectiveAlign === 'stretch') {
|
|
98
|
-
const hasExplicitCross = typeof children[i]!.style[crossDim] === 'number'
|
|
99
|
-
if (!hasExplicitCross) {
|
|
100
|
-
res[crossDim] = parentCross
|
|
101
|
-
res[crossPos] = 0
|
|
102
|
-
}
|
|
103
|
-
} else if (effectiveAlign === 'flex-end') {
|
|
104
|
-
res[crossPos] = parentCross - childCross
|
|
105
|
-
} else if (effectiveAlign === 'center') {
|
|
106
|
-
res[crossPos] = Math.max(0, (parentCross - childCross) / 2)
|
|
107
|
-
}
|
|
108
|
-
cursor += childMain + gap + extraGap
|
|
109
|
-
return res
|
|
110
|
-
})
|
|
111
|
-
}
|
|
1
|
+
export type JustifyContent = 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly'
|
|
2
|
+
|
|
3
|
+
export interface FlexStyle {
|
|
4
|
+
flexDirection?: 'row' | 'column'
|
|
5
|
+
justifyContent?: JustifyContent
|
|
6
|
+
alignItems?: 'flex-start' | 'flex-end' | 'center' | 'stretch'
|
|
7
|
+
gap?: number
|
|
8
|
+
padding?: number
|
|
9
|
+
paddingTop?: number
|
|
10
|
+
paddingRight?: number
|
|
11
|
+
paddingBottom?: number
|
|
12
|
+
paddingLeft?: number
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface ChildStyle {
|
|
16
|
+
width?: number | 'auto'; height?: number | 'auto'
|
|
17
|
+
flexGrow?: number
|
|
18
|
+
alignSelf?: 'auto' | 'flex-start' | 'flex-end' | 'center' | 'stretch'
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface ChildInfo {
|
|
22
|
+
style: ChildStyle
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface LayoutResult {
|
|
26
|
+
x: number; y: number; width: number; height: number
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const DEFAULT_W = 100
|
|
30
|
+
const DEFAULT_H = 30
|
|
31
|
+
|
|
32
|
+
export function calculateFlexLayout(
|
|
33
|
+
flex: FlexStyle,
|
|
34
|
+
parentW: number,
|
|
35
|
+
parentH: number,
|
|
36
|
+
children: ChildInfo[]
|
|
37
|
+
): LayoutResult[] {
|
|
38
|
+
const dir = flex.flexDirection || 'column'
|
|
39
|
+
const gap = flex.gap ?? 0
|
|
40
|
+
const justify = flex.justifyContent || 'flex-start'
|
|
41
|
+
const align = flex.alignItems || 'stretch'
|
|
42
|
+
const isRow = dir === 'row'
|
|
43
|
+
const n = children.length
|
|
44
|
+
|
|
45
|
+
const mainSize: 'w' | 'h' = isRow ? 'w' : 'h'
|
|
46
|
+
const crossSize: 'w' | 'h' = isRow ? 'h' : 'w'
|
|
47
|
+
const mainPos: 'x' | 'y' = isRow ? 'x' : 'y'
|
|
48
|
+
const crossPos: 'x' | 'y' = isRow ? 'y' : 'x'
|
|
49
|
+
const mainDim: 'width' | 'height' = isRow ? 'width' : 'height'
|
|
50
|
+
const crossDim: 'width' | 'height' = isRow ? 'height' : 'width'
|
|
51
|
+
const pt = flex.paddingTop ?? flex.padding ?? 0
|
|
52
|
+
const pr = flex.paddingRight ?? flex.padding ?? 0
|
|
53
|
+
const pb = flex.paddingBottom ?? flex.padding ?? 0
|
|
54
|
+
const pl = flex.paddingLeft ?? flex.padding ?? 0
|
|
55
|
+
const mainPadding = isRow ? pl + pr : pt + pb
|
|
56
|
+
const crossPadding = isRow ? pt + pb : pl + pr
|
|
57
|
+
const parentMain = (isRow ? parentW : parentH) - mainPadding
|
|
58
|
+
const parentCross = (isRow ? parentH : parentW) - crossPadding
|
|
59
|
+
|
|
60
|
+
const sizes = children.map(c => ({
|
|
61
|
+
w: typeof c.style.width === 'number' ? c.style.width : DEFAULT_W,
|
|
62
|
+
h: typeof c.style.height === 'number' ? c.style.height : DEFAULT_H,
|
|
63
|
+
}))
|
|
64
|
+
|
|
65
|
+
const flexGrows = children.map(c => c.style.flexGrow ?? 0)
|
|
66
|
+
const totalGrow = flexGrows.reduce((s, g) => s + g, 0)
|
|
67
|
+
|
|
68
|
+
const baseMain = sizes.reduce((s, c) => s + c[mainSize], 0)
|
|
69
|
+
let freeGrow = parentMain - baseMain - Math.max(0, n - 1) * gap
|
|
70
|
+
if (totalGrow > 0 && freeGrow > 0) {
|
|
71
|
+
for (let i = 0; i < n; i++) {
|
|
72
|
+
sizes[i]![mainSize] += freeGrow * flexGrows[i]! / totalGrow
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const totalMain = sizes.reduce((s, c) => s + c[mainSize], 0)
|
|
77
|
+
const free = parentMain - totalMain - Math.max(0, n - 1) * gap
|
|
78
|
+
let offset = 0, extraGap = 0
|
|
79
|
+
if (justify === 'flex-end') offset = free
|
|
80
|
+
else if (justify === 'center') offset = Math.max(0, free / 2)
|
|
81
|
+
else if (justify === 'space-between' && n > 1) extraGap = free / (n - 1)
|
|
82
|
+
else if (justify === 'space-around') { extraGap = free / n; offset = extraGap / 2 }
|
|
83
|
+
else if (justify === 'space-evenly') { extraGap = free / (n + 1); offset = extraGap }
|
|
84
|
+
|
|
85
|
+
let cursor = offset
|
|
86
|
+
return sizes.map((sz, i) => {
|
|
87
|
+
const childCrossBase = sz[crossSize]
|
|
88
|
+
const childAlign = children[i]!.style.alignSelf ?? 'auto'
|
|
89
|
+
const effectiveAlign = childAlign === 'auto' ? align : childAlign
|
|
90
|
+
let childMain = sz[mainSize]
|
|
91
|
+
let childCross = childCrossBase
|
|
92
|
+
const res: LayoutResult = { x: 0, y: 0, width: 0, height: 0 }
|
|
93
|
+
res[mainPos] = cursor
|
|
94
|
+
res[crossPos] = 0
|
|
95
|
+
res[mainDim] = childMain
|
|
96
|
+
res[crossDim] = childCross
|
|
97
|
+
if (effectiveAlign === 'stretch') {
|
|
98
|
+
const hasExplicitCross = typeof children[i]!.style[crossDim] === 'number'
|
|
99
|
+
if (!hasExplicitCross) {
|
|
100
|
+
res[crossDim] = parentCross
|
|
101
|
+
res[crossPos] = 0
|
|
102
|
+
}
|
|
103
|
+
} else if (effectiveAlign === 'flex-end') {
|
|
104
|
+
res[crossPos] = parentCross - childCross
|
|
105
|
+
} else if (effectiveAlign === 'center') {
|
|
106
|
+
res[crossPos] = Math.max(0, (parentCross - childCross) / 2)
|
|
107
|
+
}
|
|
108
|
+
cursor += childMain + gap + extraGap
|
|
109
|
+
return res
|
|
110
|
+
})
|
|
111
|
+
}
|
package/lib/react-qw/props.ts
CHANGED
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
import * as gui from 'gui'
|
|
2
|
-
import type { Instance, Props } from './reconciler.js'
|
|
3
|
-
|
|
4
|
-
export function applyProps(
|
|
5
|
-
instance: Instance,
|
|
6
|
-
newProps: Props,
|
|
7
|
-
_oldProps: Props,
|
|
8
|
-
) {
|
|
9
|
-
const hwnd = instance.hwnd!
|
|
10
|
-
instance.props = newProps
|
|
11
|
-
|
|
12
|
-
const textVal = 'text' in newProps ? newProps.text : (
|
|
13
|
-
typeof newProps.children === 'string' ? newProps.children :
|
|
14
|
-
typeof newProps.children === 'number' ? String(newProps.children) : undefined
|
|
15
|
-
)
|
|
16
|
-
if (textVal !== undefined) {
|
|
17
|
-
let cursor = -1
|
|
18
|
-
if (instance.type === 'EDIT') {
|
|
19
|
-
const sel = gui.SendMessage(hwnd, gui.EditMsg.GETSEL, 0, 0)
|
|
20
|
-
cursor = sel >>> 16
|
|
21
|
-
}
|
|
22
|
-
gui.SetWindowText(hwnd, textVal)
|
|
23
|
-
if (instance.type === 'EDIT' && cursor >= 0) {
|
|
24
|
-
gui.SendMessage(hwnd, gui.EditMsg.SETSEL, cursor, cursor)
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
if ('disabled' in newProps) {
|
|
28
|
-
gui.EnableWindow(hwnd, !newProps.disabled)
|
|
29
|
-
}
|
|
30
|
-
if ('hidden' in newProps) {
|
|
31
|
-
gui.ShowWindow(hwnd, newProps.hidden ? gui.ShowWindowCmd.HIDE : gui.ShowWindowCmd.SHOW)
|
|
32
|
-
}
|
|
33
|
-
if ('visible' in newProps) {
|
|
34
|
-
gui.ShowWindow(hwnd, newProps.visible ? gui.ShowWindowCmd.SHOW : gui.ShowWindowCmd.HIDE)
|
|
35
|
-
}
|
|
36
|
-
}
|
|
1
|
+
import * as gui from 'gui'
|
|
2
|
+
import type { Instance, Props } from './reconciler.js'
|
|
3
|
+
|
|
4
|
+
export function applyProps(
|
|
5
|
+
instance: Instance,
|
|
6
|
+
newProps: Props,
|
|
7
|
+
_oldProps: Props,
|
|
8
|
+
) {
|
|
9
|
+
const hwnd = instance.hwnd!
|
|
10
|
+
instance.props = newProps
|
|
11
|
+
|
|
12
|
+
const textVal = 'text' in newProps ? newProps.text : (
|
|
13
|
+
typeof newProps.children === 'string' ? newProps.children :
|
|
14
|
+
typeof newProps.children === 'number' ? String(newProps.children) : undefined
|
|
15
|
+
)
|
|
16
|
+
if (textVal !== undefined) {
|
|
17
|
+
let cursor = -1
|
|
18
|
+
if (instance.type === 'EDIT') {
|
|
19
|
+
const sel = gui.SendMessage(hwnd, gui.EditMsg.GETSEL, 0, 0)
|
|
20
|
+
cursor = sel >>> 16
|
|
21
|
+
}
|
|
22
|
+
gui.SetWindowText(hwnd, textVal)
|
|
23
|
+
if (instance.type === 'EDIT' && cursor >= 0) {
|
|
24
|
+
gui.SendMessage(hwnd, gui.EditMsg.SETSEL, cursor, cursor)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if ('disabled' in newProps) {
|
|
28
|
+
gui.EnableWindow(hwnd, !newProps.disabled)
|
|
29
|
+
}
|
|
30
|
+
if ('hidden' in newProps) {
|
|
31
|
+
gui.ShowWindow(hwnd, newProps.hidden ? gui.ShowWindowCmd.HIDE : gui.ShowWindowCmd.SHOW)
|
|
32
|
+
}
|
|
33
|
+
if ('visible' in newProps) {
|
|
34
|
+
gui.ShowWindow(hwnd, newProps.visible ? gui.ShowWindowCmd.SHOW : gui.ShowWindowCmd.HIDE)
|
|
35
|
+
}
|
|
36
|
+
}
|