@weft-js/plugin-surface-keel 0.1.0 → 0.1.3

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.
@@ -0,0 +1,540 @@
1
+ import './glyph-theme.mjs';
2
+ import {
3
+ rgba,
4
+ } from './color-font.mjs';
5
+ import {
6
+ add2,
7
+ arrowHead,
8
+ cut,
9
+ disc,
10
+ gear,
11
+ poly,
12
+ rect,
13
+ seg,
14
+ star,
15
+ strokes,
16
+ sword,
17
+ } from './glyph-theme.mjs';
18
+
19
+ var ICON_RECIPES = {
20
+ attack: { tone: "bad", variants: [
21
+ (S, w) => sword(S, w, S.chance(0.5)),
22
+ (S, w) => [...sword(S, w, false), ...sword(S, w, true)],
23
+ (S, w) => {
24
+ const r = S.between(0.28, 0.34);
25
+ return [add2(...strokes([[0.5, 0.08], [0.5, 0.3]], w), ...strokes([[0.5, 0.7], [0.5, 0.92]], w), ...strokes([[0.08, 0.5], [0.3, 0.5]], w), ...strokes([[0.7, 0.5], [0.92, 0.5]], w), disc(0.5, 0.5, r)), cut(disc(0.5, 0.5, r - w)), add2(disc(0.5, 0.5, w * 0.7))];
26
+ }
27
+ ] },
28
+ move: { tone: "good", variants: [
29
+ (S, w) => {
30
+ const t = S.between(0.2, 0.3);
31
+ return [add2(seg(0.18, 0.82, 0.72, 0.28, w * 1.4), arrowHead(0.86, 0.14, 1, -1, t + 0.1))];
32
+ },
33
+ (S, w) => [add2(...strokes([[0.18, 0.2], [0.46, 0.5], [0.18, 0.8]], w * 1.4)), add2(...strokes([[0.5, 0.2], [0.78, 0.5], [0.5, 0.8]], w * 1.4))],
34
+ (S, w) => {
35
+ const h = S.between(0.14, 0.2);
36
+ return [add2(seg(0.5, 0.18, 0.5, 0.82, w * 1.2), seg(0.18, 0.5, 0.82, 0.5, w * 1.2), arrowHead(0.5, 0.06, 0, -1, h), arrowHead(0.5, 0.94, 0, 1, h), arrowHead(0.06, 0.5, -1, 0, h), arrowHead(0.94, 0.5, 1, 0, h))];
37
+ }
38
+ ] },
39
+ stop: { tone: "bad", variants: [
40
+ (S) => {
41
+ const r = S.between(0.4, 0.44);
42
+ return [add2(star(0.5, 0.5, r, r, 4, Math.PI / 8))];
43
+ },
44
+ (S) => {
45
+ const m = S.between(0.14, 0.2);
46
+ return [add2(rect(m, m, 1 - m, 1 - m))];
47
+ }
48
+ ] },
49
+ hold: { tone: "accent", variants: [
50
+ (S) => {
51
+ const n = S.between(0.62, 0.72);
52
+ return [add2(poly([0.14, 0.14], [0.86, 0.14], [0.86, n - 0.1], [0.5, 0.92], [0.14, n - 0.1]))];
53
+ },
54
+ (S, w) => [add2(rect(0.2, 0.44, 0.8, 0.88), ...strokes([[0.32, 0.46], [0.32, 0.28], [0.5, 0.12], [0.68, 0.28], [0.68, 0.46]], w * 1.2))]
55
+ ] },
56
+ patrol: { tone: "accent", variants: [
57
+ (S, w) => [add2(seg(0.14, 0.34, 0.74, 0.34, w * 1.3), arrowHead(0.9, 0.34, 1, 0, 0.2), seg(0.26, 0.68, 0.86, 0.68, w * 1.3), arrowHead(0.1, 0.68, -1, 0, 0.2))],
58
+ (S, w) => [add2(disc(0.5, 0.5, 0.38)), cut(disc(0.5, 0.5, 0.38 - w * 1.4), rect(0.5, 0, 1, 0.5)), add2(arrowHead(0.5 + 0.38 - w * 0.7, 0.62, 0, -1, 0.22))]
59
+ ] },
60
+ build: { tone: "warn", variants: [
61
+ (S, w) => {
62
+ const h = S.between(0.18, 0.24);
63
+ return [add2(seg(0.24, 0.86, 0.62, 0.36, w * 1.4)), add2(poly([0.38, 0.28], [0.62, 0.06], [0.94, 0.38], [0.72, 0.6]), seg(0.46, 0.2, 0.46 - h, 0.2 - h * 0.2, w))];
64
+ },
65
+ (S, w) => [add2(seg(0.2, 0.82, 0.6, 0.42, w * 1.6), disc(0.68, 0.32, 0.22)), cut(poly([0.68, 0.32], [0.95, 0.1], [0.95, 0.4]), disc(0.2, 0.82, w * 0.4))],
66
+ () => [add2(rect(0.08, 0.2, 0.46, 0.44), rect(0.54, 0.2, 0.92, 0.44), rect(0.08, 0.52, 0.28, 0.76), rect(0.36, 0.52, 0.64, 0.76), rect(0.72, 0.52, 0.92, 0.76))]
67
+ ] },
68
+ upgrade: { tone: "good", variants: [
69
+ (S, w) => [add2(rect(0.36, 0.44, 0.64, 0.9), poly([0.5, 0.08], [0.9, 0.5], [0.1, 0.5]))],
70
+ (S, w) => [add2(...strokes([[0.16, 0.5], [0.5, 0.2], [0.84, 0.5]], w * 1.6)), add2(...strokes([[0.16, 0.82], [0.5, 0.52], [0.84, 0.82]], w * 1.6))],
71
+ (S, w) => [add2(star(0.44, 0.52, 0.4, 0.18, 5)), add2(seg(0.8, 0.08, 0.8, 0.34, w), seg(0.67, 0.21, 0.93, 0.21, w))]
72
+ ] },
73
+ supply: { tone: "warn", variants: [
74
+ (S) => {
75
+ const r = S.between(0.4, 0.5);
76
+ return [add2(poly([0.5, 0.08], [0.92, r], [0.8, r], [0.8, 0.9], [0.2, 0.9], [0.2, r], [0.08, r])), cut(rect(0.42, 0.62, 0.58, 0.9))];
77
+ },
78
+ () => [add2(disc(0.5, 0.28, 0.18), poly([0.16, 0.92], [0.2, 0.6], [0.36, 0.5], [0.64, 0.5], [0.8, 0.6], [0.84, 0.92]))],
79
+ (S, w) => [add2(rect(0.12, 0.18, 0.88, 0.86)), cut(rect(0.12 + w, 0.18 + w, 0.88 - w, 0.86 - w)), add2(seg(0.12, 0.18, 0.88, 0.86, w), seg(0.88, 0.18, 0.12, 0.86, w))]
80
+ ] },
81
+ resource: { tone: "accent", variants: [
82
+ (S) => {
83
+ const t = S.between(0.3, 0.4);
84
+ return [add2(poly([0.5, 0.06], [0.88, t], [0.5, 0.94], [0.12, t]))];
85
+ },
86
+ () => [add2(poly([0.3, 0.9], [0.22, 0.4], [0.36, 0.12], [0.5, 0.4], [0.46, 0.9]), poly([0.5, 0.9], [0.56, 0.3], [0.7, 0.06], [0.82, 0.32], [0.76, 0.9]))]
87
+ ] },
88
+ mass: { tone: "accent", variants: [
89
+ () => [add2(poly([0.5, 0.08], [0.9, 0.28], [0.9, 0.72], [0.5, 0.92], [0.1, 0.72], [0.1, 0.28]))],
90
+ () => [add2(poly([0.2, 0.36], [0.8, 0.36], [0.94, 0.76], [0.06, 0.76]))]
91
+ ] },
92
+ energy: { tone: "warn", variants: [
93
+ (S) => {
94
+ const k = S.between(0.44, 0.54);
95
+ return [add2(poly([0.62, 0.04], [0.2, k + 0.06], [0.48, k + 0.06], [0.36, 0.96], [0.82, k - 0.08], [0.54, k - 0.08]))];
96
+ },
97
+ (S, w) => [add2(disc(0.5, 0.5, 0.22), disc(0.5, 0.5, 0.44, 0.2)), cut(disc(0.5, 0.5, 0.44 - w, 0.2 - w)), add2(disc(0.5, 0.5, 0.22))]
98
+ ] },
99
+ biomass: { tone: "good", variants: [
100
+ (S, w) => [add2(poly([0.14, 0.86], [0.2, 0.4], [0.5, 0.14], [0.9, 0.1], [0.84, 0.5], [0.6, 0.8])), cut(seg(0.2, 0.8, 0.7, 0.3, w * 0.8))],
101
+ () => [add2(poly([0.5, 0.06], [0.78, 0.5], [0.7, 0.8], [0.5, 0.92], [0.3, 0.8], [0.22, 0.5]), disc(0.5, 0.64, 0.28))]
102
+ ] },
103
+ salvage: { tone: "ink", variants: [
104
+ (S, w) => {
105
+ const t = S.pick([6, 7, 8]);
106
+ return [add2(gear(0.5, 0.5, 0.46, t, 0.12)), cut(disc(0.5, 0.5, 0.14))];
107
+ },
108
+ () => [add2(star(0.5, 0.5, 0.44, 0.44, 3, Math.PI / 2)), cut(disc(0.5, 0.5, 0.14))]
109
+ ] },
110
+ gather: { tone: "warn", variants: [
111
+ (S, w) => [add2(seg(0.22, 0.88, 0.62, 0.36, w * 1.3)), add2(...strokes([[0.18, 0.3], [0.48, 0.14], [0.66, 0.2], [0.84, 0.44]], w * 1.5))]
112
+ ] },
113
+ repair: { tone: "good", variants: [
114
+ (S, w) => [add2(seg(0.2, 0.82, 0.6, 0.42, w * 1.6), disc(0.68, 0.32, 0.22)), cut(poly([0.68, 0.32], [0.95, 0.1], [0.95, 0.4]))],
115
+ (S) => {
116
+ const t = S.between(0.14, 0.18);
117
+ return [add2(rect(0.5 - t, 0.12, 0.5 + t, 0.88), rect(0.12, 0.5 - t, 0.88, 0.5 + t))];
118
+ }
119
+ ] },
120
+ cancel: { tone: "bad", variants: [(S, w) => [add2(seg(0.16, 0.16, 0.84, 0.84, w * 1.8), seg(0.84, 0.16, 0.16, 0.84, w * 1.8))]] },
121
+ rally: { tone: "accent", variants: [
122
+ (S, w) => [add2(seg(0.24, 0.08, 0.24, 0.94, w * 1.2), poly([0.24, 0.1], [0.86, 0.26], [0.24, 0.5]))],
123
+ (S, w) => [add2(seg(0.24, 0.08, 0.24, 0.94, w * 1.2), poly([0.24, 0.1], [0.84, 0.1], [0.7, 0.28], [0.84, 0.46], [0.24, 0.46]))]
124
+ ] },
125
+ research: { tone: "accent", variants: [
126
+ () => [add2(poly([0.38, 0.08], [0.62, 0.08], [0.62, 0.36], [0.9, 0.9], [0.1, 0.9], [0.38, 0.36]))],
127
+ (S, w) => [add2(rect(0.14, 0.14, 0.86, 0.86)), cut(seg(0.5, 0.2, 0.5, 0.86, w)), cut(rect(0.14 + w, 0.26, 0.44, 0.3), rect(0.56, 0.26, 0.86 - w, 0.3))]
128
+ ] },
129
+ train: { tone: "ink", variants: [
130
+ () => [add2(disc(0.5, 0.26, 0.18), poly([0.18, 0.92], [0.24, 0.56], [0.5, 0.46], [0.76, 0.56], [0.82, 0.92]))],
131
+ (S, w) => [add2(disc(0.5, 0.56, 0.36), rect(0.1, 0.56, 0.9, 0.7)), cut(rect(0, 0.7, 1, 1), rect(0.34, 0.5, 0.66, 0.6))]
132
+ ] },
133
+ ability: { tone: "accent", variants: [
134
+ (S) => {
135
+ const n = S.pick([4, 5, 6]);
136
+ return [add2(star(0.5, 0.5, 0.46, S.between(0.16, 0.24), n))];
137
+ },
138
+ (S, w) => [add2(poly([0.5, 0.06], [0.9, 0.5], [0.5, 0.94], [0.1, 0.5])), cut(poly([0.5, 0.06 + w * 2], [0.9 - w * 2, 0.5], [0.5, 0.94 - w * 2], [0.1 + w * 2, 0.5])), add2(seg(0.5, 0.26, 0.5, 0.74, w))]
139
+ ] },
140
+ vision: { tone: "ink", variants: [
141
+ (S, w) => [add2(disc(0.5, 0.5, 0.46, 0.26)), cut(disc(0.5, 0.5, 0.46 - w, 0.26 - w)), add2(disc(0.5, 0.5, 0.14))]
142
+ ] },
143
+ cloak: { tone: "dim", variants: [
144
+ (S, w) => [add2(disc(0.5, 0.5, 0.46, 0.26)), cut(disc(0.5, 0.5, 0.46 - w, 0.26 - w)), add2(disc(0.5, 0.5, 0.14), seg(0.14, 0.86, 0.86, 0.14, w))]
145
+ ] },
146
+ scan: { tone: "good", variants: [
147
+ (S, w) => [add2(disc(0.5, 0.5, 0.44)), cut(disc(0.5, 0.5, 0.44 - w)), add2(disc(0.5, 0.5, 0.22)), cut(disc(0.5, 0.5, 0.22 - w)), add2(seg(0.5, 0.5, 0.82, 0.2, w), disc(0.5, 0.5, w))]
148
+ ] },
149
+ armor: { tone: "ink", variants: [
150
+ () => [add2(poly([0.14, 0.14], [0.86, 0.14], [0.86, 0.52], [0.5, 0.92], [0.14, 0.52]))],
151
+ (S, w) => [add2(poly([0.14, 0.14], [0.86, 0.14], [0.86, 0.52], [0.5, 0.92], [0.14, 0.52])), cut(seg(0.5, 0.14, 0.5, 0.92, w * 0.8))]
152
+ ] },
153
+ damage: { tone: "bad", variants: [
154
+ (S) => {
155
+ const n = S.pick([7, 8, 9]);
156
+ return [add2(star(0.5, 0.5, 0.48, S.between(0.2, 0.28), n, S.between(0, 1)))];
157
+ }
158
+ ] },
159
+ speed: { tone: "good", variants: [
160
+ (S, w) => [add2(poly([0.08, 0.16], [0.46, 0.5], [0.08, 0.84], [0.22, 0.5])), add2(poly([0.46, 0.16], [0.9, 0.5], [0.46, 0.84], [0.6, 0.5]))]
161
+ ] },
162
+ range: { tone: "accent", variants: [
163
+ (S, w) => [add2(disc(0.5, 0.5, 0.46)), cut(disc(0.5, 0.5, 0.46 - w)), add2(disc(0.5, 0.5, 0.3)), cut(disc(0.5, 0.5, 0.3 - w)), add2(disc(0.5, 0.5, 0.12))]
164
+ ] },
165
+ health: { tone: "good", variants: [
166
+ () => [add2(poly([0.5, 0.9], [0.08, 0.46], [0.08, 0.26], [0.26, 0.1], [0.5, 0.26], [0.74, 0.1], [0.92, 0.26], [0.92, 0.46]))],
167
+ (S) => {
168
+ const t = S.between(0.14, 0.18);
169
+ return [add2(rect(0.5 - t, 0.12, 0.5 + t, 0.88), rect(0.12, 0.5 - t, 0.88, 0.5 + t))];
170
+ }
171
+ ] },
172
+ timer: { tone: "ink", variants: [
173
+ (S, w) => [add2(disc(0.5, 0.54, 0.4)), cut(disc(0.5, 0.54, 0.4 - w)), add2(seg(0.5, 0.54, 0.5, 0.3, w), seg(0.5, 0.54, 0.68, 0.62, w), rect(0.4, 0.04, 0.6, 0.12))]
174
+ ] },
175
+ // (Three bars, never so heavy they run together: each at most a sixth of the square.)
176
+ menu: { tone: "ink", variants: [(S, w0) => {
177
+ const w = Math.min(w0, 0.12);
178
+ return [add2(rect(0.14, 0.16, 0.86, 0.16 + w * 1.4), rect(0.14, 0.5 - w * 0.7, 0.86, 0.5 + w * 0.7), rect(0.14, 0.84 - w * 1.4, 0.86, 0.84))];
179
+ }] },
180
+ settings: { tone: "ink", variants: [(S, w) => [add2(gear(0.5, 0.5, 0.46, 8, 0.12)), cut(disc(0.5, 0.5, 0.16))]] },
181
+ alert: { tone: "warn", variants: [(S, w) => [add2(poly([0.5, 0.06], [0.95, 0.9], [0.05, 0.9])), cut(seg(0.5, 0.34, 0.5, 0.62, w * 1.2), disc(0.5, 0.76, w * 0.7))]] },
182
+ worker: { tone: "warn", variants: [
183
+ (S) => [add2(disc(0.5, 0.6, 0.38)), cut(rect(0, 0.62, 1, 1)), add2(rect(0.06, 0.58, 0.94, 0.7), rect(0.42, 0.14, 0.58, 0.26))],
184
+ (S, w) => [add2(seg(0.22, 0.88, 0.62, 0.36, w * 1.3)), add2(...strokes([[0.18, 0.3], [0.48, 0.14], [0.66, 0.2], [0.84, 0.44]], w * 1.5))]
185
+ ] },
186
+ unload: { tone: "ink", variants: [(S, w) => [add2(rect(0.12, 0.62, 0.88, 0.9), seg(0.5, 0.08, 0.5, 0.44, w * 1.5), arrowHead(0.5, 0.58, 0, 1, 0.22))]] },
187
+ load: { tone: "ink", variants: [(S, w) => [add2(rect(0.12, 0.62, 0.88, 0.9), seg(0.5, 0.22, 0.5, 0.58, w * 1.5), arrowHead(0.5, 0.06, 0, -1, 0.22))]] },
188
+ "attack-move": { tone: "bad", variants: [
189
+ (S, w) => [...sword(S, w * 0.9, false).map((o) => ({ ...o, shape: o.shape.map((c) => c.map((v, i) => i % 2 ? v * 0.72 : v * 0.72 + 0.28)) })), add2(seg(0.1, 0.9, 0.34, 0.66, w * 1.2), arrowHead(0.08, 0.92, -1, 1, 0.16))]
190
+ ] },
191
+ crystal: { tone: "accent", variants: [
192
+ () => [add2(poly([0.3, 0.9], [0.22, 0.4], [0.36, 0.12], [0.5, 0.4], [0.46, 0.9]), poly([0.5, 0.9], [0.56, 0.3], [0.7, 0.06], [0.82, 0.32], [0.76, 0.9]))]
193
+ ] },
194
+ flux: { tone: "accent", variants: [
195
+ (S, w) => [add2(disc(0.5, 0.5, 0.24), disc(0.5, 0.5, 0.46, 0.18)), cut(disc(0.5, 0.5, 0.46 - w, 0.18 - w)), add2(disc(0.5, 0.5, 0.24))]
196
+ ] },
197
+ pause: { tone: "ink", variants: [(S) => [add2(rect(0.2, 0.14, 0.42, 0.86), rect(0.58, 0.14, 0.8, 0.86))]] },
198
+ play: { tone: "ink", variants: [() => [add2(poly([0.2, 0.1], [0.86, 0.5], [0.2, 0.9]))]] },
199
+ close: { tone: "ink", variants: [(S, w) => [add2(seg(0.2, 0.2, 0.8, 0.8, w * 1.5), seg(0.8, 0.2, 0.2, 0.8, w * 1.5))]] },
200
+ check: { tone: "good", variants: [(S, w) => [add2(...strokes([[0.14, 0.52], [0.4, 0.78], [0.86, 0.22]], w * 1.6))]] },
201
+ chat: { tone: "ink", variants: [() => [add2(rect(0.1, 0.14, 0.9, 0.66), poly([0.26, 0.6], [0.5, 0.6], [0.22, 0.9]))]] },
202
+ ping: { tone: "warn", variants: [(S, w) => [add2(disc(0.5, 0.4, 0.3), poly([0.24, 0.5], [0.5, 0.94], [0.76, 0.5])), cut(disc(0.5, 0.4, 0.12))]] }
203
+ };
204
+ var ICON_NAMES = Object.keys(ICON_RECIPES);
205
+
206
+ // packages/ui/src/node.ts
207
+ var WIDGETS = [
208
+ "root",
209
+ "canvas",
210
+ "row",
211
+ "col",
212
+ "grid",
213
+ "panel",
214
+ "button",
215
+ "label",
216
+ "icon",
217
+ "bar",
218
+ "list",
219
+ "tooltip",
220
+ "minimap",
221
+ "portrait",
222
+ "tabs",
223
+ "toast",
224
+ "modal",
225
+ "slider",
226
+ "toggle",
227
+ "spinner",
228
+ "spacer",
229
+ "image",
230
+ "driving"
231
+ ];
232
+ var DRIVING_KINDS = ["wheel", "accelerator", "brake", "handbrake", "boost", "speedometer", "tachometer", "combined", "shift-up", "shift-down"];
233
+ var DRIVING_VARIANTS = ["touring", "track"];
234
+ var ANCHORS = ["tl", "t", "tr", "l", "c", "r", "bl", "b", "br"];
235
+
236
+ // packages/ui/src/driving.ts
237
+ var TAU2 = Math.PI * 2;
238
+
239
+ // packages/ui/src/gauges.ts
240
+ var GLYPH_BYTES = 128 * 1024;
241
+
242
+ // packages/ui/src/prompts.ts
243
+ var DEFAULT = { face: rgba(26, 32, 52), rim: rgba(150, 170, 210), ink: rgba(240, 244, 255), lit: rgba(255, 190, 70) };
244
+
245
+ // packages/codec/src/bits.ts
246
+ var F2 = new DataView(new ArrayBuffer(8));
247
+ var P32 = 2 ** 32;
248
+ var BitError = class extends RangeError {
249
+ bit;
250
+ constructor(message, bit) {
251
+ super(message);
252
+ this.name = "BitError";
253
+ this.bit = bit;
254
+ }
255
+ };
256
+ function bitsFor(n) {
257
+ if (n <= 1) return 0;
258
+ if (n <= 4294967296) return 32 - Math.clz32(n - 1);
259
+ let b = 32;
260
+ let v = Math.floor((n - 1) / 4294967296);
261
+ while (v >= 1) {
262
+ v = Math.floor(v / 2);
263
+ b += 1;
264
+ }
265
+ return b;
266
+ }
267
+ var lengthOf = (x) => x < 4294967296 ? 32 - Math.clz32(x) : 32 + lengthOf(Math.floor(x / 4294967296));
268
+ function toHalf(v) {
269
+ F2.setFloat32(0, v);
270
+ const x = F2.getUint32(0);
271
+ const sign = x >>> 16 & 32768;
272
+ const exp = x >>> 23 & 255;
273
+ let mant = x & 8388607;
274
+ if (exp === 255) return sign | 31744 | (mant ? 512 : 0);
275
+ const e = exp - 127 + 15;
276
+ if (e >= 31) return sign | 31744;
277
+ if (e <= 0) {
278
+ if (e < -10) return sign;
279
+ mant |= 8388608;
280
+ const shift = 14 - e;
281
+ let h2 = mant >>> shift;
282
+ const rem2 = mant & (1 << shift) - 1;
283
+ const half = 1 << shift - 1;
284
+ if (rem2 > half || rem2 === half && h2 & 1) h2 += 1;
285
+ return sign | h2;
286
+ }
287
+ let h = e << 10 | mant >>> 13;
288
+ const rem = mant & 8191;
289
+ if (rem > 4096 || rem === 4096 && h & 1) h += 1;
290
+ return sign | h;
291
+ }
292
+ function fromHalf(h) {
293
+ const sign = h & 32768 ? -1 : 1;
294
+ const exp = h >>> 10 & 31;
295
+ const mant = h & 1023;
296
+ if (exp === 0) return sign * mant * 2 ** -24;
297
+ if (exp === 31) return mant ? NaN : sign * Infinity;
298
+ return sign * (1 + mant / 1024) * 2 ** (exp - 15);
299
+ }
300
+ var BitWriter = class {
301
+ buf;
302
+ pos = 0;
303
+ bit = 0;
304
+ constructor(capacity = 256) {
305
+ this.buf = new Uint8Array(Math.max(16, capacity));
306
+ }
307
+ /** Bits written so far. */
308
+ get length() {
309
+ return this.pos * 8 + this.bit;
310
+ }
311
+ room(bytes2) {
312
+ if (this.pos + bytes2 < this.buf.length) return;
313
+ let n = this.buf.length * 2;
314
+ while (n <= this.pos + bytes2) n *= 2;
315
+ const next = new Uint8Array(n);
316
+ next.set(this.buf.subarray(0, this.pos + 1));
317
+ this.buf = next;
318
+ }
319
+ /** Write the low `n` bits of `v` (0 <= n <= 32; v an unsigned integer below 2^n). */
320
+ bits(v, n) {
321
+ if (n === 0) return;
322
+ this.room(5);
323
+ const buf = this.buf;
324
+ let pos = this.pos;
325
+ let bit = this.bit;
326
+ while (n > 0) {
327
+ const free = 8 - bit;
328
+ if (n >= free) {
329
+ n -= free;
330
+ buf[pos] = buf[pos] | v >>> n & (1 << free) - 1;
331
+ pos += 1;
332
+ bit = 0;
333
+ } else {
334
+ buf[pos] = buf[pos] | (v & (1 << n) - 1) << free - n;
335
+ bit += n;
336
+ n = 0;
337
+ }
338
+ }
339
+ this.pos = pos;
340
+ this.bit = bit;
341
+ }
342
+ /** Up to 53 bits. */
343
+ wide(v, n) {
344
+ if (n <= 32) {
345
+ this.bits(v >>> 0, n);
346
+ return;
347
+ }
348
+ const hi = Math.floor(v / P32);
349
+ this.bits(hi, n - 32);
350
+ this.bits(v >>> 0, 32);
351
+ }
352
+ bool(b) {
353
+ this.bits(b ? 1 : 0, 1);
354
+ }
355
+ /** A bigint's low `n` bits. */
356
+ big(v, n) {
357
+ let left = n;
358
+ while (left > 32) {
359
+ left -= 32;
360
+ this.bits(Number(v >> BigInt(left) & 0xffffffffn), 32);
361
+ }
362
+ this.bits(Number(v & (1n << BigInt(left)) - 1n), left);
363
+ }
364
+ /** Exp-Golomb of order k (k = 0: Elias-gamma of v + 1): small numbers in few bits, any size up to 2^53. */
365
+ golomb(v, k) {
366
+ const x = v + (k < 31 ? 1 << k : 2 ** k);
367
+ const len2 = lengthOf(x);
368
+ const zeros = len2 - 1 - k;
369
+ if (zeros > 0) {
370
+ this.room((zeros >>> 3) + 6);
371
+ const at = this.pos * 8 + this.bit + zeros;
372
+ this.pos = at >>> 3;
373
+ this.bit = at & 7;
374
+ }
375
+ if (len2 <= 32) this.bits(x >>> 0, len2);
376
+ else this.wide(x, len2);
377
+ }
378
+ /** LEB-style groups: `g` bits of the number then a "more" bit, least significant group first. */
379
+ groups(v, g) {
380
+ const span = 2 ** g;
381
+ do {
382
+ const part = v % span;
383
+ v = Math.floor(v / span);
384
+ this.bits(part, g);
385
+ this.bool(v > 0);
386
+ } while (v > 0);
387
+ }
388
+ f16(v) {
389
+ this.bits(toHalf(v), 16);
390
+ }
391
+ f32(v) {
392
+ F2.setFloat32(0, v);
393
+ this.bits(F2.getUint32(0), 32);
394
+ }
395
+ f64(v) {
396
+ F2.setFloat64(0, v);
397
+ this.bits(F2.getUint32(0), 32);
398
+ this.bits(F2.getUint32(4), 32);
399
+ }
400
+ /** Raw bytes (a fast copy when the stream is on a byte boundary). */
401
+ bytes(b) {
402
+ if (this.bit === 0) {
403
+ this.room(b.length + 1);
404
+ this.buf.set(b, this.pos);
405
+ this.pos += b.length;
406
+ return;
407
+ }
408
+ for (let i = 0; i < b.length; i += 1) this.bits(b[i], 8);
409
+ }
410
+ /** Another writer's bits, appended. */
411
+ append(other) {
412
+ const n = other.length;
413
+ const src = other.buf;
414
+ const full = n >>> 3;
415
+ if (this.bit === 0) {
416
+ this.room(full + 2);
417
+ this.buf.set(src.subarray(0, full), this.pos);
418
+ this.pos += full;
419
+ } else for (let i = 0; i < full; i += 1) this.bits(src[i], 8);
420
+ const rest = n & 7;
421
+ if (rest) this.bits(src[full] >>> 8 - rest, rest);
422
+ }
423
+ /** Pad with zero bits to the next byte. */
424
+ align() {
425
+ if (this.bit) {
426
+ this.pos += 1;
427
+ this.bit = 0;
428
+ this.room(1);
429
+ }
430
+ }
431
+ /** The bytes (a copy), zero-padded to a whole byte. */
432
+ finish() {
433
+ return this.buf.slice(0, this.pos + (this.bit ? 1 : 0));
434
+ }
435
+ /** Empty it for reuse (keeps its buffer). */
436
+ reset() {
437
+ this.buf.fill(0, 0, this.pos + 1);
438
+ this.pos = 0;
439
+ this.bit = 0;
440
+ }
441
+ };
442
+
443
+ // packages/codec/src/schema.ts
444
+ var SchemaError = class extends TypeError {
445
+ constructor(message) {
446
+ super(message);
447
+ this.name = "SchemaError";
448
+ }
449
+ };
450
+ var bad = (why) => {
451
+ throw new SchemaError(why);
452
+ };
453
+ var whole = (v, lo, hi, what) => {
454
+ if (!Number.isInteger(v) || v < lo || v > hi) bad(`${what} must be a whole number in ${lo}..${hi} (got ${v}).`);
455
+ return v;
456
+ };
457
+ var node = (n) => Object.freeze(n);
458
+ var asNode = (t) => t;
459
+ var uint = (bits) => node({ kind: "uint", bits: whole(bits, 1, 53, "uint bits") });
460
+ var int = (bits) => node({ kind: "int", bits: whole(bits, 2, 53, "int bits") });
461
+ var bool = () => node({ kind: "bool" });
462
+ function fixed(min, max, step, { off = "round", k = -1, delta: delta2 = false } = {}) {
463
+ if (![min, max, step].every(Number.isFinite)) bad("fixed(min, max, step) takes finite numbers.");
464
+ if (!(step > 0)) bad(`fixed step must be positive (got ${step}).`);
465
+ if (!(max > min)) bad(`fixed max must be above min (got ${min}..${max}).`);
466
+ const steps = Math.round((max - min) / step);
467
+ if (steps > 2 ** 52) bad(`fixed(${min}, ${max}, ${step}) has more than 2^52 steps.`);
468
+ if (!["round", "strict", "exact"].includes(off)) bad(`fixed off must be "round", "strict" or "exact" (got ${off}).`);
469
+ if (delta2 && k < 0) bad("fixed delta needs a Golomb k (the differences are Golomb-coded).");
470
+ return node({ kind: "fixed", min, max, step, off, k: whole(k, -1, 31, "fixed k"), delta: delta2 });
471
+ }
472
+ var varuint = ({ k = 0, group = 0 } = {}) => node({ kind: "varuint", k: whole(k, 0, 31, "varuint k"), group: whole(group, 0, 31, "varuint group") });
473
+ var varint = ({ k = 0, group = 0 } = {}) => node({ kind: "varint", k: whole(k, 0, 31, "varint k"), group: whole(group, 0, 31, "varint group") });
474
+ var num = () => node({ kind: "num" });
475
+ function enumOf(values, { capacity = 0, open = false, other = false } = {}) {
476
+ if (!values.length) bad("An enum needs values.");
477
+ const seen = /* @__PURE__ */ new Set();
478
+ for (const v of values) {
479
+ const key = `${typeof v}:${String(v)}`;
480
+ if (!["string", "number", "boolean"].includes(typeof v)) bad(`Enum values are strings, numbers or booleans (got ${typeof v}).`);
481
+ if (seen.has(key)) bad(`Enum value ${JSON.stringify(v)} is listed twice.`);
482
+ seen.add(key);
483
+ }
484
+ if (capacity && capacity < values.length) bad(`Enum capacity ${capacity} is below its ${values.length} values.`);
485
+ return node({ kind: "enum", values: Object.freeze([...values]), capacity: whole(capacity, 0, 2 ** 32, "enum capacity"), open, other });
486
+ }
487
+ var string = ({ max = 0, packHex = false } = {}) => node({ kind: "string", max: whole(max, 0, 2 ** 32, "string max"), packHex });
488
+ var ref = (table = "str", { packHex = false } = {}) => node({ kind: "ref", table: table || bad("ref needs a table name."), packHex });
489
+ var bytes = ({ length = 0 } = {}) => node({ kind: "bytes", length: whole(length, 0, 2 ** 32, "bytes length") });
490
+ var dyn = () => node({ kind: "dyn" });
491
+ function array(of, { length = 0, max = 0 } = {}) {
492
+ if (length && max) bad("An array has a fixed length or a max, not both.");
493
+ return node({ kind: "array", of: asNode(of), length: whole(length, 0, 2 ** 32, "array length"), max: whole(max, 0, 2 ** 32, "array max") });
494
+ }
495
+ var optional = (of) => node({ kind: "optional", of: asNode(of), optional: true });
496
+ var fieldsOf = (fields, what) => {
497
+ const out = [];
498
+ for (const [name, type] of Object.entries(fields)) {
499
+ if (!name) bad(`${what}: a field needs a name.`);
500
+ if (!type || typeof type.kind !== "string") bad(`${what}: field ${name} is not a schema.`);
501
+ out.push(Object.freeze({ name, type: asNode(type) }));
502
+ }
503
+ return out;
504
+ };
505
+ function struct(fields, { open = false } = {}) {
506
+ return node({ kind: "struct", fields: Object.freeze(fieldsOf(fields, "struct")), open, ext: Object.freeze([]) });
507
+ }
508
+
509
+ export {
510
+ ANCHORS,
511
+ BitError,
512
+ BitWriter,
513
+ DRIVING_KINDS,
514
+ DRIVING_VARIANTS,
515
+ SchemaError,
516
+ WIDGETS,
517
+ array,
518
+ asNode,
519
+ bad,
520
+ bitsFor,
521
+ bool,
522
+ bytes,
523
+ dyn,
524
+ enumOf,
525
+ fieldsOf,
526
+ fixed,
527
+ fromHalf,
528
+ int,
529
+ node,
530
+ num,
531
+ optional,
532
+ ref,
533
+ string,
534
+ struct,
535
+ toHalf,
536
+ uint,
537
+ varint,
538
+ varuint,
539
+ whole,
540
+ };