quickwin 2.3.1 → 3.0.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.
Files changed (172) hide show
  1. package/README.en.md +1 -2
  2. package/README.md +1 -2
  3. package/constants.ts +15 -0
  4. package/enum_map.d.ts +3 -0
  5. package/examples/PdfCanvas.js +1 -1
  6. package/examples/PdfCanvas.tsx +2 -2
  7. package/examples/execd/main.js +334 -188
  8. package/examples/pdf_preview2.js +76 -67
  9. package/examples/pdf_preview2.ts +84 -64
  10. package/examples/pdf_viewer.js +4932 -1029
  11. package/examples/pdf_viewer.tsx +11 -22
  12. package/examples/test_gallery.js +308 -143
  13. package/examples/test_gallery.tsx +12 -7
  14. package/examples/test_react_lazy.js +295 -133
  15. package/examples/test_react_lazy.tsx +4 -3
  16. package/examples/test_react_listbox.js +293 -132
  17. package/examples/test_react_listbox.tsx +3 -2
  18. package/examples/test_root_window.js +283 -126
  19. package/examples/test_tab.js +295 -133
  20. package/examples/test_tab.tsx +4 -3
  21. package/examples/tray_demo.js +37 -30
  22. package/examples/tray_demo.tsx +39 -32
  23. package/lib/abort.d.ts +21 -0
  24. package/lib/assert.d.ts +2 -0
  25. package/lib/bitmap.d.ts +7 -0
  26. package/lib/bitmap.js +40 -0
  27. package/lib/cache-utils.d.ts +6 -0
  28. package/lib/certs.d.ts +1 -0
  29. package/lib/certs.js +31 -3
  30. package/lib/dpi.d.ts +9 -0
  31. package/lib/dpi.js +30 -0
  32. package/lib/dumpRects.d.ts +2 -0
  33. package/lib/dumpRects.js +14 -7
  34. package/lib/exec-log.d.ts +23 -0
  35. package/lib/fetch.d.ts +4 -0
  36. package/lib/ffi/bind.d.ts +70 -0
  37. package/lib/ffi/bind.js +5 -4
  38. package/lib/ffi/ctype.d.ts +117 -0
  39. package/lib/ffi/index.d.ts +2 -0
  40. package/lib/ffi/struct.d.ts +174 -0
  41. package/lib/http-common.d.ts +143 -0
  42. package/lib/http-server.d.ts +59 -0
  43. package/lib/polyfill.d.ts +22 -0
  44. package/lib/react-qw/components/Button.d.ts +9 -0
  45. package/lib/react-qw/components/CheckBox.d.ts +11 -0
  46. package/lib/react-qw/components/ComboBox.d.ts +11 -0
  47. package/lib/react-qw/components/DateTimePicker.d.ts +15 -0
  48. package/lib/react-qw/components/DateTimePicker.js +6 -7
  49. package/lib/react-qw/components/Input.d.ts +15 -0
  50. package/lib/react-qw/components/Input.js +5 -1
  51. package/lib/react-qw/components/Link.d.ts +12 -0
  52. package/lib/react-qw/components/ListBox.d.ts +13 -0
  53. package/lib/react-qw/components/ListView.d.ts +37 -0
  54. package/lib/react-qw/components/ListView.js +8 -6
  55. package/lib/react-qw/components/PathPicker.d.ts +23 -0
  56. package/lib/react-qw/components/ProgressBar.d.ts +9 -0
  57. package/lib/react-qw/components/RadioButton.d.ts +11 -0
  58. package/lib/react-qw/components/ScrollView.d.ts +9 -0
  59. package/lib/react-qw/components/ScrollView.js +28 -22
  60. package/lib/react-qw/components/Slider.d.ts +12 -0
  61. package/lib/react-qw/components/Tab.d.ts +14 -0
  62. package/lib/react-qw/components/Tooltip.d.ts +7 -0
  63. package/lib/react-qw/components/TreeView.d.ts +18 -0
  64. package/lib/react-qw/components/index.d.ts +16 -0
  65. package/lib/react-qw/index.d.ts +24 -0
  66. package/lib/react-qw/index.js +7 -5
  67. package/lib/react-qw/layout.d.ts +29 -0
  68. package/lib/react-qw/nmhdr.d.ts +1 -0
  69. package/lib/react-qw/props.d.ts +2 -0
  70. package/lib/react-qw/props.js +3 -3
  71. package/lib/react-qw/reconciler.d.ts +21 -0
  72. package/lib/react-qw/reconciler.js +12 -17
  73. package/lib/stream.d.ts +20 -0
  74. package/lib/text-codec.d.ts +39 -0
  75. package/lib/text-measure.d.ts +14 -0
  76. package/lib/text-measure.js +9 -6
  77. package/lib/url.d.ts +54 -0
  78. package/lib/websocket.d.ts +73 -0
  79. package/lib/windows/{advapi32.ts → advapi32.d.ts} +6 -21
  80. package/lib/windows/comctl32.d.ts +14 -0
  81. package/lib/windows/comctl32.js +3 -2
  82. package/lib/windows/comdlg32.d.ts +4 -0
  83. package/lib/windows/{gdi32.ts → gdi32.d.ts} +184 -97
  84. package/lib/windows/gdi32.js +28 -6
  85. package/lib/windows/{kernel32.ts → kernel32.d.ts} +145 -113
  86. package/lib/windows/kernel32.js +9 -0
  87. package/lib/windows/{msimg32.ts → msimg32.d.ts} +11 -14
  88. package/lib/windows/ntdll.d.ts +5 -0
  89. package/lib/windows/ole32.d.ts +3 -0
  90. package/lib/windows/{psapi.ts → psapi.d.ts} +9 -18
  91. package/lib/windows/shell32.d.ts +51 -0
  92. package/lib/windows/shell32.js +11 -2
  93. package/lib/windows/structs.d.ts +3141 -0
  94. package/lib/windows/structs.js +51 -0
  95. package/lib/windows/user32.d.ts +623 -0
  96. package/lib/windows/user32.js +6 -5
  97. package/lib/windows/version.d.ts +27 -0
  98. package/lib/windows/{winspool.ts → winspool.d.ts} +18 -32
  99. package/main.js +13 -5
  100. package/package.json +16 -7
  101. package/quickwin.d.ts +13 -115
  102. package/qwin-nowasm-x86.exe +0 -0
  103. package/qwin-nowasm.exe +0 -0
  104. package/qwin-x86.exe +0 -0
  105. package/qwin.exe +0 -0
  106. package/test/bench_ffi_callraw.js +3 -4
  107. package/test/bench_ffi_callraw.ts +3 -4
  108. package/test/debug/mupdf_debug.js +4 -22
  109. package/test/debug/wasm_export_debug.js +2 -12
  110. package/test/debug/wasm_names.js +3 -13
  111. package/test/example.pdf +0 -0
  112. package/test/mupdf-cdn.js +40 -0
  113. package/test/mupdf-cdn.ts +43 -0
  114. package/test/test_ffi.js +8 -9
  115. package/test/test_ffi.ts +8 -9
  116. package/test/test_ffi_abi.js +6 -6
  117. package/test/test_ffi_abi.ts +8 -8
  118. package/test/test_ffi_windows.js +82 -11
  119. package/test/test_ffi_windows.ts +85 -11
  120. package/test/test_gdi_draw.js +3 -3
  121. package/test/test_gdi_draw.ts +4 -4
  122. package/test/test_mupdf_render.js +4 -22
  123. package/test/test_mupdf_render.ts +4 -23
  124. package/test/test_mupdf_twice.js +4 -19
  125. package/test/test_mupdf_twice.ts +4 -20
  126. package/test/test_mupdf_wasm.js +10 -4
  127. package/test/test_mupdf_wasm.ts +6 -4
  128. package/test/test_react_complex.js +316 -140
  129. package/test/test_react_counter.js +295 -133
  130. package/test/test_react_flex.js +297 -138
  131. package/test/test_react_hidden.js +296 -134
  132. package/test/test_react_listview_link.js +288 -131
  133. package/test/test_react_notify.js +290 -133
  134. package/test/test_react_render.js +295 -133
  135. package/lib/abort.ts +0 -69
  136. package/lib/assert.ts +0 -7
  137. package/lib/cache-utils.ts +0 -40
  138. package/lib/certs.ts +0 -229
  139. package/lib/dumpRects.ts +0 -26
  140. package/lib/exec-log.ts +0 -30
  141. package/lib/fetch.ts +0 -589
  142. package/lib/ffi/bind.ts +0 -539
  143. package/lib/ffi/ctype.ts +0 -371
  144. package/lib/ffi/index.ts +0 -6
  145. package/lib/ffi/struct.ts +0 -780
  146. package/lib/http-common.ts +0 -441
  147. package/lib/http-server.ts +0 -604
  148. package/lib/polyfill.ts +0 -171
  149. package/lib/react-qw/components/index.ts +0 -17
  150. package/lib/react-qw/index.ts +0 -96
  151. package/lib/react-qw/layout.ts +0 -111
  152. package/lib/react-qw/nmhdr.ts +0 -7
  153. package/lib/react-qw/props.ts +0 -41
  154. package/lib/react-qw/reconciler.ts +0 -383
  155. package/lib/stream.ts +0 -22
  156. package/lib/text-codec.ts +0 -171
  157. package/lib/text-measure.ts +0 -41
  158. package/lib/url.ts +0 -201
  159. package/lib/websocket.ts +0 -600
  160. package/lib/windows/comctl32.ts +0 -19
  161. package/lib/windows/comdlg32.ts +0 -10
  162. package/lib/windows/ntdll.ts +0 -11
  163. package/lib/windows/ole32.ts +0 -9
  164. package/lib/windows/shell32.ts +0 -39
  165. package/lib/windows/structs.ts +0 -752
  166. package/lib/windows/user32.ts +0 -619
  167. package/lib/windows/version.ts +0 -35
  168. package/vendor/mupdf-wasm/mupdf-wasm.d.ts +0 -571
  169. package/vendor/mupdf-wasm/mupdf-wasm.js +0 -2749
  170. package/vendor/mupdf-wasm/mupdf-wasm.wasm +0 -0
  171. package/vendor/mupdf-wasm/mupdf.d.ts +0 -939
  172. package/vendor/mupdf-wasm/mupdf.js +0 -3317
@@ -0,0 +1,117 @@
1
+ declare const C_BASIC_TYPE: readonly ['void', 'u8', 'i8', 'u16', 'i16', 'u32', 'i32', 'u64', 'i64', 'f32', 'f64', 'ptr'];
2
+ export type C_BasicType = (typeof C_BASIC_TYPE)[number];
3
+ export type C_BasicType_No_Void = Exclude<C_BasicType, 'void'>;
4
+ export type C_BasicType_Token = Exclude<C_BasicType, 'ptr'> | `<${string}>ptr` | `<${string}>ptr!` | `<${string}>`;
5
+ export type C_BasicType_Token_No_Void = Exclude<C_BasicType_Token, 'void'>;
6
+ export declare function isCPtrToken(t: string): t is `<${string}>ptr` | `${string}ptr!` | `${string}ptr@${string}`;
7
+ export declare function isCValToken(t: string): t is `<${string}>`;
8
+ export declare function valName<const N extends string>(t: `<${N}>`): N;
9
+ export declare function ptrName<const N extends string>(t: `<${N}>ptr` | `<${N}>ptr!`): N;
10
+ /**
11
+ * @description `<${string}>ptr` / `<${string}>ptr!` -> 'ptr'。按值形 `<${string}>` 无
12
+ * 标量槽等价物 —— 运行时 throw(返回位由 parseSig 拒、closure 入参位由 closure() 拒,
13
+ * 正常路径不可达),返回类型同时 Exclude 掉按值形:消费方(readRet / dispatchClosure
14
+ * 的 IA32_ARG_SIZE 索引)拿不到会误导编译期的标量误判。
15
+ */
16
+ export declare const cTokenToType: <const T extends string>(t: T) => Exclude<T, `<${string}>ptr` | `<${string}>ptr!` | `<${string}>`> | 'ptr';
17
+ export type C_Number = Exclude<C_BasicType, 'void' | 'ptr'>;
18
+ export type C_Integer = Exclude<C_Number, 'f32' | 'f64'>;
19
+ export type Encoding = 'utf-8' | 'utf-16le';
20
+ type First = '_' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z';
21
+ export type SimpleToken = C_Number | `${C_Number}@${keyof EnumMap}` | `<${string}>ptr` | `${string}ptr!` | `<${string}>ptr@${keyof EnumMap}`;
22
+ export type SimpleMember = {
23
+ [K: `${First}${string}`]: SimpleValue;
24
+ [K: `$${string}`]: C_Struct | C_Union;
25
+ };
26
+ export interface C_Struct {
27
+ '#': 'struct';
28
+ '#pack'?: number;
29
+ [K: `${First}${string}`]: SimpleValue;
30
+ [K: `$${string}`]: C_Struct | C_Union;
31
+ }
32
+ export interface C_Union {
33
+ '#': 'union';
34
+ '#pack'?: number;
35
+ [K: `${First}${string}`]: SimpleValue;
36
+ [K: `$${string}`]: C_Struct | C_Union;
37
+ }
38
+ export type C_Array = {
39
+ '#': 'array';
40
+ element: SimpleValue;
41
+ length: number;
42
+ };
43
+ export type SimpleValue = SimpleToken | `${SimpleToken}[${number}]` | `${C_Number}:${number}` | `${'u8' | 'u16'}[${number}]@${Encoding}` | C_Struct | C_Union | C_Array;
44
+ export declare const PTR_SIZE: number;
45
+ export declare const SizeAlign: Record<C_Number, number>;
46
+ export type Ptr<T extends string> = '' extends T ? number : number & {
47
+ readonly ptrBrand: T;
48
+ };
49
+ /** NULL 品牌零:0 的品牌形态 —— 全 FFI 层唯一的空指针字面量(对应 C 的 NULL 宏,
50
+ * 运行时就是 0)。JS 的 null 不在指针值域:类型层禁收,运行时不做 null→0 转换
51
+ * (动态 null 在参数槽 / 写槽处 fail-loud 报错)。 */
52
+ export type NULL = 0 & {
53
+ readonly ptrBrand: 'NULL';
54
+ };
55
+ export declare const NULL: NULL;
56
+ /** 唯一指针类型:参数位 / 返回位 / struct 字段 / closure 双侧通用。
57
+ * C→JS 0 保真(readScalar 不做 0→null);JS→C 空位写 NULL(写槽即 0)。
58
+ * 传参前由 tsc 收窄掉空位(truthy / === NULL / === 0)。 */
59
+ export type MaybePtr<T extends string> = NULL | Ptr<T>;
60
+ export type C_TypeJsTypeMap = {
61
+ u8: number;
62
+ i8: number;
63
+ u16: number;
64
+ i16: number;
65
+ u32: number;
66
+ i32: number;
67
+ i64: bigint;
68
+ u64: bigint;
69
+ f32: number;
70
+ f64: number;
71
+ };
72
+ export type TokenArgJsTypeMap = C_TypeJsTypeMap;
73
+ export type TokenReturnJsTypeMap = C_TypeJsTypeMap & {
74
+ void: void;
75
+ };
76
+ /** token 枚举标注('u32@Name' / '<>ptr@Name')的值域表 —— 全局 interface 声明合并:
77
+ * 预填由 tools/gen_enum_map.sh 从 quickwin_const.d.ts 提取(quickwin_enum_map.d.ts),
78
+ * 用户在自己的 .d.ts 里直接扩展(interface EnumMap { MyEnum: import('...').MyEnum })——
79
+ * 勿用 declare module:用户 import specifier 形态五花八门,模块匹配不上;全局合并对
80
+ * 「按枚举名索引」的 token 语义才成立。消费点(bind Arg/Ret、struct 字段)统一以
81
+ * `infer E extends keyof EnumMap` 收紧后直接索引本表 —— 值域类型不分参数/返回语境
82
+ * (拦异种枚举、域外字面量靠枚举类型自身的 nominal);未知枚举名由词汇/分支约束
83
+ * 挡在外面:struct 定义点 ∉ SimpleValue,bind 签名落链末 map[never] 塌 never
84
+ * (参数位)/ unknown(返回位——never 是 bottom 会被任意使用放行,反而危险)。 */
85
+ declare global {
86
+ interface EnumMap {
87
+ }
88
+ }
89
+ export type ArgJsTypeOfToken<K extends string, L> = K extends `<${infer N}>ptr!` ? Ptr<N> | L[N & keyof L] : K extends `<${string}>ptr@${infer E extends keyof EnumMap}` ? EnumMap[E] : K extends `<${infer N}>ptr` ? MaybePtr<N> | L[N & keyof L] : K extends `<${infer N}>` ? L[N & keyof L] : K extends `${C_Number}@${infer E extends keyof EnumMap}` ? EnumMap[E] : TokenArgJsTypeMap[K & keyof TokenArgJsTypeMap] extends never ? never : TokenArgJsTypeMap[K & keyof TokenArgJsTypeMap];
90
+ export type RetJsTypeOfToken<K extends string, D> = K extends `<${infer N}>ptr!` ? (D[N & keyof D] extends never ? Ptr<N> : D[N & keyof D]) : K extends `<${string}>ptr@${infer E extends keyof EnumMap}` ? EnumMap[E] : K extends `<${infer N}>ptr` ? (D[N & keyof D] extends never ? MaybePtr<N> : D[N & keyof D] | NULL) : K extends `${C_Number}@${infer E extends keyof EnumMap}` ? EnumMap[E] : TokenReturnJsTypeMap[K & keyof TokenReturnJsTypeMap] extends never ? unknown : TokenReturnJsTypeMap[K & keyof TokenReturnJsTypeMap];
91
+ export declare function normToken(t: string): C_BasicType_Token;
92
+ export declare function readScalar(dv: DataView, off: number, k: C_BasicType_No_Void): number | bigint | null;
93
+ type Entry = {
94
+ [K in C_BasicType_No_Void]: {
95
+ k: K;
96
+ v: (C_TypeJsTypeMap & {
97
+ ptr: number;
98
+ })[K];
99
+ };
100
+ }[C_BasicType_No_Void];
101
+ /** 内存写:按 sizeof 精确写,供 struct 字段编码用。小整数只占自己的字节,
102
+ * 否则 `{a:u8,b:u8}` 这类紧凑布局会被 setUint32 越界覆盖相邻字段。 */
103
+ export declare function writeScalar(dv: DataView, off: number, { k, v }: Entry): void;
104
+ /** 槽写:供 bind 的参数槽/返回槽用。小整数扩展到 4 字节 —— 可变参数按 int 提升读,
105
+ * `i8 = -1` 必须给 `0xFFFFFFFF` 而非 `0x000000FF`。u32/i32/u64/i64/f32/f64/ptr
106
+ * 槽宽 == sizeof,直接委托 writeScalar。 */
107
+ export declare function writeSlot(dv: DataView, off: number, e: Entry): void;
108
+ /** buffer + 品牌指针合一:一个引用既是 ArrayBuffer(喂 decode / encode(v, buf) 复用)
109
+ * 又带 `.ptr` 直接喂 <N>ptr 形参 —— 替代旧 { buf, ptr } 结构包装。
110
+ * `ptr` 是构造时快照(与旧 StructAlloc 同性质:底层数据不可 detach/transfer)。
111
+ * 品牌 N 由创建方声明:struct def 的 alloc()/encode() 返回值在类型层带 def 的 N(不可伪造);
112
+ * 直接 new 属自报品牌,仅限内部/原型场景 —— 生产路径一律走 def.alloc()。 */
113
+ export declare class PtrArrayBuffer<N extends string> extends ArrayBuffer {
114
+ readonly ptr: Ptr<N>;
115
+ constructor(byteLength: number);
116
+ }
117
+ export {};
@@ -0,0 +1,2 @@
1
+ export * from './bind.js';
2
+ export * from './struct.js';
@@ -0,0 +1,174 @@
1
+ import '../text-codec.js';
2
+ import { C_BasicType_No_Void, C_TypeJsTypeMap, MaybePtr, PtrArrayBuffer, type C_Array, type C_Integer, type C_Number, type C_Struct, type C_Union, type Encoding, type Ptr, type SimpleMember, type SimpleToken } from './ctype.js';
3
+ type N = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53;
4
+ type ValOf<T> = T extends `<${infer B}>ptr!` ? Ptr<B> : T extends `<${string}>ptr@${infer E extends keyof EnumMap}` ? EnumMap[E] : T extends `<${infer B}>ptr` ? MaybePtr<B> : T extends `${infer U}@${infer E extends keyof EnumMap}` ? (U extends C_Number ? EnumMap[E] : never) : T extends C_Number ? C_TypeJsTypeMap[T] : never;
5
+ type BitShape<T extends string, W extends number> = T extends C_Integer ? (W extends N ? number : bigint) : never;
6
+ type ShapeOfValue<V> = V extends infer T extends SimpleToken ? ValOf<T> : V extends `${infer U}[${infer L}]@${infer E}` ? (U extends 'u8' | 'u16' ? (L extends `${number}` ? (E extends Encoding ? string : never) : never) : never) : V extends `${infer T extends SimpleToken}[${infer L extends number}]` ? Tuple<ShapeOfValue<T>, L> : V extends `${infer T extends SimpleToken}:${infer W extends number}` ? BitShape<T, W> : V extends {
7
+ '#': 'array';
8
+ element: infer E;
9
+ length: infer L extends number;
10
+ } ? Tuple<ShapeOfValue<E>, L> : V extends {
11
+ '#': 'struct' | 'union';
12
+ } ? ShapeOfC<V> : never;
13
+ type Tuple<T, N extends number, R extends T[] = []> = number extends N ? T[] : R['length'] extends N ? R : R['length'] extends 64 ? T[] : Tuple<T, N, [...R, T]>;
14
+ type DollarKeys<T> = {
15
+ [K in keyof T]: K extends `$${string}` ? K : never;
16
+ }[keyof T];
17
+ type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
18
+ type Lift<T> = {
19
+ [K in keyof T as K extends `$${string}` ? never : K]: T[K] extends readonly unknown[] ? T[K] : T[K] extends number ? T[K] : T[K] extends object ? Lift<T[K]> : T[K];
20
+ } & UnionToIntersection<{
21
+ [K in DollarKeys<T>]: Lift<T[K]>;
22
+ }[DollarKeys<T>]>;
23
+ type FieldKey<K> = K extends `#${string}` ? never : K extends `${infer B}@${string}` ? B : K;
24
+ type _ShapeOfC<M> = {
25
+ [K in keyof M as FieldKey<K>]: ShapeOfValue<M[K]>;
26
+ };
27
+ type ShapeOfC<M> = Lift<_ShapeOfC<M>>;
28
+ export type DeepPartial<T> = T extends readonly unknown[] ? T : T extends number | string | boolean | bigint | symbol ? T : {
29
+ [K in keyof T]?: DeepPartial<T[K]>;
30
+ };
31
+ type IsSubtreeMandatory<D> = D extends {
32
+ '#': 'array';
33
+ element: infer E;
34
+ } ? IsSubtreeMandatory<E> : D extends {
35
+ '#': 'struct' | 'union';
36
+ } ? (true extends {
37
+ [K in keyof D]-?: IsSubtreeMandatory<D[K]> extends true ? true : false;
38
+ }[keyof D] ? true : false) : D extends `${string}[${number}]@${string}` ? false : D extends `${infer TK extends SimpleToken}[${string}]` ? IsSubtreeMandatory<TK> : D extends `${string}:${number}` ? false : D extends `<${string}>ptr!` ? true : D extends `<${string}>ptr@${infer E extends keyof EnumMap}` ? (0 extends EnumMap[E] ? false : true) : D extends `${infer U}@${infer E extends keyof EnumMap}` ? (U extends C_Number ? (0 extends EnumMap[E] ? false : true) : false) : false;
39
+ type MandatoryDeclKeys<T> = {
40
+ [K in keyof T]-?: IsSubtreeMandatory<T[K]> extends true ? FieldKey<K> : never;
41
+ }[keyof T];
42
+ type EncodeValOfT<D> = D extends {
43
+ '#': 'struct' | 'union';
44
+ } ? EncodeShapeOfC<D> : ShapeOfValue<D>;
45
+ type EncodeShapeOfC<T> = DeepPartial<ShapeOfC<T>> & {
46
+ [K in keyof T as IsSubtreeMandatory<T[K]> extends true ? FieldKey<K> : never]-?: EncodeValOfT<T[K]>;
47
+ };
48
+ type EncodeIn<T extends {
49
+ '#': 'struct' | 'union';
50
+ }> = [
51
+ MandatoryDeclKeys<T>
52
+ ] extends [never] ? DeepPartial<ShapeOfC<T>> : EncodeShapeOfC<T>;
53
+ type FieldType = {
54
+ tag: 'basic';
55
+ kind: C_BasicType_No_Void;
56
+ } | {
57
+ tag: 'bitfield';
58
+ unit: C_Integer;
59
+ bit: number;
60
+ width: number;
61
+ } | {
62
+ tag: 'string';
63
+ encoding: Encoding;
64
+ } | {
65
+ tag: 'struct' | 'union';
66
+ fields: Field[];
67
+ } | {
68
+ tag: 'array';
69
+ elementType: FieldType;
70
+ elementSize: number;
71
+ };
72
+ export type Field = {
73
+ name: string;
74
+ offset: number;
75
+ size: number;
76
+ type: FieldType;
77
+ /** '!' 标注字段(原文 token `<X>ptr!`):decode 读出 0 当场 throw(后置兜底 ——
78
+ * C 没填 / 拿未填充槽 decode 都在这里拦,见 doDecode)。 */
79
+ nonnull?: true;
80
+ };
81
+ export type Fields = Field[];
82
+ export type StructDef<T extends {
83
+ '#': 'struct' | 'union';
84
+ }, N extends string = ''> = {
85
+ readonly fields: Fields;
86
+ readonly size: number;
87
+ readonly structAlign: number;
88
+ decode(buf: ArrayBuffer | Ptr<N>): ShapeOfC<T>;
89
+ /** n(默认 1)= 按本布局 size 步长连续分配 n 个元素的零填充缓冲(出参数组场景,
90
+ * 品牌 .ptr 直接喂 <N>ptr 位)。n < 1 / 非整数运行时 throw ——
91
+ * 任何路径都不产出 PAB(0)(其 .ptr 是"非 0 的 1 字节堆指针",会骗过 C 的 NULL
92
+ * 防御;空位语义由调用方显式传 NULL)。 */
93
+ alloc(n?: number): PtrArrayBuffer<N>;
94
+ encode(v: EncodeIn<T>): PtrArrayBuffer<N>;
95
+ encode(v: EncodeIn<T>, buf: PtrArrayBuffer<any>, offset?: number): PtrArrayBuffer<any>;
96
+ offsetOf(name: string): number;
97
+ };
98
+ type Layout = {
99
+ size: number;
100
+ maxEffectiveAlign: number;
101
+ fields: Fields;
102
+ };
103
+ export declare function computeArray(t: C_Array): {
104
+ align: number;
105
+ size: number;
106
+ };
107
+ export declare function computeStructLayout(t: C_Struct | C_Union): Layout;
108
+ /** 聚合对齐上限(pack 压 maxAlign,语义同 MSVC #pragma pack)。 */
109
+ export type AggOpts = {
110
+ pack?: number;
111
+ };
112
+ /** def 的类型经方法签名索引提取(StructDef 不再挂 __struct 成员 —— T 只活在签名里):
113
+ * encode 重载末条首参 = EncodeIn<T>、decode 返回 = ShapeOfC<T>、alloc 返回 = PAB<N>、
114
+ * decode 首参剥 ArrayBuffer = Ptr<N>(裸地址形)。 */
115
+ type EncInOf<D extends StructDef<any, any>> = Parameters<D['encode']>[0];
116
+ type DecOf<D extends StructDef<any, any>> = ReturnType<D['decode']>;
117
+ type PABOf<D extends StructDef<any, any>> = ReturnType<D['alloc']>;
118
+ type AddrOf<D extends StructDef<any, any>> = Exclude<Parameters<D['decode']>[0], ArrayBuffer>;
119
+ /** decode 双态重载:有 byteLength 的 buffer 形 count 可缺省(自算);裸地址无长度
120
+ * 信息,count 必填(类型层拦,缺省调用编译红)。 */
121
+ type StructArrayDecode<D extends StructDef<any, any>> = {
122
+ (p: ArrayBuffer, count?: number): DecOf<D>[];
123
+ (p: AddrOf<D>, count: number): DecOf<D>[];
124
+ };
125
+ /** 结构/联合体的数组编解码对工厂:返回 `{ encode, decode }`。
126
+ * encode —— 单值 encoder 的数组版:收元素数组 → 按本布局 size 步长紧密排列
127
+ * (stride = size,已含尾部对齐 padding),返回带品牌 .ptr 的 PAB —— 与 C 的
128
+ * `const T apt[]` 同构。值域刻意收普通数组(调用方持有的 `const pts = [...]` 变量
129
+ * 直传,非空元组会拒之);[] / 非数组 / 单对象运行时 throw —— 任何路径都不产出
130
+ * PAB(0)(其 .ptr 是"非 0 的 1 字节堆指针",会骗过 C 的 NULL 防御;空位语义由
131
+ * 调用方显式传 NULL)。注册进 bind 的 encoders 表(`{ POINT: structArray(POINT) }`)
132
+ * 后,普通 `<POINT>ptr` 位的值域即元素数组(值域由 encoder 推导,token/引擎/类型层
133
+ * 零数组概念);直接调用 `.encode(els).ptr` 亦可。
134
+ * decode —— 出参数组读回(与 def.decode 的 ArrayBuffer/地址双态对称):
135
+ * - buffer 形(含 PAB):count? 缺省自算 byteLength/size —— 要求整数倍,% ≠ 0
136
+ * throw(混合缓冲如 EnumPrinters 的"结构 + 尾部字符串"必须显式 count);显式
137
+ * count 校验 count*size ≤ byteLength(写错 count → 越界读的防线,buf 形可校才
138
+ * 校;不验品牌,与 def.decode 的 buffer 形同款)。
139
+ * - 裸地址形:count 必填(地址无长度信息),逐字节拷读(def.decode 的 number 形
140
+ * 同机制);长度不可校 → 信任 C 的 count。
141
+ * - count = 0 → [](读 0 个真空安全,与 encode 禁空的 PAB(0) 理由刻意不对称)。
142
+ * 实现:encode 走纯公开 API(alloc + encode offset 循环);decode 直接读 def.fields
143
+ * (createStruct 暴露的布局 IR,与 def.decode 同一份,无需重算)。 */
144
+ export declare function structArray<D extends StructDef<any, any>>(def: D): {
145
+ encode: (els: readonly EncInOf<D>[]) => PABOf<D>;
146
+ decode: StructArrayDecode<D>;
147
+ };
148
+ /** 平铺字段表定义结构体(token/`X[n]`/`unit:width`/`'#'` 声明均可,见 ctype.ts §4)。
149
+ * 给 name 则 alloc().ptr 与 decode 入参带 Ptr<name> 品牌。DECL 常量可直传(
150
+ * `struct('X', X_DECL)`)—— 参数交叉 `{ '#'?: 'struct' }` 锁 kind:传 union/array
151
+ * DECL 时 '#' 字面类型交叉成 never,编译期即报错。 */
152
+ type StructOf<M, N extends string = ''> = StructDef<{
153
+ '#': 'struct';
154
+ '#pack'?: number;
155
+ } & M, N>;
156
+ type UnionOf<M, N extends string = ''> = StructDef<{
157
+ '#': 'union';
158
+ '#pack'?: number;
159
+ } & M, N>;
160
+ export declare function struct<const M extends SimpleMember>(member: M & {
161
+ '#'?: 'struct';
162
+ }, opts?: AggOpts): StructOf<M>;
163
+ export declare function struct<const N extends string, const M extends SimpleMember>(name: N, member: M & {
164
+ '#'?: 'struct';
165
+ }, opts?: AggOpts): StructOf<M, N>;
166
+ /** 平铺字段表定义联合体;布局/读写与 struct 相同,仅成员偏移重叠。DECL 常量可直传,
167
+ * 参数交叉 `{ '#'?: 'union' }` 锁 kind(struct 侧镜像,理由见上)。 */
168
+ export declare function union<const M extends SimpleMember>(member: M & {
169
+ '#'?: 'union';
170
+ }, opts?: AggOpts): UnionOf<M>;
171
+ export declare function union<const N extends string, const M extends SimpleMember>(name: N, member: M & {
172
+ '#'?: 'union';
173
+ }, opts?: AggOpts): UnionOf<M, N>;
174
+ export {};
@@ -0,0 +1,143 @@
1
+ import './polyfill.js';
2
+ import './stream.js';
3
+ export declare function _concat(parts: Uint8Array[]): Uint8Array<ArrayBuffer>;
4
+ export declare function _toReadableStream(body: BodyInit): ReadableStream<Uint8Array>;
5
+ export declare function _readStream(stream: ReadableStream<Uint8Array>): Promise<Uint8Array<ArrayBuffer>>;
6
+ export declare function _hasChunkedEnd(data: Uint8Array): boolean;
7
+ export declare function decodeChunked(data: Uint8Array): Uint8Array;
8
+ export declare class HeadersImpl {
9
+ private _headers;
10
+ constructor(init?: HeadersInit);
11
+ append(name: string, value: string): void;
12
+ delete(name: string): void;
13
+ get(name: string): string | null;
14
+ has(name: string): boolean;
15
+ set(name: string, value: string): void;
16
+ forEach(callback: (value: string, name: string, headers: HeadersImpl) => void): void;
17
+ entries(): IterableIterator<[string, string]>;
18
+ keys(): IterableIterator<string>;
19
+ values(): IterableIterator<string>;
20
+ [Symbol.iterator](): IterableIterator<[string, string]>;
21
+ }
22
+ export declare class RequestImpl {
23
+ readonly url: string;
24
+ readonly method: string;
25
+ readonly headers: HeadersImpl;
26
+ private _body;
27
+ readonly redirect: RequestRedirect;
28
+ readonly timeout: number;
29
+ readonly maxRedirects: number;
30
+ private _bodyConsumed;
31
+ readonly integrity: string;
32
+ readonly keepalive: boolean;
33
+ readonly mode: string;
34
+ readonly cache: string;
35
+ readonly credentials: string;
36
+ readonly referrer: string;
37
+ readonly referrerPolicy: string;
38
+ readonly signal: AbortSignal | null;
39
+ readonly rejectUnauthorized: boolean;
40
+ readonly destination: string;
41
+ get body(): ReadableStream<Uint8Array> | null;
42
+ get bodyUsed(): boolean;
43
+ constructor(input: string | RequestImpl, init?: RequestInit);
44
+ arrayBuffer(): Promise<ArrayBuffer>;
45
+ json<T = unknown>(): Promise<T>;
46
+ text(): Promise<string>;
47
+ clone(): RequestImpl;
48
+ }
49
+ export declare class ResponseImpl {
50
+ readonly status: number;
51
+ readonly statusText: string;
52
+ readonly ok: boolean;
53
+ private _headers;
54
+ _redirected: boolean;
55
+ private _type;
56
+ _url: string;
57
+ private _body;
58
+ private _bodyConsumed;
59
+ private _trailers;
60
+ get body(): ReadableStream<Uint8Array>;
61
+ get bodyUsed(): boolean;
62
+ /** Trailing headers to emit after a chunked body (Promise resolves to
63
+ * a HeadersInit), when a `Trailer` declaration header is present. */
64
+ get trailers(): Promise<HeadersInit> | undefined;
65
+ get headers(): HeadersImpl;
66
+ get redirected(): boolean;
67
+ get type(): ResponseType;
68
+ get url(): string;
69
+ constructor(body?: BodyInit | null, init?: ResponseInit);
70
+ text(): Promise<string>;
71
+ json<T = unknown>(): Promise<T>;
72
+ arrayBuffer(): Promise<ArrayBuffer>;
73
+ bytes(): Promise<Uint8Array>;
74
+ clone(): Response;
75
+ _applyDecompressedBody(stream: ReadableStream<Uint8Array>, _body: ArrayBuffer, newHeaders: HeadersImpl): void;
76
+ }
77
+ declare global {
78
+ type HeadersInit = [string, string][] | Record<string, string> | Headers;
79
+ type BodyInit = ReadableStream<Uint8Array> | string | ArrayBuffer | ArrayBufferView;
80
+ type RequestRedirect = 'error' | 'follow' | 'manual';
81
+ type RequestCache = 'default' | 'force-cache' | 'no-cache' | 'no-store' | 'only-if-cached' | 'reload';
82
+ type RequestCredentials = 'include' | 'omit' | 'same-origin';
83
+ type RequestMode = 'cors' | 'navigate' | 'no-cors' | 'same-origin';
84
+ type ResponseType = 'basic' | 'cors' | 'default' | 'error' | 'opaque' | 'opaqueredirect';
85
+ interface AbortSignal {
86
+ readonly aborted: boolean;
87
+ readonly reason: unknown;
88
+ onabort: ((event: {
89
+ type: 'abort';
90
+ target: unknown;
91
+ }) => void) | null;
92
+ addEventListener(type: 'abort', listener: (e: {
93
+ type: 'abort';
94
+ target: unknown;
95
+ }) => void): void;
96
+ removeEventListener(type: 'abort', listener: (e: {
97
+ type: 'abort';
98
+ target: unknown;
99
+ }) => void): void;
100
+ throwIfAborted(): void;
101
+ }
102
+ interface RequestInit {
103
+ body?: BodyInit | null;
104
+ cache?: RequestCache;
105
+ credentials?: RequestCredentials;
106
+ headers?: HeadersInit;
107
+ integrity?: string;
108
+ keepalive?: boolean;
109
+ method?: string;
110
+ mode?: RequestMode;
111
+ redirect?: RequestRedirect;
112
+ referrer?: string;
113
+ referrerPolicy?: string;
114
+ signal?: AbortSignal | null;
115
+ window?: null;
116
+ timeout?: number;
117
+ maxRedirects?: number;
118
+ /** Non-standard: when false, TLS certificate verification is skipped
119
+ * (mirrors Node's https.request rejectUnauthorized option). */
120
+ rejectUnauthorized?: boolean;
121
+ }
122
+ interface ResponseInit {
123
+ status?: number;
124
+ statusText?: string;
125
+ headers?: HeadersInit;
126
+ /** Non-standard: trailing headers, resolved after the body streams.
127
+ * http-server emits them (Node addTrailers semantics) when a `Trailer`
128
+ * declaration header is present and the body is chunk-framed. */
129
+ trailers?: Promise<HeadersInit>;
130
+ }
131
+ interface Headers extends HeadersImpl {
132
+ }
133
+ var Headers: typeof HeadersImpl;
134
+ interface Response extends Omit<ResponseImpl, '_url' | '_redirected' | '_applyDecompressedBody'> {
135
+ }
136
+ interface ResponseConstructor {
137
+ new (body?: BodyInit | null, init?: ResponseInit): Response;
138
+ }
139
+ var Response: ResponseConstructor;
140
+ interface Request extends RequestImpl {
141
+ }
142
+ var Request: typeof RequestImpl;
143
+ }
@@ -0,0 +1,59 @@
1
+ import './polyfill.js';
2
+ import * as sock from 'sock';
3
+ import { RequestImpl } from './http-common.js';
4
+ import { AbortController } from './abort.js';
5
+ type SockHandle = import('sock').SockHandle;
6
+ export type ServerHandler = (req: Request) => Promise<Response>;
7
+ interface ParsedHeader {
8
+ method: string;
9
+ target: string;
10
+ version: string;
11
+ headers: Record<string, string>;
12
+ chunked: boolean;
13
+ contentLength: number;
14
+ }
15
+ interface PendingReq {
16
+ parsed: ParsedHeader;
17
+ bodyStart: number;
18
+ }
19
+ interface ActiveReq {
20
+ req: RequestImpl;
21
+ }
22
+ interface Conn {
23
+ sock: SockHandle;
24
+ parts: Uint8Array[];
25
+ /** Cached total length of `parts` — lets the pending-body wait check
26
+ * "have we received enough yet" in O(1) instead of re-concatenating
27
+ * every received byte on each read event (O(n²) for large bodies). */
28
+ partsLen: number;
29
+ pending: PendingReq | null;
30
+ current: ActiveReq | null;
31
+ outQueue: Uint8Array | null;
32
+ resumeRead: (() => void) | null;
33
+ closed: boolean;
34
+ closeAfterFlush: boolean;
35
+ keepAlive: boolean;
36
+ owner: HttpServer;
37
+ /** AbortController for the request currently served on this connection,
38
+ * aborted when the client disconnects mid-response. */
39
+ ac: AbortController | null;
40
+ }
41
+ export declare class HttpServer {
42
+ readonly handler: ServerHandler;
43
+ private serverSock;
44
+ readonly conns: Map<sock.SockHandle, Conn>;
45
+ private closed;
46
+ constructor(handler: ServerHandler);
47
+ /** Actual bound address, or null if not listening. */
48
+ address(): {
49
+ addr: string;
50
+ port: number;
51
+ } | null;
52
+ /** Bind and start listening. Returns 0 on success, -1 on failure. */
53
+ listen(port: number, host?: string, backlog?: number): number;
54
+ close(): void;
55
+ private acceptLoop;
56
+ private onConnEvent;
57
+ }
58
+ export declare function createServer(handler: ServerHandler): HttpServer;
59
+ export {};
@@ -0,0 +1,22 @@
1
+ import * as os from 'os';
2
+ import './url.js';
3
+ import './text-codec.js';
4
+ declare global {
5
+ interface Console {
6
+ error: (...args: unknown[]) => void;
7
+ }
8
+ var window: typeof globalThis;
9
+ type TimerId = os.TimerId;
10
+ function setTimeout<P extends unknown[]>(fn: (...argsf: P) => void, ms?: number, ...argsr: P): TimerId;
11
+ function clearTimeout(id: TimerId): void;
12
+ function btoa(data: string): string;
13
+ function atob(data: string): string;
14
+ interface SubtleCrypto {
15
+ digest(algorithm: 'SHA-1', data: ArrayBuffer | Uint8Array): Promise<ArrayBuffer>;
16
+ }
17
+ interface Crypto {
18
+ getRandomValues<T extends ArrayBufferView>(array: T): T;
19
+ subtle: SubtleCrypto;
20
+ }
21
+ var crypto: Crypto;
22
+ }
@@ -0,0 +1,9 @@
1
+ import * as gui from 'gui';
2
+ import type { WStyle } from '../jsx.d.ts';
3
+ export interface ButtonProps {
4
+ children?: string | number | (string | number)[];
5
+ onClick?: () => void;
6
+ style?: WStyle;
7
+ disabled?: boolean;
8
+ }
9
+ export declare const Button: import("react").ForwardRefExoticComponent<ButtonProps & import("react").RefAttributes<gui.HWND>>;
@@ -0,0 +1,11 @@
1
+ import * as gui from 'gui';
2
+ import type { WStyle } from '../jsx.d.ts';
3
+ export interface CheckBoxProps {
4
+ checked?: boolean;
5
+ defaultChecked?: boolean;
6
+ onChange?: (checked: boolean) => void;
7
+ label?: string;
8
+ style?: WStyle;
9
+ disabled?: boolean;
10
+ }
11
+ export declare const CheckBox: import("react").ForwardRefExoticComponent<CheckBoxProps & import("react").RefAttributes<gui.HWND>>;
@@ -0,0 +1,11 @@
1
+ import * as gui from 'gui';
2
+ import type { WStyle } from '../jsx.d.ts';
3
+ export interface ComboBoxProps {
4
+ items: string[];
5
+ selectedIndex?: number;
6
+ defaultSelectedIndex?: number;
7
+ onChange?: (index: number) => void;
8
+ style?: WStyle;
9
+ disabled?: boolean;
10
+ }
11
+ export declare const ComboBox: import("react").ForwardRefExoticComponent<ComboBoxProps & import("react").RefAttributes<gui.HWND>>;
@@ -0,0 +1,15 @@
1
+ import * as gui from 'gui';
2
+ import type { WStyle } from '../jsx.d.ts';
3
+ export interface DateTimePickerProps {
4
+ value?: Date | null;
5
+ onChange?: (date: Date | null) => void;
6
+ defaultValue?: Date;
7
+ format?: 'short' | 'long' | 'time';
8
+ allowNone?: boolean;
9
+ updown?: boolean;
10
+ style?: WStyle;
11
+ }
12
+ declare const DateTimePicker: (props: DateTimePickerProps & {
13
+ ref?: React.Ref<gui.HWND>;
14
+ }) => React.ReactElement;
15
+ export { DateTimePicker };
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { forwardRef, useRef, useEffect, useState } from 'react';
3
3
  import * as gui from 'gui';
4
- import { InvalidateRect } from '../../windows/user32.js';
4
+ import { GetClientRect, InvalidateRect } from '../../windows/user32.js';
5
5
  import { NULL } from '../../ffi/ctype.js';
6
- import { SYSTEMTIME, NMDATETIMECHANGE } from '../../windows/structs.js';
6
+ import { RECT, SYSTEMTIME, NMDATETIMECHANGE } from '../../windows/structs.js';
7
7
  import { nmCode } from '../nmhdr.js';
8
8
  function dateToSysTimeBuf(d) {
9
9
  // wDayOfWeek 设置时被忽略,缺省跳过 = 0
@@ -52,11 +52,10 @@ const DateTimePicker = forwardRef(function DateTimePicker({ value, onChange, def
52
52
  return;
53
53
  InvalidateRect(h, NULL, 1);
54
54
  // 发送 WM_SIZE 让控件(尤其是 DTS_UPDOWN)重新布局内部子窗口
55
- const cr = gui.GetClientRect(h);
56
- if (cr) {
57
- const w = cr.right - cr.left;
58
- const hh = cr.bottom - cr.top;
59
- gui.SendMessage(h, 5 /* WmMsg.SIZE */, 0, (hh << 16) | w);
55
+ const cr = RECT.alloc();
56
+ if (GetClientRect(h, cr.ptr)) {
57
+ const { left, top, right, bottom } = RECT.decode(cr);
58
+ gui.SendMessage(h, 5 /* WmMsg.SIZE */, 0, ((bottom - top) << 16) | (right - left));
60
59
  }
61
60
  }, []);
62
61
  return (_jsx("w", { type: "STATIC", ws: 268435456 /* WindowStyle.VISIBLE */ | 33554432 /* WindowStyle.CLIPCHILDREN */, style: { ...style, flexDirection: 'column', alignItems: 'stretch' }, ref: ref, onEvent: (e) => {
@@ -0,0 +1,15 @@
1
+ import * as gui from 'gui';
2
+ import type { WStyle } from '../jsx.d.ts';
3
+ export interface InputProps {
4
+ value?: string;
5
+ defaultValue?: string;
6
+ onChange?: (value: string) => void;
7
+ placeholder?: string;
8
+ password?: boolean;
9
+ multiline?: boolean;
10
+ readonly?: boolean;
11
+ number?: boolean;
12
+ disabled?: boolean;
13
+ style?: WStyle;
14
+ }
15
+ export declare const Input: import("react").ForwardRefExoticComponent<InputProps & import("react").RefAttributes<gui.HWND>>;
@@ -2,6 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { forwardRef, useState, useRef, useEffect } from 'react';
3
3
  import * as gui from 'gui';
4
4
  import { WCHAR } from '../../ffi/bind.js';
5
+ import { GetWindowText, GetWindowTextLength } from '../../windows/user32.js';
5
6
  export const Input = forwardRef(({ value: controlledValue, defaultValue = '', onChange, placeholder, password, multiline, readonly, number, disabled, style }, ref) => {
6
7
  const [internalValue, setInternalValue] = useState(defaultValue);
7
8
  const isControlled = controlledValue !== undefined;
@@ -34,7 +35,10 @@ export const Input = forwardRef(({ value: controlledValue, defaultValue = '', on
34
35
  const h = inputRef.current;
35
36
  if (!h)
36
37
  return;
37
- const newText = gui.GetWindowText(h);
38
+ const cap = GetWindowTextLength(h) + 1;
39
+ const buf = WCHAR.alloc(cap);
40
+ GetWindowText(h, buf, cap);
41
+ const newText = WCHAR.decode(buf);
38
42
  if (!isControlled)
39
43
  setInternalValue(newText);
40
44
  onChange?.(newText);
@@ -0,0 +1,12 @@
1
+ import * as gui from 'gui';
2
+ import type { WStyle } from '../jsx.d.ts';
3
+ export interface LinkProps {
4
+ href?: string;
5
+ children?: string;
6
+ onClick?: (url: string) => void;
7
+ style?: WStyle;
8
+ }
9
+ declare const Link: (props: LinkProps & {
10
+ ref?: React.Ref<gui.HWND>;
11
+ }) => React.ReactElement;
12
+ export { Link };