dualsense-ts 6.2.0 → 6.4.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/LINUX_HID.md +85 -0
- package/README.md +83 -12
- package/dist/dualsense.d.ts +28 -8
- package/dist/dualsense.d.ts.map +1 -1
- package/dist/dualsense.js +57 -17
- package/dist/dualsense.js.map +1 -1
- package/dist/hid/bt_checksum.d.ts +7 -0
- package/dist/hid/bt_checksum.d.ts.map +1 -1
- package/dist/hid/bt_checksum.js +33 -1
- package/dist/hid/bt_checksum.js.map +1 -1
- package/dist/hid/dualsense_hid.d.ts +77 -0
- package/dist/hid/dualsense_hid.d.ts.map +1 -1
- package/dist/hid/dualsense_hid.js +193 -0
- package/dist/hid/dualsense_hid.js.map +1 -1
- package/dist/hid/factory_info.d.ts +53 -0
- package/dist/hid/factory_info.d.ts.map +1 -0
- package/dist/hid/factory_info.js +166 -0
- package/dist/hid/factory_info.js.map +1 -0
- package/dist/hid/firmware_info.d.ts +46 -0
- package/dist/hid/firmware_info.d.ts.map +1 -0
- package/dist/hid/firmware_info.js +109 -0
- package/dist/hid/firmware_info.js.map +1 -0
- package/dist/hid/hid_provider.d.ts +12 -0
- package/dist/hid/hid_provider.d.ts.map +1 -1
- package/dist/hid/hid_provider.js +13 -0
- package/dist/hid/hid_provider.js.map +1 -1
- package/dist/hid/index.d.ts +3 -0
- package/dist/hid/index.d.ts.map +1 -1
- package/dist/hid/index.js +3 -0
- package/dist/hid/index.js.map +1 -1
- package/dist/hid/node_hid_provider.d.ts +2 -0
- package/dist/hid/node_hid_provider.d.ts.map +1 -1
- package/dist/hid/node_hid_provider.js +14 -0
- package/dist/hid/node_hid_provider.js.map +1 -1
- package/dist/hid/pairing_info.d.ts +9 -0
- package/dist/hid/pairing_info.d.ts.map +1 -0
- package/dist/hid/pairing_info.js +33 -0
- package/dist/hid/pairing_info.js.map +1 -0
- package/dist/hid/web_hid_provider.d.ts +14 -0
- package/dist/hid/web_hid_provider.d.ts.map +1 -1
- package/dist/hid/web_hid_provider.js +79 -8
- package/dist/hid/web_hid_provider.js.map +1 -1
- package/dist/id.d.ts +4 -0
- package/dist/id.d.ts.map +1 -1
- package/dist/manager.d.ts +57 -4
- package/dist/manager.d.ts.map +1 -1
- package/dist/manager.js +248 -66
- package/dist/manager.js.map +1 -1
- package/nodehid_example/debug.ts +43 -13
- package/nodehid_example/single.ts +29 -0
- package/package.json +1 -1
- package/src/dualsense.ts +73 -23
- package/src/hid/bt_checksum.ts +39 -0
- package/src/hid/dualsense_hid.ts +230 -0
- package/src/hid/factory_info.ts +206 -0
- package/src/hid/firmware_info.ts +157 -0
- package/src/hid/hid_provider.ts +22 -0
- package/src/hid/index.ts +3 -0
- package/src/hid/node_hid_provider.ts +14 -0
- package/src/hid/pairing_info.ts +33 -0
- package/src/hid/web_hid_provider.ts +87 -8
- package/src/id.ts +5 -0
- package/src/manager.ts +285 -71
- package/webhid_example/build/asset-manifest.json +3 -3
- package/webhid_example/build/index.html +1 -1
- package/webhid_example/build/static/js/main.1c1a2c23.js +3 -0
- package/webhid_example/build/static/js/main.1c1a2c23.js.map +1 -0
- package/webhid_example/src/App.tsx +7 -1
- package/webhid_example/src/hud/AudioIndicator.tsx +116 -0
- package/webhid_example/src/hud/BatteryIndicator.tsx +4 -2
- package/webhid_example/src/hud/ColorIndicator.tsx +72 -0
- package/webhid_example/src/hud/ControllerConnection.tsx +29 -2
- package/webhid_example/src/hud/Debugger.tsx +31 -1
- package/webhid_example/src/hud/LightbarFadeButtons.tsx +2 -2
- package/webhid_example/src/hud/MuteLedControls.tsx +3 -2
- package/webhid_example/src/hud/index.tsx +2 -0
- package/webhid_example/build/static/js/main.2ac31d24.js +0 -3
- package/webhid_example/build/static/js/main.2ac31d24.js.map +0 -1
- /package/webhid_example/build/static/js/{main.2ac31d24.js.LICENSE.txt → main.1c1a2c23.js.LICENSE.txt} +0 -0
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.WebHIDProvider = void 0;
|
|
4
4
|
const hid_provider_1 = require("./hid_provider");
|
|
5
|
+
const bt_checksum_1 = require("./bt_checksum");
|
|
5
6
|
class WebHIDProvider extends hid_provider_1.HIDProvider {
|
|
6
7
|
constructor(options = {}) {
|
|
7
8
|
super();
|
|
@@ -11,7 +12,8 @@ class WebHIDProvider extends hid_provider_1.HIDProvider {
|
|
|
11
12
|
this.targetDevice = options.device;
|
|
12
13
|
navigator.hid.addEventListener("disconnect", ({ device }) => {
|
|
13
14
|
if (device === this.device) {
|
|
14
|
-
this.device
|
|
15
|
+
// Let disconnect() → reset() handle nulling this.device so that
|
|
16
|
+
// reset() can detect the device was attached and fire onDisconnect.
|
|
15
17
|
this.disconnect();
|
|
16
18
|
}
|
|
17
19
|
});
|
|
@@ -66,15 +68,11 @@ class WebHIDProvider extends hid_provider_1.HIDProvider {
|
|
|
66
68
|
}
|
|
67
69
|
attach(device) {
|
|
68
70
|
const key = WebHIDProvider.deviceKey(device);
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
device
|
|
73
|
-
.open()
|
|
71
|
+
const openPromise = device.opened ? Promise.resolve() : device.open();
|
|
72
|
+
openPromise
|
|
74
73
|
.then(() => {
|
|
75
74
|
this.device = device;
|
|
76
75
|
this.deviceId = key;
|
|
77
|
-
hid_provider_1.HIDProvider.claimedDevices.add(key);
|
|
78
76
|
this.detectConnectionType();
|
|
79
77
|
// Enable accelerometer, gyro, touchpad
|
|
80
78
|
return this.device.receiveFeatureReport(0x05);
|
|
@@ -86,12 +84,36 @@ class WebHIDProvider extends hid_provider_1.HIDProvider {
|
|
|
86
84
|
this.buffer = data;
|
|
87
85
|
this.onData(this.process({ reportId, buffer: data }));
|
|
88
86
|
});
|
|
87
|
+
this.onConnect();
|
|
89
88
|
})
|
|
90
89
|
.catch((err) => {
|
|
91
90
|
this.onError(err);
|
|
92
91
|
this.disconnect();
|
|
93
92
|
});
|
|
94
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Detach the current HIDDevice (if any) and attach a different one in place.
|
|
96
|
+
* Used by the manager to transplant a freshly-discovered device into an
|
|
97
|
+
* existing slot's provider after identity matching, so the consumer's
|
|
98
|
+
* Dualsense reference survives reconnection.
|
|
99
|
+
*
|
|
100
|
+
* The new device must already be open (or openable) — we close the old one,
|
|
101
|
+
* release its claim, and run the standard attach() flow on the new one.
|
|
102
|
+
*/
|
|
103
|
+
replaceDevice(device) {
|
|
104
|
+
// Tear down the existing device without firing the disconnect cascade
|
|
105
|
+
// (we don't want subscribers to see a disconnect/reconnect blip).
|
|
106
|
+
if (this.device) {
|
|
107
|
+
const old = this.device;
|
|
108
|
+
const oldKey = this.deviceId;
|
|
109
|
+
this.device = undefined;
|
|
110
|
+
if (oldKey)
|
|
111
|
+
hid_provider_1.HIDProvider.claimedDevices.delete(oldKey);
|
|
112
|
+
// Best-effort close; failures are non-fatal.
|
|
113
|
+
old.close().catch(() => { });
|
|
114
|
+
}
|
|
115
|
+
this.attach(device);
|
|
116
|
+
}
|
|
95
117
|
/**
|
|
96
118
|
* You need to get HID device permissions from an interactive
|
|
97
119
|
* component, like a button. This returns a callback for triggering
|
|
@@ -157,12 +179,61 @@ class WebHIDProvider extends hid_provider_1.HIDProvider {
|
|
|
157
179
|
}
|
|
158
180
|
disconnect() {
|
|
159
181
|
if (this.device) {
|
|
160
|
-
|
|
182
|
+
const dev = this.device;
|
|
183
|
+
// Reset synchronously so claimedDevices is freed immediately —
|
|
184
|
+
// otherwise a rapid disconnect/reconnect can race: the browser's
|
|
185
|
+
// connect event arrives before close() resolves, and attach() sees
|
|
186
|
+
// the key still claimed and silently bails out.
|
|
187
|
+
this.reset();
|
|
188
|
+
dev.close().catch(() => { });
|
|
161
189
|
}
|
|
162
190
|
else {
|
|
163
191
|
this.reset();
|
|
164
192
|
}
|
|
165
193
|
}
|
|
194
|
+
async readFeatureReport(reportId) {
|
|
195
|
+
if (!this.device)
|
|
196
|
+
throw new Error("No device connected");
|
|
197
|
+
const view = await this.device.receiveFeatureReport(reportId);
|
|
198
|
+
return new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
|
|
199
|
+
}
|
|
200
|
+
async sendFeatureReport(reportId, data) {
|
|
201
|
+
if (!this.device)
|
|
202
|
+
return;
|
|
203
|
+
// WebHID sendFeatureReport takes the report ID separately.
|
|
204
|
+
// data[0] is the report ID (for node-hid compat); strip it for WebHID.
|
|
205
|
+
const rawPayload = data.slice(1);
|
|
206
|
+
// Pad to the expected payload length from the HID descriptor
|
|
207
|
+
const expectedLength = this.getFeatureReportLength(reportId);
|
|
208
|
+
const payload = expectedLength > 0 && rawPayload.length < expectedLength
|
|
209
|
+
? new Uint8Array(expectedLength)
|
|
210
|
+
: new Uint8Array(rawPayload);
|
|
211
|
+
if (expectedLength > rawPayload.length) {
|
|
212
|
+
payload.set(rawPayload);
|
|
213
|
+
}
|
|
214
|
+
// Bluetooth requires CRC-32 in the last 4 bytes of the payload
|
|
215
|
+
if (this.wireless) {
|
|
216
|
+
const crc = (0, bt_checksum_1.computeFeatureReportChecksum)(reportId, payload);
|
|
217
|
+
const off = payload.length - 4;
|
|
218
|
+
payload[off] = crc & 0xff;
|
|
219
|
+
payload[off + 1] = (crc >>> 8) & 0xff;
|
|
220
|
+
payload[off + 2] = (crc >>> 16) & 0xff;
|
|
221
|
+
payload[off + 3] = (crc >>> 24) & 0xff;
|
|
222
|
+
}
|
|
223
|
+
await this.device.sendFeatureReport(reportId, payload);
|
|
224
|
+
}
|
|
225
|
+
/** Query the HID descriptor for the expected payload length of a feature report */
|
|
226
|
+
getFeatureReportLength(reportId) {
|
|
227
|
+
if (!this.device)
|
|
228
|
+
return 0;
|
|
229
|
+
for (const c of this.device.collections) {
|
|
230
|
+
const report = (c.featureReports ?? []).find((r) => r.reportId === reportId);
|
|
231
|
+
if (report) {
|
|
232
|
+
return (report.items ?? []).reduce((sum, item) => sum + Math.ceil(((item.reportSize ?? 0) * (item.reportCount ?? 0)) / 8), 0);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return 0;
|
|
236
|
+
}
|
|
166
237
|
async write(data) {
|
|
167
238
|
if (!this.device)
|
|
168
239
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web_hid_provider.js","sourceRoot":"","sources":["../../src/hid/web_hid_provider.ts"],"names":[],"mappings":";;;AACA,iDAAgE;
|
|
1
|
+
{"version":3,"file":"web_hid_provider.js","sourceRoot":"","sources":["../../src/hid/web_hid_provider.ts"],"names":[],"mappings":"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"}
|
package/dist/id.d.ts
CHANGED
|
@@ -45,6 +45,10 @@ export declare const enum InputId {
|
|
|
45
45
|
BatteryLevel = "BatteryLevel",
|
|
46
46
|
BatteryStatus = "BatteryStatus",
|
|
47
47
|
MuteLed = "MuteLed",
|
|
48
|
+
/** Whether a microphone is connected to the controller */
|
|
49
|
+
Microphone = "Microphone",
|
|
50
|
+
/** Whether headphones are connected to the controller */
|
|
51
|
+
Headphone = "Headphone",
|
|
48
52
|
/** For placeholder inputs */
|
|
49
53
|
Unknown = "Unknown"
|
|
50
54
|
}
|
package/dist/id.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"id.d.ts","sourceRoot":"","sources":["../src/id.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,0BAAkB,OAAO;IACvB,OAAO,YAAY;IACnB,MAAM,WAAW;IACjB,WAAW,gBAAgB;IAC3B,IAAI,SAAS;IACb,uCAAuC;IACvC,MAAM,WAAW;IAEjB,QAAQ,aAAa;IACrB,MAAM,WAAW;IACjB,KAAK,UAAU;IACf,MAAM,WAAW;IAEjB,IAAI,SAAS;IACb,EAAE,OAAO;IACT,IAAI,SAAS;IACb,IAAI,SAAS;IACb,KAAK,UAAU;IAEf,WAAW,gBAAgB;IAE3B,OAAO,YAAY;IACnB,OAAO,YAAY;IACnB,aAAa,kBAAkB;IAC/B,QAAQ,aAAa;IAErB,OAAO,YAAY;IACnB,OAAO,YAAY;IACnB,aAAa,kBAAkB;IAC/B,QAAQ,aAAa;IAErB,gBAAgB,OAAO;IACvB,iBAAiB,OAAO;IAExB,WAAW,OAAO;IAClB,YAAY,OAAO;IACnB,iBAAiB,aAAa;IAC9B,kBAAkB,aAAa;IAE/B,UAAU,OAAO;IACjB,WAAW,OAAO;IAElB,WAAW,OAAO;IAClB,WAAW,OAAO;IAClB,YAAY,OAAO;IACnB,YAAY,OAAO;IAEnB,KAAK,UAAU;IACf,KAAK,UAAU;IACf,KAAK,UAAU;IAEf,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,MAAM,WAAW;IAEjB,YAAY,iBAAiB;IAC7B,aAAa,kBAAkB;IAC/B,OAAO,YAAY;IAEnB,6BAA6B;IAC7B,OAAO,YAAY;CACpB"}
|
|
1
|
+
{"version":3,"file":"id.d.ts","sourceRoot":"","sources":["../src/id.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,0BAAkB,OAAO;IACvB,OAAO,YAAY;IACnB,MAAM,WAAW;IACjB,WAAW,gBAAgB;IAC3B,IAAI,SAAS;IACb,uCAAuC;IACvC,MAAM,WAAW;IAEjB,QAAQ,aAAa;IACrB,MAAM,WAAW;IACjB,KAAK,UAAU;IACf,MAAM,WAAW;IAEjB,IAAI,SAAS;IACb,EAAE,OAAO;IACT,IAAI,SAAS;IACb,IAAI,SAAS;IACb,KAAK,UAAU;IAEf,WAAW,gBAAgB;IAE3B,OAAO,YAAY;IACnB,OAAO,YAAY;IACnB,aAAa,kBAAkB;IAC/B,QAAQ,aAAa;IAErB,OAAO,YAAY;IACnB,OAAO,YAAY;IACnB,aAAa,kBAAkB;IAC/B,QAAQ,aAAa;IAErB,gBAAgB,OAAO;IACvB,iBAAiB,OAAO;IAExB,WAAW,OAAO;IAClB,YAAY,OAAO;IACnB,iBAAiB,aAAa;IAC9B,kBAAkB,aAAa;IAE/B,UAAU,OAAO;IACjB,WAAW,OAAO;IAElB,WAAW,OAAO;IAClB,WAAW,OAAO;IAClB,YAAY,OAAO;IACnB,YAAY,OAAO;IAEnB,KAAK,UAAU;IACf,KAAK,UAAU;IACf,KAAK,UAAU;IAEf,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,MAAM,WAAW;IAEjB,YAAY,iBAAiB;IAC7B,aAAa,kBAAkB;IAC/B,OAAO,YAAY;IAEnB,0DAA0D;IAC1D,UAAU,eAAe;IACzB,yDAAyD;IACzD,SAAS,cAAc;IAEvB,6BAA6B;IAC7B,OAAO,YAAY;CACpB"}
|
package/dist/manager.d.ts
CHANGED
|
@@ -31,15 +31,22 @@ export declare class DualsenseManager extends Input<DualsenseManagerState> {
|
|
|
31
31
|
private readonly playerPatterns;
|
|
32
32
|
/** All controller slots, indexed by slot number */
|
|
33
33
|
private readonly slots;
|
|
34
|
-
/** Map from serial
|
|
34
|
+
/** Map from node-hid serial to slot index — best-effort, used as a fallback */
|
|
35
35
|
private readonly serialToSlot;
|
|
36
|
+
/** Map from canonical hardware identity to slot index — preferred when available */
|
|
37
|
+
private readonly identityToSlot;
|
|
36
38
|
/** Discovery polling timer (Node.js only) */
|
|
37
39
|
private discoveryTimer?;
|
|
38
40
|
/** Whether we're running in a browser environment */
|
|
39
41
|
private readonly isBrowser;
|
|
40
42
|
constructor(params?: DualsenseManagerParams);
|
|
41
43
|
get active(): boolean;
|
|
42
|
-
/**
|
|
44
|
+
/**
|
|
45
|
+
* All managed controller instances (including disconnected ones awaiting
|
|
46
|
+
* reconnection). Excludes provisional slots whose identity is still being
|
|
47
|
+
* resolved — those become visible only after firmware info loads, to
|
|
48
|
+
* avoid surfacing controllers that may be merged into an existing slot.
|
|
49
|
+
*/
|
|
43
50
|
get controllers(): readonly Dualsense[];
|
|
44
51
|
/** Number of managed controllers (including disconnected ones awaiting reconnection) */
|
|
45
52
|
get count(): number;
|
|
@@ -47,6 +54,14 @@ export declare class DualsenseManager extends Input<DualsenseManagerState> {
|
|
|
47
54
|
get(index: number): Dualsense | undefined;
|
|
48
55
|
/** Iterate over all managed controllers */
|
|
49
56
|
[Symbol.iterator](): IterableIterator<Dualsense>;
|
|
57
|
+
/** Slots that are visible to the consumer (i.e. identity has been resolved) */
|
|
58
|
+
private publicSlots;
|
|
59
|
+
/**
|
|
60
|
+
* True while at least one controller has been discovered but is still
|
|
61
|
+
* waiting for firmware info to load. Useful for showing a "connecting"
|
|
62
|
+
* state in the UI without surfacing the unresolved slot itself.
|
|
63
|
+
*/
|
|
64
|
+
get pending(): boolean;
|
|
50
65
|
/**
|
|
51
66
|
* Override the player LED pattern for a given slot index.
|
|
52
67
|
* @param index Slot index (0-based)
|
|
@@ -75,14 +90,52 @@ export declare class DualsenseManager extends Input<DualsenseManagerState> {
|
|
|
75
90
|
* allowing the user to select multiple controllers at once.
|
|
76
91
|
*/
|
|
77
92
|
getRequest(): () => Promise<void>;
|
|
93
|
+
/** Previous state snapshot, for deduplication */
|
|
94
|
+
private lastActive;
|
|
95
|
+
private lastPlayerCount;
|
|
96
|
+
/** Fingerprint of the last published player set (slot indices + connected flags) */
|
|
97
|
+
private lastPlayerKey;
|
|
78
98
|
/** Build a new state snapshot and push it through InputSet */
|
|
79
99
|
private updateState;
|
|
80
|
-
/**
|
|
100
|
+
/**
|
|
101
|
+
* Create a Dualsense instance and register it in a (provisional) slot.
|
|
102
|
+
* The caller is responsible for opening the device on the provider — the
|
|
103
|
+
* manager treats this as the *only* path that opens new devices, so
|
|
104
|
+
* identity matching can run before the slot becomes visible.
|
|
105
|
+
*
|
|
106
|
+
* Note: identity is the sole reconnection key. We do NOT key on node-hid's
|
|
107
|
+
* serialNumber because it's frequently missing or wrong (especially over
|
|
108
|
+
* Bluetooth on Linux). Path is tracked only so we can re-target the same
|
|
109
|
+
* device on transplant.
|
|
110
|
+
*/
|
|
81
111
|
private createSlot;
|
|
112
|
+
/**
|
|
113
|
+
* Called when a slot's HID layer has finished reading firmware/factory info.
|
|
114
|
+
* If the resolved identity matches a *different* (disconnected) slot, the
|
|
115
|
+
* underlying device is transplanted into that slot's existing provider so
|
|
116
|
+
* the consumer's Dualsense reference is preserved across reconnect.
|
|
117
|
+
*/
|
|
118
|
+
private handleSlotReady;
|
|
119
|
+
/** Mark a slot as visible to consumers and publish state */
|
|
120
|
+
private promoteSlot;
|
|
121
|
+
/**
|
|
122
|
+
* Move the device handle from `from` into `into`'s existing provider so
|
|
123
|
+
* the existing Dualsense instance reconnects in place. Then remove `from`.
|
|
124
|
+
*/
|
|
125
|
+
private transplant;
|
|
126
|
+
/** Remove a slot without firing the player-LED reshuffle */
|
|
127
|
+
private dropSlot;
|
|
82
128
|
private startNodeDiscovery;
|
|
83
|
-
/**
|
|
129
|
+
/**
|
|
130
|
+
* Handle a newly discovered device from enumeration. Opens the device on
|
|
131
|
+
* a fresh provider, which adds it to `claimedDevices` so subsequent polls
|
|
132
|
+
* skip it. Identity matching (and any merge into a disconnected slot)
|
|
133
|
+
* happens later, once firmware info has been read.
|
|
134
|
+
*/
|
|
84
135
|
private processDiscoveredDevice;
|
|
85
136
|
private startWebDiscovery;
|
|
137
|
+
/** HIDDevice objects we've already handed to a provider */
|
|
138
|
+
private readonly knownWebDevices;
|
|
86
139
|
private addWebDevice;
|
|
87
140
|
}
|
|
88
141
|
//# sourceMappingURL=manager.d.ts.map
|
package/dist/manager.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../src/manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,KAAK,EAAY,WAAW,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../src/manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,KAAK,EAAY,WAAW,EAAE,MAAM,SAAS,CAAC;AAmCvD,mEAAmE;AACnE,MAAM,WAAW,qBAAqB;IACpC,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CACzC;AA4CD,wCAAwC;AACxC,MAAM,WAAW,sBAAuB,SAAQ,WAAW;IACzD,kFAAkF;IAClF,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yEAAyE;IACzE,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;;;;;;GAOG;AACH,qBAAa,gBAAiB,SAAQ,KAAK,CAAC,qBAAqB,CAAC;IAChE,yDAAyD;IAClD,KAAK,EAAE,qBAAqB,CAGjC;IAEF,+DAA+D;IACxD,oBAAoB,EAAE,OAAO,CAAC;IAErC,gEAAgE;IAChE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA0C;IAEzE,mDAAmD;IACnD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAwB;IAE9C,+EAA+E;IAC/E,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA6B;IAE1D,oFAAoF;IACpF,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6B;IAE5D,6CAA6C;IAC7C,OAAO,CAAC,cAAc,CAAC,CAAiC;IAExD,qDAAqD;IACrD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0C;gBAExD,MAAM,GAAE,sBAA2B;IAgB/C,IAAW,MAAM,IAAI,OAAO,CAE3B;IAED;;;;;OAKG;IACH,IAAW,WAAW,IAAI,SAAS,SAAS,EAAE,CAE7C;IAED,wFAAwF;IACxF,IAAW,KAAK,IAAI,MAAM,CAEzB;IAED,qCAAqC;IAC9B,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAMhD,2CAA2C;IAC3C,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC,SAAS,CAAC;IAIhD,+EAA+E;IAC/E,OAAO,CAAC,WAAW;IAInB;;;;OAIG;IACH,IAAW,OAAO,IAAI,OAAO,CAE5B;IAED;;;;OAIG;IACI,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAU7D,wDAAwD;IACjD,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAI9C;;;;OAIG;IACI,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAqCnC;;;OAGG;IACI,mBAAmB,IAAI,IAAI;IASlC;;OAEG;IACI,OAAO,IAAI,IAAI;IAYtB;;;OAGG;IACI,UAAU,IAAI,MAAM,OAAO,CAAC,IAAI,CAAC;IAYxC,iDAAiD;IACjD,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,eAAe,CAAK;IAC5B,oFAAoF;IACpF,OAAO,CAAC,aAAa,CAAM;IAE3B,8DAA8D;IAC9D,OAAO,CAAC,WAAW;IA4BnB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,UAAU;IAuDlB;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IAoDvB,4DAA4D;IAC5D,OAAO,CAAC,WAAW;IASnB;;;OAGG;IACH,OAAO,CAAC,UAAU;IA8ClB,4DAA4D;IAC5D,OAAO,CAAC,QAAQ;IAsBhB,OAAO,CAAC,kBAAkB;IAkB1B;;;;;OAKG;IACH,OAAO,CAAC,uBAAuB;IAmB/B,OAAO,CAAC,iBAAiB;IAsBzB,2DAA2D;IAC3D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA4B;IAE5D,OAAO,CAAC,YAAY;CAWrB"}
|