kvozy 0.0.1 → 0.2.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/README.md +52 -90
- package/__compiled__/cjs/src/bindValue.d.ts +2 -0
- package/__compiled__/cjs/src/bindValue.js +26 -2
- package/__compiled__/cjs/src/bindValue.js.map +1 -1
- package/__compiled__/esm/src/bindValue.d.mts +2 -0
- package/__compiled__/esm/src/bindValue.mjs +26 -2
- package/__compiled__/esm/src/bindValue.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,9 +14,11 @@ This architecture makes it easy to add connectors for other frameworks (Vue, Sve
|
|
|
14
14
|
## Features
|
|
15
15
|
|
|
16
16
|
- Framework-agnostic core (bindValue)
|
|
17
|
+
- Flexible storage support (localStorage, sessionStorage, in-memory)
|
|
18
|
+
- Graceful fallback to in-memory storage when storage is unavailable
|
|
17
19
|
- Thin React integration (useStorage)
|
|
18
20
|
- String-only values (simple, predictable)
|
|
19
|
-
- Real localStorage
|
|
21
|
+
- Real localStorage/backend storage
|
|
20
22
|
- Subscription-based reactivity
|
|
21
23
|
- TypeScript support
|
|
22
24
|
- Easy to extend to other frameworks
|
|
@@ -29,6 +31,8 @@ npm install kvozy
|
|
|
29
31
|
|
|
30
32
|
## Quick Start
|
|
31
33
|
|
|
34
|
+
> ⚠️ **Note:** `bindValue` is an internal API. Use `useStorage` for React components. Direct usage of `bindValue` is not recommended.
|
|
35
|
+
|
|
32
36
|
```typescript
|
|
33
37
|
import { bindValue, useStorage } from 'kvozy';
|
|
34
38
|
|
|
@@ -43,49 +47,28 @@ const Component = () => {
|
|
|
43
47
|
};
|
|
44
48
|
```
|
|
45
49
|
|
|
46
|
-
##
|
|
47
|
-
|
|
48
|
-
### bindValue(options)
|
|
49
|
-
|
|
50
|
-
Creates a storage binding to localStorage.
|
|
51
|
-
|
|
52
|
-
**Parameters:**
|
|
53
|
-
|
|
54
|
-
- `options` (object, required)
|
|
55
|
-
- `key` (string, required) - localStorage key
|
|
56
|
-
|
|
57
|
-
**Returns:** `BindValue` instance
|
|
50
|
+
## Why In-Memory Storage?
|
|
58
51
|
|
|
59
|
-
|
|
52
|
+
In-memory storage provides a graceful fallback when persistent storage is unavailable, such as:
|
|
60
53
|
|
|
61
|
-
-
|
|
62
|
-
-
|
|
63
|
-
-
|
|
64
|
-
|
|
65
|
-
**Behavior:**
|
|
66
|
-
|
|
67
|
-
- `subscribe()` does NOT call the callback immediately when subscribing
|
|
68
|
-
- Callbacks are only invoked when value changes via `set()`
|
|
69
|
-
|
|
70
|
-
**Example:**
|
|
54
|
+
- **Incognito/Private Mode**: Some browsers disable localStorage in private browsing
|
|
55
|
+
- **Storage Quota Exceeded**: When storage limits are reached
|
|
56
|
+
- **Cookie/Storage Disabled**: When users have disabled cookies/storage
|
|
71
57
|
|
|
72
58
|
```typescript
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
59
|
+
// This code works even if localStorage is unavailable (e.g., incognito mode)
|
|
60
|
+
const bindedValue = bindValue({
|
|
61
|
+
key: "some-key",
|
|
62
|
+
storage: localStorage ?? undefined,
|
|
63
|
+
});
|
|
64
|
+
// Falls back to in-memory storage, so your code continues to work
|
|
65
|
+
```
|
|
77
66
|
|
|
78
|
-
|
|
79
|
-
binding.set("Alice");
|
|
67
|
+
The in-memory storage ensures your application remains functional, maintaining session state without throwing errors or breaking your user experience.
|
|
80
68
|
|
|
81
|
-
|
|
82
|
-
const unsubscribe = binding.subscribe((newValue) => {
|
|
83
|
-
console.log("Value changed:", newValue);
|
|
84
|
-
});
|
|
69
|
+
## API Reference
|
|
85
70
|
|
|
86
|
-
|
|
87
|
-
unsubscribe();
|
|
88
|
-
```
|
|
71
|
+
> ⚠️ **Note:** `bindValue` is an internal API. Use `useStorage` for React components. Direct usage of `bindValue` is not recommended.
|
|
89
72
|
|
|
90
73
|
### useStorage(binding)
|
|
91
74
|
|
|
@@ -193,6 +176,38 @@ const Component = () => {
|
|
|
193
176
|
};
|
|
194
177
|
```
|
|
195
178
|
|
|
179
|
+
### Using Different Storage Types
|
|
180
|
+
|
|
181
|
+
Kvozy supports localStorage, sessionStorage, and in-memory storage:
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
import { bindValue, useStorage } from 'kvozy';
|
|
185
|
+
|
|
186
|
+
// localStorage - persists across browser sessions
|
|
187
|
+
const localBinding = bindValue({ key: 'theme', storage: localStorage });
|
|
188
|
+
|
|
189
|
+
// sessionStorage - persists within the same tab
|
|
190
|
+
const sessionBinding = bindValue({ key: 'form-data', storage: sessionStorage });
|
|
191
|
+
|
|
192
|
+
// In-memory - no persistence, graceful fallback
|
|
193
|
+
const memoryBinding = bindValue({ key: 'temp-state' });
|
|
194
|
+
|
|
195
|
+
const LocalComponent = () => {
|
|
196
|
+
const { value, setValue } = useStorage(localBinding);
|
|
197
|
+
return <div>Theme: {value || 'light'}</div>;
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
const SessionComponent = () => {
|
|
201
|
+
const { value, setValue } = useStorage(sessionBinding);
|
|
202
|
+
return <div>Form data: {value || 'empty'}</div>;
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
const MemoryComponent = () => {
|
|
206
|
+
const { value, setValue } = useStorage(memoryBinding);
|
|
207
|
+
return <div>Temp: {value || 'empty'}</div>;
|
|
208
|
+
};
|
|
209
|
+
```
|
|
210
|
+
|
|
196
211
|
### Persisting Form Data
|
|
197
212
|
|
|
198
213
|
```typescript
|
|
@@ -292,51 +307,6 @@ function useStorage(binding: BindValue): UseStorageReturn {
|
|
|
292
307
|
}
|
|
293
308
|
```
|
|
294
309
|
|
|
295
|
-
## Testing
|
|
296
|
-
|
|
297
|
-
### Unit Tests (Node)
|
|
298
|
-
|
|
299
|
-
Run unit tests for `bindValue`:
|
|
300
|
-
|
|
301
|
-
```bash
|
|
302
|
-
npm test
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
Tests are located in `unitTests/bindValue.test.ts` and use mocked localStorage.
|
|
306
|
-
|
|
307
|
-
### Browser Tests (Playwright)
|
|
308
|
-
|
|
309
|
-
Run browser tests for React integration:
|
|
310
|
-
|
|
311
|
-
```bash
|
|
312
|
-
npm run test:browser
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
Tests are located in `browserTests/useStorage.test.ts` and run on Chrome, Firefox, and Webkit.
|
|
316
|
-
|
|
317
|
-
## Browser Support
|
|
318
|
-
|
|
319
|
-
- Chrome >= 87
|
|
320
|
-
- Firefox >= 78
|
|
321
|
-
- Safari >= 15.4
|
|
322
|
-
- Edge >= 88
|
|
323
|
-
|
|
324
|
-
## TypeScript Support
|
|
325
|
-
|
|
326
|
-
Kvozy is written in TypeScript and provides full type definitions:
|
|
327
|
-
|
|
328
|
-
```typescript
|
|
329
|
-
import {
|
|
330
|
-
bindValue,
|
|
331
|
-
useStorage,
|
|
332
|
-
type BindValue,
|
|
333
|
-
type UseStorageReturn,
|
|
334
|
-
} from "kvozy";
|
|
335
|
-
|
|
336
|
-
const binding: BindValue = bindValue({ key: "test" });
|
|
337
|
-
const { value, setValue }: UseStorageReturn = useStorage(binding);
|
|
338
|
-
```
|
|
339
|
-
|
|
340
310
|
## Limitations
|
|
341
311
|
|
|
342
312
|
- **String-only values**: Kvozy only supports string values. For objects or arrays, serialize them as JSON.
|
|
@@ -350,11 +320,3 @@ const { value, setValue }: UseStorageReturn = useStorage(binding);
|
|
|
350
320
|
- [ ] Angular connector
|
|
351
321
|
- [ ] SSR support
|
|
352
322
|
- [ ] Cross-tab synchronization
|
|
353
|
-
|
|
354
|
-
## License
|
|
355
|
-
|
|
356
|
-
ISC
|
|
357
|
-
|
|
358
|
-
## Contributing
|
|
359
|
-
|
|
360
|
-
Contributions are welcome! Please read `src/AGENTS.md` for development guidelines.
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
export interface BindValueOptions {
|
|
2
2
|
key: string;
|
|
3
|
+
storage?: Storage;
|
|
3
4
|
}
|
|
4
5
|
export declare class BindValue {
|
|
5
6
|
private options;
|
|
6
7
|
private value;
|
|
7
8
|
private subscribers;
|
|
9
|
+
private storage;
|
|
8
10
|
constructor(options: BindValueOptions);
|
|
9
11
|
getValue(): string | undefined;
|
|
10
12
|
set(newValue: string): void;
|
|
@@ -3,11 +3,35 @@ var __defProp = Object.defineProperty;
|
|
|
3
3
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
5
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
6
|
+
const memoryStorage = /* @__PURE__ */ new Map();
|
|
7
|
+
const inMemoryStorage = {
|
|
8
|
+
get length() {
|
|
9
|
+
return memoryStorage.size;
|
|
10
|
+
},
|
|
11
|
+
clear() {
|
|
12
|
+
memoryStorage.clear();
|
|
13
|
+
},
|
|
14
|
+
getItem(key) {
|
|
15
|
+
return memoryStorage.get(key) ?? null;
|
|
16
|
+
},
|
|
17
|
+
key(index) {
|
|
18
|
+
const keys = Array.from(memoryStorage.keys());
|
|
19
|
+
return keys[index] ?? null;
|
|
20
|
+
},
|
|
21
|
+
removeItem(key) {
|
|
22
|
+
memoryStorage.delete(key);
|
|
23
|
+
},
|
|
24
|
+
setItem(key, value) {
|
|
25
|
+
memoryStorage.set(key, value);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
6
28
|
class BindValue {
|
|
7
29
|
constructor(options) {
|
|
8
30
|
__publicField(this, "value");
|
|
9
31
|
__publicField(this, "subscribers");
|
|
32
|
+
__publicField(this, "storage");
|
|
10
33
|
this.options = options;
|
|
34
|
+
this.storage = options.storage ?? inMemoryStorage;
|
|
11
35
|
this.subscribers = /* @__PURE__ */ new Set();
|
|
12
36
|
this.value = this.loadFromStorage();
|
|
13
37
|
}
|
|
@@ -26,11 +50,11 @@ class BindValue {
|
|
|
26
50
|
};
|
|
27
51
|
}
|
|
28
52
|
loadFromStorage() {
|
|
29
|
-
const value =
|
|
53
|
+
const value = this.storage.getItem(this.options.key);
|
|
30
54
|
return value !== null ? value : void 0;
|
|
31
55
|
}
|
|
32
56
|
saveToStorage(value) {
|
|
33
|
-
|
|
57
|
+
this.storage.setItem(this.options.key, value);
|
|
34
58
|
}
|
|
35
59
|
notifySubscribers() {
|
|
36
60
|
for (const subscriber of this.subscribers) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bindValue.js","sources":["../../../../src/bindValue.ts"],"sourcesContent":["export interface BindValueOptions {\n key: string;\n}\n\nexport class BindValue {\n private value: string | undefined;\n private subscribers: Set<(value: string | undefined) => void>;\n\n constructor(private options: BindValueOptions) {\n this.subscribers = new Set();\n this.value = this.loadFromStorage();\n }\n\n getValue(): string | undefined {\n return this.value;\n }\n\n set(newValue: string): void {\n this.value = newValue;\n this.saveToStorage(newValue);\n this.notifySubscribers();\n }\n\n subscribe(callback: (value: string | undefined) => void): () => void {\n this.subscribers.add(callback);\n return () => {\n this.subscribers.delete(callback);\n };\n }\n\n private loadFromStorage(): string | undefined {\n const value =
|
|
1
|
+
{"version":3,"file":"bindValue.js","sources":["../../../../src/bindValue.ts"],"sourcesContent":["export interface BindValueOptions {\n key: string;\n storage?: Storage;\n}\n\nconst memoryStorage = new Map<string, string>();\n\nconst inMemoryStorage: Storage = {\n get length() {\n return memoryStorage.size;\n },\n clear() {\n memoryStorage.clear();\n },\n getItem(key: string) {\n return memoryStorage.get(key) ?? null;\n },\n key(index: number) {\n const keys = Array.from(memoryStorage.keys());\n return keys[index] ?? null;\n },\n removeItem(key: string) {\n memoryStorage.delete(key);\n },\n setItem(key: string, value: string) {\n memoryStorage.set(key, value);\n },\n};\n\nexport class BindValue {\n private value: string | undefined;\n private subscribers: Set<(value: string | undefined) => void>;\n private storage: Storage;\n\n constructor(private options: BindValueOptions) {\n this.storage = options.storage ?? inMemoryStorage;\n this.subscribers = new Set();\n this.value = this.loadFromStorage();\n }\n\n getValue(): string | undefined {\n return this.value;\n }\n\n set(newValue: string): void {\n this.value = newValue;\n this.saveToStorage(newValue);\n this.notifySubscribers();\n }\n\n subscribe(callback: (value: string | undefined) => void): () => void {\n this.subscribers.add(callback);\n return () => {\n this.subscribers.delete(callback);\n };\n }\n\n private loadFromStorage(): string | undefined {\n const value = this.storage.getItem(this.options.key);\n return value !== null ? value : undefined;\n }\n\n private saveToStorage(value: string): void {\n this.storage.setItem(this.options.key, value);\n }\n\n private notifySubscribers(): void {\n for (const subscriber of this.subscribers) {\n subscriber(this.value);\n }\n }\n}\n\nexport function bindValue(options: BindValueOptions): BindValue {\n return new BindValue(options);\n}\n"],"names":[],"mappings":";;;;;AAKA,MAAM,oCAAoB,IAAA;AAE1B,MAAM,kBAA2B;AAAA,EAC/B,IAAI,SAAS;AACX,WAAO,cAAc;AAAA,EACvB;AAAA,EACA,QAAQ;AACN,kBAAc,MAAA;AAAA,EAChB;AAAA,EACA,QAAQ,KAAa;AACnB,WAAO,cAAc,IAAI,GAAG,KAAK;AAAA,EACnC;AAAA,EACA,IAAI,OAAe;AACjB,UAAM,OAAO,MAAM,KAAK,cAAc,MAAM;AAC5C,WAAO,KAAK,KAAK,KAAK;AAAA,EACxB;AAAA,EACA,WAAW,KAAa;AACtB,kBAAc,OAAO,GAAG;AAAA,EAC1B;AAAA,EACA,QAAQ,KAAa,OAAe;AAClC,kBAAc,IAAI,KAAK,KAAK;AAAA,EAC9B;AACF;AAEO,MAAM,UAAU;AAAA,EAKrB,YAAoB,SAA2B;AAJvC;AACA;AACA;AAEY,SAAA,UAAA;AAClB,SAAK,UAAU,QAAQ,WAAW;AAClC,SAAK,kCAAkB,IAAA;AACvB,SAAK,QAAQ,KAAK,gBAAA;AAAA,EACpB;AAAA,EAEA,WAA+B;AAC7B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,UAAwB;AAC1B,SAAK,QAAQ;AACb,SAAK,cAAc,QAAQ;AAC3B,SAAK,kBAAA;AAAA,EACP;AAAA,EAEA,UAAU,UAA2D;AACnE,SAAK,YAAY,IAAI,QAAQ;AAC7B,WAAO,MAAM;AACX,WAAK,YAAY,OAAO,QAAQ;AAAA,IAClC;AAAA,EACF;AAAA,EAEQ,kBAAsC;AAC5C,UAAM,QAAQ,KAAK,QAAQ,QAAQ,KAAK,QAAQ,GAAG;AACnD,WAAO,UAAU,OAAO,QAAQ;AAAA,EAClC;AAAA,EAEQ,cAAc,OAAqB;AACzC,SAAK,QAAQ,QAAQ,KAAK,QAAQ,KAAK,KAAK;AAAA,EAC9C;AAAA,EAEQ,oBAA0B;AAChC,eAAW,cAAc,KAAK,aAAa;AACzC,iBAAW,KAAK,KAAK;AAAA,IACvB;AAAA,EACF;AACF;AAEO,SAAS,UAAU,SAAsC;AAC9D,SAAO,IAAI,UAAU,OAAO;AAC9B;;;"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
export interface BindValueOptions {
|
|
2
2
|
key: string;
|
|
3
|
+
storage?: Storage;
|
|
3
4
|
}
|
|
4
5
|
export declare class BindValue {
|
|
5
6
|
private options;
|
|
6
7
|
private value;
|
|
7
8
|
private subscribers;
|
|
9
|
+
private storage;
|
|
8
10
|
constructor(options: BindValueOptions);
|
|
9
11
|
getValue(): string | undefined;
|
|
10
12
|
set(newValue: string): void;
|
|
@@ -1,11 +1,35 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
const memoryStorage = /* @__PURE__ */ new Map();
|
|
5
|
+
const inMemoryStorage = {
|
|
6
|
+
get length() {
|
|
7
|
+
return memoryStorage.size;
|
|
8
|
+
},
|
|
9
|
+
clear() {
|
|
10
|
+
memoryStorage.clear();
|
|
11
|
+
},
|
|
12
|
+
getItem(key) {
|
|
13
|
+
return memoryStorage.get(key) ?? null;
|
|
14
|
+
},
|
|
15
|
+
key(index) {
|
|
16
|
+
const keys = Array.from(memoryStorage.keys());
|
|
17
|
+
return keys[index] ?? null;
|
|
18
|
+
},
|
|
19
|
+
removeItem(key) {
|
|
20
|
+
memoryStorage.delete(key);
|
|
21
|
+
},
|
|
22
|
+
setItem(key, value) {
|
|
23
|
+
memoryStorage.set(key, value);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
4
26
|
class BindValue {
|
|
5
27
|
constructor(options) {
|
|
6
28
|
__publicField(this, "value");
|
|
7
29
|
__publicField(this, "subscribers");
|
|
30
|
+
__publicField(this, "storage");
|
|
8
31
|
this.options = options;
|
|
32
|
+
this.storage = options.storage ?? inMemoryStorage;
|
|
9
33
|
this.subscribers = /* @__PURE__ */ new Set();
|
|
10
34
|
this.value = this.loadFromStorage();
|
|
11
35
|
}
|
|
@@ -24,11 +48,11 @@ class BindValue {
|
|
|
24
48
|
};
|
|
25
49
|
}
|
|
26
50
|
loadFromStorage() {
|
|
27
|
-
const value =
|
|
51
|
+
const value = this.storage.getItem(this.options.key);
|
|
28
52
|
return value !== null ? value : void 0;
|
|
29
53
|
}
|
|
30
54
|
saveToStorage(value) {
|
|
31
|
-
|
|
55
|
+
this.storage.setItem(this.options.key, value);
|
|
32
56
|
}
|
|
33
57
|
notifySubscribers() {
|
|
34
58
|
for (const subscriber of this.subscribers) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bindValue.mjs","sources":["../../../../src/bindValue.ts"],"sourcesContent":["export interface BindValueOptions {\n key: string;\n}\n\nexport class BindValue {\n private value: string | undefined;\n private subscribers: Set<(value: string | undefined) => void>;\n\n constructor(private options: BindValueOptions) {\n this.subscribers = new Set();\n this.value = this.loadFromStorage();\n }\n\n getValue(): string | undefined {\n return this.value;\n }\n\n set(newValue: string): void {\n this.value = newValue;\n this.saveToStorage(newValue);\n this.notifySubscribers();\n }\n\n subscribe(callback: (value: string | undefined) => void): () => void {\n this.subscribers.add(callback);\n return () => {\n this.subscribers.delete(callback);\n };\n }\n\n private loadFromStorage(): string | undefined {\n const value =
|
|
1
|
+
{"version":3,"file":"bindValue.mjs","sources":["../../../../src/bindValue.ts"],"sourcesContent":["export interface BindValueOptions {\n key: string;\n storage?: Storage;\n}\n\nconst memoryStorage = new Map<string, string>();\n\nconst inMemoryStorage: Storage = {\n get length() {\n return memoryStorage.size;\n },\n clear() {\n memoryStorage.clear();\n },\n getItem(key: string) {\n return memoryStorage.get(key) ?? null;\n },\n key(index: number) {\n const keys = Array.from(memoryStorage.keys());\n return keys[index] ?? null;\n },\n removeItem(key: string) {\n memoryStorage.delete(key);\n },\n setItem(key: string, value: string) {\n memoryStorage.set(key, value);\n },\n};\n\nexport class BindValue {\n private value: string | undefined;\n private subscribers: Set<(value: string | undefined) => void>;\n private storage: Storage;\n\n constructor(private options: BindValueOptions) {\n this.storage = options.storage ?? inMemoryStorage;\n this.subscribers = new Set();\n this.value = this.loadFromStorage();\n }\n\n getValue(): string | undefined {\n return this.value;\n }\n\n set(newValue: string): void {\n this.value = newValue;\n this.saveToStorage(newValue);\n this.notifySubscribers();\n }\n\n subscribe(callback: (value: string | undefined) => void): () => void {\n this.subscribers.add(callback);\n return () => {\n this.subscribers.delete(callback);\n };\n }\n\n private loadFromStorage(): string | undefined {\n const value = this.storage.getItem(this.options.key);\n return value !== null ? value : undefined;\n }\n\n private saveToStorage(value: string): void {\n this.storage.setItem(this.options.key, value);\n }\n\n private notifySubscribers(): void {\n for (const subscriber of this.subscribers) {\n subscriber(this.value);\n }\n }\n}\n\nexport function bindValue(options: BindValueOptions): BindValue {\n return new BindValue(options);\n}\n"],"names":[],"mappings":";;;AAKA,MAAM,oCAAoB,IAAA;AAE1B,MAAM,kBAA2B;AAAA,EAC/B,IAAI,SAAS;AACX,WAAO,cAAc;AAAA,EACvB;AAAA,EACA,QAAQ;AACN,kBAAc,MAAA;AAAA,EAChB;AAAA,EACA,QAAQ,KAAa;AACnB,WAAO,cAAc,IAAI,GAAG,KAAK;AAAA,EACnC;AAAA,EACA,IAAI,OAAe;AACjB,UAAM,OAAO,MAAM,KAAK,cAAc,MAAM;AAC5C,WAAO,KAAK,KAAK,KAAK;AAAA,EACxB;AAAA,EACA,WAAW,KAAa;AACtB,kBAAc,OAAO,GAAG;AAAA,EAC1B;AAAA,EACA,QAAQ,KAAa,OAAe;AAClC,kBAAc,IAAI,KAAK,KAAK;AAAA,EAC9B;AACF;AAEO,MAAM,UAAU;AAAA,EAKrB,YAAoB,SAA2B;AAJvC;AACA;AACA;AAEY,SAAA,UAAA;AAClB,SAAK,UAAU,QAAQ,WAAW;AAClC,SAAK,kCAAkB,IAAA;AACvB,SAAK,QAAQ,KAAK,gBAAA;AAAA,EACpB;AAAA,EAEA,WAA+B;AAC7B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,UAAwB;AAC1B,SAAK,QAAQ;AACb,SAAK,cAAc,QAAQ;AAC3B,SAAK,kBAAA;AAAA,EACP;AAAA,EAEA,UAAU,UAA2D;AACnE,SAAK,YAAY,IAAI,QAAQ;AAC7B,WAAO,MAAM;AACX,WAAK,YAAY,OAAO,QAAQ;AAAA,IAClC;AAAA,EACF;AAAA,EAEQ,kBAAsC;AAC5C,UAAM,QAAQ,KAAK,QAAQ,QAAQ,KAAK,QAAQ,GAAG;AACnD,WAAO,UAAU,OAAO,QAAQ;AAAA,EAClC;AAAA,EAEQ,cAAc,OAAqB;AACzC,SAAK,QAAQ,QAAQ,KAAK,QAAQ,KAAK,KAAK;AAAA,EAC9C;AAAA,EAEQ,oBAA0B;AAChC,eAAW,cAAc,KAAK,aAAa;AACzC,iBAAW,KAAK,KAAK;AAAA,IACvB;AAAA,EACF;AACF;AAEO,SAAS,UAAU,SAAsC;AAC9D,SAAO,IAAI,UAAU,OAAO;AAC9B;"}
|