+2
-2
.gitignore
+2
-2
.gitignore
+22
.npmignore
+22
.npmignore
···
1
+
# Demo and development files
2
+
demo/
3
+
src/
4
+
index.html
5
+
6
+
# Build configuration
7
+
vite.config.ts
8
+
vite.config.d.ts
9
+
tsconfig.app.json
10
+
tsconfig.node.json
11
+
eslint.config.js
12
+
tsconfig.lib.tsbuildinfo
13
+
14
+
# Dependencies
15
+
node_modules/
16
+
package-lock.json
17
+
bun.lock
18
+
19
+
CLAUDE.md
20
+
21
+
# Output directory
22
+
lib/
+42
.tangled/workflows/upload-demo-to-wisp.yml
+42
.tangled/workflows/upload-demo-to-wisp.yml
···
1
+
when:
2
+
- event: ['push']
3
+
branch: ['main']
4
+
- event: ['manual']
5
+
engine: 'nixery'
6
+
clone:
7
+
skip: false
8
+
depth: 1
9
+
submodules: false
10
+
dependencies:
11
+
nixpkgs:
12
+
- nodejs
13
+
- coreutils
14
+
- curl
15
+
github:NixOS/nixpkgs/nixpkgs-unstable:
16
+
- bun
17
+
18
+
environment:
19
+
SITE_PATH: 'demo'
20
+
SITE_NAME: 'atproto-ui'
21
+
WISP_HANDLE: 'ana.pds.nkp.pet'
22
+
23
+
steps:
24
+
- name: build demo
25
+
command: |
26
+
export PATH="$HOME/.nix-profile/bin:$PATH"
27
+
28
+
# regenerate lockfile, https://github.com/npm/cli/pull/8184 makes rolldown not install
29
+
rm package-lock.json bun.lock
30
+
bun install
31
+
32
+
# run directly with bun because of shebang issues in nix
33
+
BUILD_TARGET=demo bun node_modules/.bin/vite build
34
+
- name: upload to wisp
35
+
command: |
36
+
curl https://sites.wisp.place/nekomimi.pet/wisp-cli-binaries/wisp-cli-x86_64-linux -o wisp-cli
37
+
chmod +x wisp-cli
38
+
./wisp-cli \
39
+
"$WISP_HANDLE" \
40
+
--path "$SITE_PATH" \
41
+
--site "$SITE_NAME" \
42
+
--password "$WISP_APP_PASSWORD"
+701
CLAUDE.md
+701
CLAUDE.md
···
1
+
# AtReact Hooks Deep Dive
2
+
3
+
## Overview
4
+
The AtReact hooks system provides a robust, cache-optimized layer for fetching AT Protocol data. All hooks follow React best practices with proper cleanup, cancellation, and stable references.
5
+
6
+
---
7
+
8
+
## Core Architecture Principles
9
+
10
+
### 1. **Three-Tier Caching Strategy**
11
+
All data flows through three cache layers:
12
+
- **DidCache** - DID documents, handle mappings, PDS endpoints
13
+
- **BlobCache** - Media/image blobs with reference counting
14
+
- **RecordCache** - AT Protocol records with deduplication
15
+
16
+
### 2. **Concurrent Request Deduplication**
17
+
When multiple components request the same data, only one network request is made. Uses reference counting to manage in-flight requests.
18
+
19
+
### 3. **Stable Reference Pattern**
20
+
Caches use memoized snapshots to prevent unnecessary re-renders:
21
+
```typescript
22
+
// Only creates new snapshot if data actually changed
23
+
if (existing && existing.did === did && existing.handle === handle) {
24
+
return toSnapshot(existing); // Reuse existing
25
+
}
26
+
```
27
+
28
+
### 4. **Three-Tier Fallback for Bluesky**
29
+
For `app.bsky.*` collections:
30
+
1. Try Bluesky appview API (fastest, public)
31
+
2. Fall back to Slingshot (microcosm service)
32
+
3. Finally query PDS directly
33
+
34
+
---
35
+
36
+
## Hook Catalog
37
+
38
+
## 1. `useDidResolution`
39
+
**Purpose:** Resolves handles to DIDs or fetches DID documents
40
+
41
+
### Key Features:
42
+
- **Bidirectional:** Works with handles OR DIDs
43
+
- **Smart Caching:** Only fetches if not in cache
44
+
- **Dual Resolution Paths:**
45
+
- Handle โ DID: Uses Slingshot first, then appview
46
+
- DID โ Document: Fetches full DID document for handle extraction
47
+
48
+
### State Flow:
49
+
```typescript
50
+
Input: "alice.bsky.social" or "did:plc:xxx"
51
+
โ
52
+
Check didCache
53
+
โ
54
+
If handle: ensureHandle(resolver, handle) โ DID
55
+
If DID: ensureDidDoc(resolver, did) โ DID doc + handle from alsoKnownAs
56
+
โ
57
+
Return: { did, handle, loading, error }
58
+
```
59
+
60
+
### Critical Implementation Details:
61
+
- **Normalizes input** to lowercase for handles
62
+
- **Memoizes input** to prevent effect re-runs
63
+
- **Stabilizes error references** - only updates if message changes
64
+
- **Cleanup:** Cancellation token prevents stale updates
65
+
66
+
---
67
+
68
+
## 2. `usePdsEndpoint`
69
+
**Purpose:** Discovers the PDS endpoint for a DID
70
+
71
+
### Key Features:
72
+
- **Depends on DID resolution** (implicit dependency)
73
+
- **Extracts from DID document** if already cached
74
+
- **Lazy fetching** - only when endpoint not in cache
75
+
76
+
### State Flow:
77
+
```typescript
78
+
Input: DID
79
+
โ
80
+
Check didCache.getByDid(did).pdsEndpoint
81
+
โ
82
+
If missing: ensurePdsEndpoint(resolver, did)
83
+
โโ Tries to get from existing DID doc
84
+
โโ Falls back to resolver.pdsEndpointForDid()
85
+
โ
86
+
Return: { endpoint, loading, error }
87
+
```
88
+
89
+
### Service Discovery:
90
+
Looks for `AtprotoPersonalDataServer` service in DID document:
91
+
```json
92
+
{
93
+
"service": [{
94
+
"type": "AtprotoPersonalDataServer",
95
+
"serviceEndpoint": "https://pds.example.com"
96
+
}]
97
+
}
98
+
```
99
+
100
+
---
101
+
102
+
## 3. `useAtProtoRecord`
103
+
**Purpose:** Fetches a single AT Protocol record with smart routing
104
+
105
+
### Key Features:
106
+
- **Collection-aware routing:** Bluesky vs other protocols
107
+
- **RecordCache deduplication:** Multiple components = one fetch
108
+
- **Cleanup with reference counting**
109
+
110
+
### State Flow:
111
+
```typescript
112
+
Input: { did, collection, rkey }
113
+
โ
114
+
If collection.startsWith("app.bsky."):
115
+
โโ useBlueskyAppview() โ Three-tier fallback
116
+
Else:
117
+
โโ useDidResolution(did)
118
+
โโ usePdsEndpoint(resolved.did)
119
+
โโ recordCache.ensure() โ Fetch from PDS
120
+
โ
121
+
Return: { record, loading, error }
122
+
```
123
+
124
+
### RecordCache Deduplication:
125
+
```typescript
126
+
// First component calling this
127
+
const { promise, release } = recordCache.ensure(did, collection, rkey, loader)
128
+
// refCount = 1
129
+
130
+
// Second component calling same record
131
+
const { promise, release } = recordCache.ensure(...) // Same promise!
132
+
// refCount = 2
133
+
134
+
// On cleanup, both call release()
135
+
// Only aborts when refCount reaches 0
136
+
```
137
+
138
+
---
139
+
140
+
## 4. `useBlueskyAppview`
141
+
**Purpose:** Fetches Bluesky records with appview optimization
142
+
143
+
### Key Features:
144
+
- **Collection-aware endpoints:**
145
+
- `app.bsky.actor.profile` โ `app.bsky.actor.getProfile`
146
+
- `app.bsky.feed.post` โ `app.bsky.feed.getPostThread`
147
+
- **CDN URL extraction:** Parses CDN URLs to extract CIDs
148
+
- **Atomic state updates:** Uses reducer for complex state
149
+
150
+
### Three-Tier Fallback with Source Tracking:
151
+
```typescript
152
+
async function fetchWithFallback() {
153
+
// Tier 1: Appview (if endpoint mapped)
154
+
try {
155
+
const result = await fetchFromAppview(did, collection, rkey);
156
+
return { record: result, source: "appview" };
157
+
} catch {}
158
+
159
+
// Tier 2: Slingshot
160
+
try {
161
+
const result = await fetchFromSlingshot(did, collection, rkey);
162
+
return { record: result, source: "slingshot" };
163
+
} catch {}
164
+
165
+
// Tier 3: PDS
166
+
try {
167
+
const result = await fetchFromPds(did, collection, rkey);
168
+
return { record: result, source: "pds" };
169
+
} catch {}
170
+
171
+
// All tiers failed - provide helpful error for banned Bluesky accounts
172
+
if (pdsEndpoint.includes('.bsky.network')) {
173
+
throw new Error('Record unavailable. The Bluesky PDS may be unreachable or the account may be banned.');
174
+
}
175
+
176
+
throw new Error('Failed to fetch record from all sources');
177
+
}
178
+
```
179
+
180
+
The `source` field in the result accurately indicates which tier successfully fetched the data, enabling debugging and analytics.
181
+
182
+
### CDN URL Handling:
183
+
Appview returns CDN URLs like:
184
+
```
185
+
https://cdn.bsky.app/img/avatar/plain/did:plc:xxx/bafkreixxx@jpeg
186
+
```
187
+
188
+
Hook extracts CID (`bafkreixxx`) and creates standard Blob object:
189
+
```typescript
190
+
{
191
+
$type: "blob",
192
+
ref: { $link: "bafkreixxx" },
193
+
mimeType: "image/jpeg",
194
+
size: 0,
195
+
cdnUrl: "https://cdn.bsky.app/..." // Preserved for fast rendering
196
+
}
197
+
```
198
+
199
+
### Reducer Pattern:
200
+
```typescript
201
+
type Action =
202
+
| { type: "SET_LOADING"; loading: boolean }
203
+
| { type: "SET_SUCCESS"; record: T; source: "appview" | "slingshot" | "pds" }
204
+
| { type: "SET_ERROR"; error: Error }
205
+
| { type: "RESET" };
206
+
207
+
// Atomic state updates, no race conditions
208
+
dispatch({ type: "SET_SUCCESS", record, source });
209
+
```
210
+
211
+
---
212
+
213
+
## 5. `useLatestRecord`
214
+
**Purpose:** Fetches the most recent record from a collection
215
+
216
+
### Key Features:
217
+
- **Timestamp validation:** Skips records before 2023 (pre-ATProto)
218
+
- **PDS-only:** Slingshot doesn't support `listRecords`
219
+
- **Smart fetching:** Gets 3 records to handle invalid timestamps
220
+
221
+
### State Flow:
222
+
```typescript
223
+
Input: { did, collection }
224
+
โ
225
+
useDidResolution(did)
226
+
usePdsEndpoint(did)
227
+
โ
228
+
callListRecords(endpoint, did, collection, limit: 3)
229
+
โ
230
+
Filter: isValidTimestamp(record) โ year >= 2023
231
+
โ
232
+
Return first valid record: { record, rkey, loading, error, empty }
233
+
```
234
+
235
+
### Timestamp Validation:
236
+
```typescript
237
+
function isValidTimestamp(record: unknown): boolean {
238
+
const timestamp = record.createdAt || record.indexedAt;
239
+
if (!timestamp) return true; // No timestamp, assume valid
240
+
241
+
const date = new Date(timestamp);
242
+
return date.getFullYear() >= 2023; // ATProto created in 2023
243
+
}
244
+
```
245
+
246
+
---
247
+
248
+
## 6. `usePaginatedRecords`
249
+
**Purpose:** Cursor-based pagination with prefetching
250
+
251
+
### Key Features:
252
+
- **Dual fetching modes:**
253
+
- Author feed (appview) - for Bluesky posts with filters
254
+
- Direct PDS - for all other collections
255
+
- **Smart prefetching:** Loads next page in background
256
+
- **Invalid timestamp filtering:** Same as `useLatestRecord`
257
+
- **Request sequencing:** Prevents race conditions with `requestSeq`
258
+
259
+
### State Management:
260
+
```typescript
261
+
// Pages stored as array
262
+
pages: [
263
+
{ records: [...], cursor: "abc" }, // page 0
264
+
{ records: [...], cursor: "def" }, // page 1
265
+
{ records: [...], cursor: undefined } // page 2 (last)
266
+
]
267
+
pageIndex: 1 // Currently viewing page 1
268
+
```
269
+
270
+
### Prefetch Logic:
271
+
```typescript
272
+
useEffect(() => {
273
+
const cursor = pages[pageIndex]?.cursor;
274
+
if (!cursor || pages[pageIndex + 1]) return; // No cursor or already loaded
275
+
276
+
// Prefetch next page in background
277
+
fetchPage(identity, cursor, pageIndex + 1, "prefetch");
278
+
}, [pageIndex, pages]);
279
+
```
280
+
281
+
### Author Feed vs PDS:
282
+
```typescript
283
+
if (preferAuthorFeed && collection === "app.bsky.feed.post") {
284
+
// Use app.bsky.feed.getAuthorFeed
285
+
const res = await callAppviewRpc("app.bsky.feed.getAuthorFeed", {
286
+
actor: handle || did,
287
+
filter: "posts_with_media", // Optional filter
288
+
includePins: true
289
+
});
290
+
} else {
291
+
// Use com.atproto.repo.listRecords
292
+
const res = await callListRecords(pdsEndpoint, did, collection, limit);
293
+
}
294
+
```
295
+
296
+
### Race Condition Prevention:
297
+
```typescript
298
+
const requestSeq = useRef(0);
299
+
300
+
// On identity change
301
+
resetState();
302
+
requestSeq.current += 1; // Invalidate in-flight requests
303
+
304
+
// In fetch callback
305
+
const token = requestSeq.current;
306
+
// ... do async work ...
307
+
if (token !== requestSeq.current) return; // Stale request, abort
308
+
```
309
+
310
+
---
311
+
312
+
## 7. `useBlob`
313
+
**Purpose:** Fetches and caches media blobs with object URL management
314
+
315
+
### Key Features:
316
+
- **Automatic cleanup:** Revokes object URLs on unmount
317
+
- **BlobCache deduplication:** Same blob = one fetch
318
+
- **Reference counting:** Safe concurrent access
319
+
320
+
### State Flow:
321
+
```typescript
322
+
Input: { did, cid }
323
+
โ
324
+
useDidResolution(did)
325
+
usePdsEndpoint(did)
326
+
โ
327
+
Check blobCache.get(did, cid)
328
+
โ
329
+
If missing: blobCache.ensure() โ Fetch from PDS
330
+
โโ GET /xrpc/com.atproto.sync.getBlob?did={did}&cid={cid}
331
+
โโ Store in cache
332
+
โ
333
+
Create object URL: URL.createObjectURL(blob)
334
+
โ
335
+
Return: { url, loading, error }
336
+
โ
337
+
Cleanup: URL.revokeObjectURL(url)
338
+
```
339
+
340
+
### Object URL Management:
341
+
```typescript
342
+
const objectUrlRef = useRef<string>();
343
+
344
+
// On successful fetch
345
+
const nextUrl = URL.createObjectURL(blob);
346
+
const prevUrl = objectUrlRef.current;
347
+
objectUrlRef.current = nextUrl;
348
+
if (prevUrl) URL.revokeObjectURL(prevUrl); // Clean up old URL
349
+
350
+
// On unmount
351
+
useEffect(() => () => {
352
+
if (objectUrlRef.current) {
353
+
URL.revokeObjectURL(objectUrlRef.current);
354
+
}
355
+
}, []);
356
+
```
357
+
358
+
---
359
+
360
+
## 8. `useBlueskyProfile`
361
+
**Purpose:** Wrapper around `useBlueskyAppview` for profile records
362
+
363
+
### Key Features:
364
+
- **Simplified interface:** Just pass DID
365
+
- **Type conversion:** Converts ProfileRecord to BlueskyProfileData
366
+
- **CID extraction:** Extracts avatar/banner CIDs from blobs
367
+
368
+
### Implementation:
369
+
```typescript
370
+
export function useBlueskyProfile(did: string | undefined) {
371
+
const { record, loading, error } = useBlueskyAppview<ProfileRecord>({
372
+
did,
373
+
collection: "app.bsky.actor.profile",
374
+
rkey: "self",
375
+
});
376
+
377
+
const data = record ? {
378
+
did: did || "",
379
+
handle: "", // Populated by caller
380
+
displayName: record.displayName,
381
+
description: record.description,
382
+
avatar: extractCidFromBlob(record.avatar),
383
+
banner: extractCidFromBlob(record.banner),
384
+
createdAt: record.createdAt,
385
+
} : undefined;
386
+
387
+
return { data, loading, error };
388
+
}
389
+
```
390
+
391
+
---
392
+
393
+
## 9. `useBacklinks`
394
+
**Purpose:** Fetches backlinks from Microcosm Constellation API
395
+
396
+
### Key Features:
397
+
- **Specialized use case:** Tangled stars, etc.
398
+
- **Abort controller:** Cancels in-flight requests
399
+
- **Refetch support:** Manual refresh capability
400
+
401
+
### State Flow:
402
+
```typescript
403
+
Input: { subject: "at://did:plc:xxx/sh.tangled.repo/yyy", source: "sh.tangled.feed.star:subject" }
404
+
โ
405
+
GET https://constellation.microcosm.blue/xrpc/blue.microcosm.links.getBacklinks
406
+
?subject={subject}&source={source}&limit={limit}
407
+
โ
408
+
Return: { backlinks: [...], total, loading, error, refetch }
409
+
```
410
+
411
+
---
412
+
413
+
## 10. `useRepoLanguages`
414
+
**Purpose:** Fetches language statistics from Tangled knot server
415
+
416
+
### Key Features:
417
+
- **Branch fallback:** Tries "main", then "master"
418
+
- **Knot server query:** For repository analysis
419
+
420
+
### State Flow:
421
+
```typescript
422
+
Input: { knot: "knot.gaze.systems", did, repoName, branch }
423
+
โ
424
+
GET https://{knot}/xrpc/sh.tangled.repo.languages
425
+
?repo={did}/{repoName}&ref={branch}
426
+
โ
427
+
If 404: Try fallback branch
428
+
โ
429
+
Return: { data: { languages: {...} }, loading, error }
430
+
```
431
+
432
+
---
433
+
434
+
## Cache Implementation Deep Dive
435
+
436
+
### DidCache
437
+
**Purpose:** Cache DID documents, handle mappings, PDS endpoints
438
+
439
+
```typescript
440
+
class DidCache {
441
+
private byHandle = new Map<string, DidCacheEntry>();
442
+
private byDid = new Map<string, DidCacheEntry>();
443
+
private handlePromises = new Map<string, Promise<...>>();
444
+
private docPromises = new Map<string, Promise<...>>();
445
+
private pdsPromises = new Map<string, Promise<...>>();
446
+
447
+
// Memoized snapshots prevent re-renders
448
+
private toSnapshot(entry): DidCacheSnapshot {
449
+
if (entry.snapshot) return entry.snapshot; // Reuse
450
+
entry.snapshot = { did, handle, doc, pdsEndpoint };
451
+
return entry.snapshot;
452
+
}
453
+
}
454
+
```
455
+
456
+
**Key methods:**
457
+
- `getByHandle(handle)` - Instant cache lookup
458
+
- `getByDid(did)` - Instant cache lookup
459
+
- `ensureHandle(resolver, handle)` - Deduplicated resolution
460
+
- `ensureDidDoc(resolver, did)` - Deduplicated doc fetch
461
+
- `ensurePdsEndpoint(resolver, did)` - Deduplicated PDS discovery
462
+
463
+
**Snapshot stability:**
464
+
```typescript
465
+
memoize(entry) {
466
+
const existing = this.byDid.get(did);
467
+
468
+
// Data unchanged? Reuse snapshot (same reference)
469
+
if (existing && existing.did === did &&
470
+
existing.handle === handle && ...) {
471
+
return toSnapshot(existing); // Prevents re-render!
472
+
}
473
+
474
+
// Data changed, create new entry
475
+
const merged = { did, handle, doc, pdsEndpoint, snapshot: undefined };
476
+
this.byDid.set(did, merged);
477
+
return toSnapshot(merged);
478
+
}
479
+
```
480
+
481
+
### BlobCache
482
+
**Purpose:** Cache media blobs with reference counting
483
+
484
+
```typescript
485
+
class BlobCache {
486
+
private store = new Map<string, BlobCacheEntry>();
487
+
private inFlight = new Map<string, InFlightBlobEntry>();
488
+
489
+
ensure(did, cid, loader) {
490
+
// Already cached?
491
+
const cached = this.get(did, cid);
492
+
if (cached) return { promise: Promise.resolve(cached), release: noop };
493
+
494
+
// In-flight request?
495
+
const existing = this.inFlight.get(key);
496
+
if (existing) {
497
+
existing.refCount++; // Multiple consumers
498
+
return { promise: existing.promise, release: () => this.release(key) };
499
+
}
500
+
501
+
// New request
502
+
const { promise, abort } = loader();
503
+
this.inFlight.set(key, { promise, abort, refCount: 1 });
504
+
return { promise, release: () => this.release(key) };
505
+
}
506
+
507
+
private release(key) {
508
+
const entry = this.inFlight.get(key);
509
+
entry.refCount--;
510
+
if (entry.refCount <= 0) {
511
+
this.inFlight.delete(key);
512
+
entry.abort(); // Cancel fetch
513
+
}
514
+
}
515
+
}
516
+
```
517
+
518
+
### RecordCache
519
+
**Purpose:** Cache AT Protocol records with deduplication
520
+
521
+
Identical structure to BlobCache but for record data.
522
+
523
+
---
524
+
525
+
## Common Patterns
526
+
527
+
### 1. Cancellation Pattern
528
+
```typescript
529
+
useEffect(() => {
530
+
let cancelled = false;
531
+
532
+
const assignState = (next) => {
533
+
if (cancelled) return; // Don't update unmounted component
534
+
setState(prev => ({ ...prev, ...next }));
535
+
};
536
+
537
+
// ... async work ...
538
+
539
+
return () => {
540
+
cancelled = true; // Mark as cancelled
541
+
release?.(); // Decrement refCount
542
+
};
543
+
}, [deps]);
544
+
```
545
+
546
+
### 2. Error Stabilization Pattern
547
+
```typescript
548
+
setError(prevError =>
549
+
prevError?.message === newError.message
550
+
? prevError // Reuse same reference
551
+
: newError // New error
552
+
);
553
+
```
554
+
555
+
### 3. Identity Tracking Pattern
556
+
```typescript
557
+
const identityRef = useRef<string>();
558
+
const identity = did && endpoint ? `${did}::${endpoint}` : undefined;
559
+
560
+
useEffect(() => {
561
+
if (identityRef.current !== identity) {
562
+
identityRef.current = identity;
563
+
resetState(); // Clear stale data
564
+
}
565
+
// ...
566
+
}, [identity]);
567
+
```
568
+
569
+
### 4. Dual-Mode Resolution
570
+
```typescript
571
+
const isDid = input.startsWith("did:");
572
+
const normalizedHandle = !isDid ? input.toLowerCase() : undefined;
573
+
574
+
// Different code paths
575
+
if (isDid) {
576
+
snapshot = await didCache.ensureDidDoc(resolver, input);
577
+
} else {
578
+
snapshot = await didCache.ensureHandle(resolver, normalizedHandle);
579
+
}
580
+
```
581
+
582
+
---
583
+
584
+
## Performance Optimizations
585
+
586
+
### 1. **Memoized Snapshots**
587
+
Caches return stable references when data unchanged โ prevents re-renders
588
+
589
+
### 2. **Reference Counting**
590
+
Multiple components requesting same data share one fetch
591
+
592
+
### 3. **Prefetching**
593
+
`usePaginatedRecords` loads next page in background
594
+
595
+
### 4. **CDN URLs**
596
+
Bluesky appview returns CDN URLs โ skip blob fetching for images
597
+
598
+
### 5. **Smart Routing**
599
+
Bluesky collections use fast appview โ non-Bluesky goes direct to PDS
600
+
601
+
### 6. **Request Deduplication**
602
+
In-flight request maps prevent duplicate fetches
603
+
604
+
### 7. **Timestamp Validation**
605
+
Skip invalid records early (before 2023) โ fewer wasted cycles
606
+
607
+
---
608
+
609
+
## Error Handling Strategy
610
+
611
+
### 1. **Fallback Chains**
612
+
Never fail on first attempt โ try multiple sources
613
+
614
+
### 2. **Graceful Degradation**
615
+
```typescript
616
+
// Slingshot failed? Try appview
617
+
try {
618
+
return await fetchFromSlingshot();
619
+
} catch (slingshotError) {
620
+
try {
621
+
return await fetchFromAppview();
622
+
} catch (appviewError) {
623
+
// Combine errors for better debugging
624
+
throw new Error(`${appviewError.message}; Slingshot: ${slingshotError.message}`);
625
+
}
626
+
}
627
+
```
628
+
629
+
### 3. **Component Isolation**
630
+
Errors in one component don't crash others (via error boundaries recommended)
631
+
632
+
### 4. **Abort Handling**
633
+
```typescript
634
+
try {
635
+
await fetch(url, { signal });
636
+
} catch (err) {
637
+
if (err.name === "AbortError") return; // Expected, ignore
638
+
throw err;
639
+
}
640
+
```
641
+
642
+
### 5. **Banned Bluesky Account Detection**
643
+
When all three tiers fail and the PDS is a `.bsky.network` endpoint, provide a helpful error:
644
+
```typescript
645
+
// All tiers failed - check if it's a banned Bluesky account
646
+
if (pdsEndpoint.includes('.bsky.network')) {
647
+
throw new Error(
648
+
'Record unavailable. The Bluesky PDS may be unreachable or the account may be banned.'
649
+
);
650
+
}
651
+
```
652
+
653
+
This helps users understand why data is unavailable instead of showing generic fetch errors. Applies to both `useBlueskyAppview` and `useAtProtoRecord` hooks.
654
+
655
+
---
656
+
657
+
## Testing Considerations
658
+
659
+
### Key scenarios to test:
660
+
1. **Concurrent requests:** Multiple components requesting same data
661
+
2. **Race conditions:** Component unmounting mid-fetch
662
+
3. **Cache invalidation:** Identity changes during fetch
663
+
4. **Error fallbacks:** Slingshot down โ appview works
664
+
5. **Timestamp filtering:** Records before 2023 skipped
665
+
6. **Reference counting:** Proper cleanup on unmount
666
+
7. **Prefetching:** Background loads don't interfere with active loads
667
+
668
+
---
669
+
670
+
## Common Gotchas
671
+
672
+
### 1. **React Rules of Hooks**
673
+
All hooks called unconditionally, even if results not used:
674
+
```typescript
675
+
// Always call, conditionally use results
676
+
const blueskyResult = useBlueskyAppview({
677
+
did: isBlueskyCollection ? handleOrDid : undefined, // Pass undefined to skip
678
+
collection: isBlueskyCollection ? collection : undefined,
679
+
rkey: isBlueskyCollection ? rkey : undefined,
680
+
});
681
+
```
682
+
683
+
### 2. **Cleanup Order Matters**
684
+
```typescript
685
+
return () => {
686
+
cancelled = true; // 1. Prevent state updates
687
+
release?.(); // 2. Decrement refCount
688
+
revokeObjectURL(...); // 3. Free resources
689
+
};
690
+
```
691
+
692
+
### 3. **Snapshot Reuse**
693
+
Don't modify cached snapshots! They're shared across components.
694
+
695
+
### 4. **CDN URL Extraction**
696
+
Bluesky CDN URLs must be parsed carefully:
697
+
```
698
+
https://cdn.bsky.app/img/avatar/plain/did:plc:xxx/bafkreixxx@jpeg
699
+
^^^^^^^^^^^^ ^^^^^^
700
+
DID CID
701
+
```
+141
-78
README.md
+141
-78
README.md
···
1
1
# atproto-ui
2
2
3
-
atproto-ui is a component library and set of hooks for rendering records from the AT Protocol (Bluesky, Leaflet, and friends) in React applications. It handles DID resolution, PDS endpoint discovery, and record fetching so you can focus on UI. [Live demo](https://atproto-ui.wisp.place).
3
+
A React component library for rendering AT Protocol records (Bluesky, Leaflet, Tangled, and more). Handles DID resolution, PDS discovery, and record fetching automatically as well as caching these so multiple components can render quickly. [Live demo](https://atproto-ui.wisp.place).
4
+
5
+
This project is mostly a wrapper on the extremely amazing work [Mary](https://mary.my.id/) has done with [atcute](https://tangled.org/@mary.my.id/atcute), please support it. I have to give thanks to [phil](https://bsky.app/profile/bad-example.com) for microcosm and slingshot. Incredible services being given for free that is responsible for why the components fetch data so quickly.
4
6
5
7
## Screenshots
6
8
···
9
11
10
12
## Features
11
13
12
-
- Drop-in components for common record types (`BlueskyPost`, `BlueskyProfile`, `TangledString`, etc.).
13
-
- Pass prefetched data directly to components to skip API callsโperfect for server-side rendering, caching, or when you already have the data.
14
-
- Hooks and helpers for composing your own renderers for your own applications, (PRs welcome!)
15
-
- Built on the lightweight [`@atcute/*`](https://github.com/atcute) clients.
14
+
- **Drop-in components** for common record types (`BlueskyPost`, `BlueskyProfile`, `TangledRepo`, `LeafletDocument`)
15
+
- **Prefetch support** - Pass data directly to skip API calls (perfect for SSR/caching)
16
+
- **Caching** - Blobs, DIDs, and records are cached so components which use the same ones can render even quicker
17
+
- **Customizable theming** - Override CSS variables to match your app's design
18
+
- **Composable hooks** - Build custom renderers with protocol primitives
19
+
- Built on lightweight [`@atcute/*`](https://tangled.org/@mary.my.id/atcute) clients
16
20
17
21
## Installation
18
22
···
20
24
npm install atproto-ui
21
25
```
22
26
23
-
## Quick start
24
-
25
-
1. Wrap your app (once) with the `AtProtoProvider`.
26
-
2. Drop any of the ready-made components inside that provider.
27
-
3. Use the hooks to prefetch handles, blobs, or latest records when you want to control the render flow yourself.
27
+
## Quick Start
28
28
29
29
```tsx
30
-
import { AtProtoProvider, BlueskyPost } from "atproto-ui";
30
+
import { AtProtoProvider, BlueskyPost, LeafletDocument } from "atproto-ui";
31
+
import "atproto-ui/styles.css";
31
32
32
33
export function App() {
33
34
return (
34
35
<AtProtoProvider>
35
36
<BlueskyPost did="did:plc:example" rkey="3k2aexample" />
36
-
{/* you can use handles in the components as well. */}
37
+
{/* You can use handles too */}
37
38
<LeafletDocument did="nekomimi.pet" rkey="3m2seagm2222c" />
38
39
</AtProtoProvider>
39
40
);
40
41
}
41
42
```
42
43
43
-
## Passing prefetched data to skip API calls
44
+
**Note:** The library automatically imports the CSS when you import any component. If you prefer to import it explicitly (e.g., for better IDE support or control over load order), you can use `import "atproto-ui/styles.css"`.
45
+
46
+
## Theming
47
+
48
+
Components use CSS variables for theming. By default, they respond to system dark mode preferences, or you can set a theme explicitly:
49
+
50
+
```tsx
51
+
// Set theme via data attribute on document element
52
+
document.documentElement.setAttribute("data-theme", "dark"); // or "light"
53
+
54
+
// For system preference (default)
55
+
document.documentElement.removeAttribute("data-theme");
56
+
```
57
+
58
+
### Available CSS Variables
59
+
60
+
```css
61
+
--atproto-color-bg
62
+
--atproto-color-bg-elevated
63
+
--atproto-color-text
64
+
--atproto-color-text-secondary
65
+
--atproto-color-border
66
+
--atproto-color-link
67
+
/* ...and more, check out lib/styles.css */
68
+
```
44
69
45
-
All components accept a `record` prop. When provided, the component uses your data immediately without making network requests for that record. This is perfect for SSR, caching strategies, or when you've already fetched data through other means.
70
+
### Override Component Theme
71
+
72
+
Wrap any component in a div with custom CSS variables to override its appearance:
73
+
74
+
```tsx
75
+
import { AtProtoStyles } from "atproto-ui";
76
+
77
+
<div style={{
78
+
'--atproto-color-bg': '#f0f0f0',
79
+
'--atproto-color-text': '#000',
80
+
'--atproto-color-link': '#0066cc',
81
+
} satisfies AtProtoStyles}>
82
+
<BlueskyPost did="..." rkey="..." />
83
+
</div>
84
+
```
85
+
86
+
## Prefetched Data
87
+
88
+
All components accept a `record` prop. When provided, the component uses your data immediately without making network requests. Perfect for SSR, caching, or when you've already fetched data.
46
89
47
90
```tsx
48
91
import { BlueskyPost, useLatestRecord } from "atproto-ui";
···
63
106
};
64
107
```
65
108
66
-
The same pattern works for all components:
109
+
All components support prefetched data:
67
110
68
111
```tsx
69
-
// BlueskyProfile with prefetched data
70
112
<BlueskyProfile did={did} record={profileRecord} />
113
+
<TangledString did={did} rkey={rkey} record={stringRecord} />
114
+
<LeafletDocument did={did} rkey={rkey} record={documentRecord} />
115
+
```
71
116
72
-
// TangledString with prefetched data
73
-
<TangledString did={did} rkey={rkey} record={stringRecord} />
117
+
### Using atcute Directly
118
+
119
+
Use atcute directly to construct records and pass them to componentsโfully compatible!
120
+
121
+
```tsx
122
+
import { Client, simpleFetchHandler, ok } from '@atcute/client';
123
+
import type { AppBskyFeedPost } from '@atcute/bluesky';
124
+
import { BlueskyPost } from 'atproto-ui';
125
+
126
+
// Create atcute client
127
+
const client = new Client({
128
+
handler: simpleFetchHandler({ service: 'https://public.api.bsky.app' })
129
+
});
130
+
131
+
// Fetch a record
132
+
const data = await ok(
133
+
client.get('com.atproto.repo.getRecord', {
134
+
params: {
135
+
repo: 'did:plc:ttdrpj45ibqunmfhdsb4zdwq',
136
+
collection: 'app.bsky.feed.post',
137
+
rkey: '3m45rq4sjes2h'
138
+
}
139
+
})
140
+
);
141
+
142
+
const record = data.value as AppBskyFeedPost.Main;
74
143
75
-
// LeafletDocument with prefetched data
76
-
<LeafletDocument did={did} rkey={rkey} record={documentRecord} />
144
+
// Pass atcute record directly to component!
145
+
<BlueskyPost
146
+
did="did:plc:ttdrpj45ibqunmfhdsb4zdwq"
147
+
rkey="3m45rq4sjes2h"
148
+
record={record}
149
+
/>
77
150
```
78
151
79
-
### Available building blocks
152
+
## API Reference
80
153
81
-
| Component / Hook | What it does |
82
-
| --------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
83
-
| `AtProtoProvider` | Configures PLC directory (defaults to `https://plc.directory`) and shares protocol clients via React context. |
84
-
| `AtProtoRecord` | Core component that fetches and renders any AT Protocol record. **Accepts a `record` prop to use prefetched data and skip API calls.** |
85
-
| `BlueskyProfile` | Renders a profile card for a DID/handle. **Accepts a `record` prop to skip fetching.** Also supports `fallback`, `loadingIndicator`, `renderer`, and `colorScheme`. |
86
-
| `BlueskyPost` / `BlueskyQuotePost` | Shows a single Bluesky post with quotation support. **Accepts a `record` prop to skip fetching.** Custom renderer overrides and loading/fallback knobs available. |
87
-
| `BlueskyPostList` | Lists the latest posts with built-in pagination (defaults: 5 per page, pagination controls on). |
88
-
| `TangledString` | Renders a Tangled string (gist-like record). **Accepts a `record` prop to skip fetching.** Optional renderer overrides available. |
89
-
| `LeafletDocument` | Displays long-form Leaflet documents with blocks and theme support. **Accepts a `record` prop to skip fetching.** Renderer overrides available. |
90
-
| `useDidResolution`, `useLatestRecord`, `usePaginatedRecords`, โฆ | Hook-level access to records. `useLatestRecord` returns both the `record` and `rkey` so you can pass them directly to components. |
154
+
### Components
155
+
156
+
| Component | Description |
157
+
|-----------|-------------|
158
+
| `AtProtoProvider` | Context provider for sharing protocol clients. Optional `plcDirectory` prop. |
159
+
| `AtProtoRecord` | Core component for fetching/rendering any AT Protocol record. Accepts `record` prop. |
160
+
| `BlueskyProfile` | Profile card for a DID/handle. Accepts `record`, `fallback`, `loadingIndicator`, `renderer`. |
161
+
| `BlueskyPost` | Single Bluesky post. Accepts `record`, `iconPlacement`, custom renderers. |
162
+
| `BlueskyQuotePost` | Post with quoted post support. Accepts `record`. |
163
+
| `BlueskyPostList` | Paginated list of posts (default: 5 per page). |
164
+
| `TangledString` | Tangled string (code snippet) renderer. Accepts `record`. |
165
+
| `LeafletDocument` | Long-form document with blocks. Accepts `record`, `publicationRecord`. |
166
+
167
+
### Hooks
91
168
92
-
All components accept a `colorScheme` of `'light' | 'dark' | 'system'` so they can blend into your design. They also accept `fallback` and `loadingIndicator` props to control what renders before or during network work, and most expose a `renderer` override when you need total control of the final markup.
169
+
| Hook | Returns |
170
+
|------|---------|
171
+
| `useDidResolution(did)` | `{ did, handle, loading, error }` |
172
+
| `useLatestRecord(did, collection)` | `{ record, rkey, loading, error, empty }` |
173
+
| `usePaginatedRecords(options)` | `{ records, loading, hasNext, loadNext, ... }` |
174
+
| `useBlob(did, cid)` | `{ url, loading, error }` |
175
+
| `useAtProtoRecord(did, collection, rkey)` | `{ record, loading, error }` |
93
176
94
-
### Using hooks to fetch data once
177
+
## Advanced Usage
95
178
96
-
`useLatestRecord` gives you the most recent record for any collection along with its `rkey`. You can pass both to components to skip the fetch:
179
+
### Using Hooks for Custom Logic
97
180
98
181
```tsx
99
182
import { useLatestRecord, BlueskyPost } from "atproto-ui";
···
114
197
};
115
198
```
116
199
117
-
The same pattern works for other components. Just swap the collection NSID and component:
200
+
### Custom Renderer
118
201
119
-
```tsx
120
-
const LatestLeafletDocument: React.FC<{ did: string }> = ({ did }) => {
121
-
const { record, rkey } = useLatestRecord(did, "pub.leaflet.document");
122
-
return record && rkey ? (
123
-
<LeafletDocument did={did} rkey={rkey} record={record} colorScheme="light" />
124
-
) : null;
125
-
};
126
-
```
127
-
128
-
## Compose your own component
129
-
130
-
The helpers let you stitch together custom experiences without reimplementing protocol plumbing. The example below pulls a creator's latest post and renders a minimal summary:
202
+
Use `AtProtoRecord` with a custom renderer for full control:
131
203
132
204
```tsx
133
-
import { useLatestRecord, useColorScheme, AtProtoRecord } from "atproto-ui";
205
+
import { AtProtoRecord } from "atproto-ui";
134
206
import type { FeedPostRecord } from "atproto-ui";
135
207
136
-
const LatestPostSummary: React.FC<{ did: string }> = ({ did }) => {
137
-
const scheme = useColorScheme("system");
138
-
const { rkey, loading, error } = useLatestRecord<FeedPostRecord>(
139
-
did,
140
-
"app.bsky.feed.post",
141
-
);
142
-
143
-
if (loading) return <span>Loadingโฆ</span>;
144
-
if (error || !rkey) return <span>No post yet.</span>;
145
-
146
-
return (
147
-
<AtProtoRecord<FeedPostRecord>
148
-
did={did}
149
-
collection="app.bsky.feed.post"
150
-
rkey={rkey}
151
-
renderer={({ record }) => (
152
-
<article data-color-scheme={scheme}>
153
-
<strong>{record?.text ?? "Empty post"}</strong>
154
-
</article>
155
-
)}
156
-
/>
157
-
);
158
-
};
208
+
<AtProtoRecord<FeedPostRecord>
209
+
did={did}
210
+
collection="app.bsky.feed.post"
211
+
rkey={rkey}
212
+
renderer={({ record, loading, error }) => (
213
+
<article>
214
+
<strong>{record?.text ?? "Empty post"}</strong>
215
+
</article>
216
+
)}
217
+
/>
159
218
```
160
219
161
-
There is a [demo](https://atproto-ui.wisp.place/) where you can see the components in live action.
220
+
## Demo
221
+
222
+
Check out the [live demo](https://atproto-ui.wisp.place/) to see all components in action.
162
223
163
-
## Running the demo locally
224
+
### Running Locally
164
225
165
226
```bash
166
227
npm install
167
228
npm run dev
168
229
```
169
230
170
-
Then open the printed Vite URL and try entering a Bluesky handle to see the components in action.
231
+
## Contributing
171
232
172
-
## Next steps
233
+
Contributions are welcome! Open an issue or PR for:
234
+
- New record type support (e.g., Grain.social photos)
235
+
- Improved documentation
236
+
- Bug fixes or feature requests
173
237
174
-
- Expand renderer coverage (e.g., Grain.social photos).
175
-
- Expand documentation with TypeScript API references and theming guidelines.
238
+
## License
176
239
177
-
Contributions and ideas are welcomeโfeel free to open an issue or PR!
240
+
MIT
+697
bun.lock
+697
bun.lock
···
1
+
{
2
+
"lockfileVersion": 1,
3
+
"configVersion": 1,
4
+
"workspaces": {
5
+
"": {
6
+
"name": "atproto-ui",
7
+
"dependencies": {
8
+
"@atcute/atproto": "^3.1.7",
9
+
"@atcute/bluesky": "^3.2.3",
10
+
"@atcute/client": "^4.0.3",
11
+
"@atcute/identity-resolver": "^1.1.3",
12
+
"@atcute/tangled": "^1.0.10",
13
+
},
14
+
"devDependencies": {
15
+
"@eslint/js": "^9.36.0",
16
+
"@microsoft/api-extractor": "^7.53.1",
17
+
"@types/node": "^24.6.0",
18
+
"@types/react": "^19.1.16",
19
+
"@types/react-dom": "^19.1.9",
20
+
"@vitejs/plugin-react": "^5.0.4",
21
+
"eslint": "^9.36.0",
22
+
"eslint-plugin-react-hooks": "^5.2.0",
23
+
"eslint-plugin-react-refresh": "^0.4.22",
24
+
"globals": "^16.4.0",
25
+
"react": "^19.1.1",
26
+
"react-dom": "^19.1.1",
27
+
"rollup-plugin-typescript2": "^0.36.0",
28
+
"typescript": "~5.9.3",
29
+
"typescript-eslint": "^8.45.0",
30
+
"unplugin-dts": "^1.0.0-beta.6",
31
+
"vite": "npm:rolldown-vite@7.1.14",
32
+
},
33
+
"peerDependencies": {
34
+
"react": "^18.2.0 || ^19.0.0",
35
+
"react-dom": "^18.2.0 || ^19.0.0",
36
+
},
37
+
"optionalPeers": [
38
+
"react-dom",
39
+
],
40
+
},
41
+
},
42
+
"packages": {
43
+
"@atcute/atproto": ["@atcute/atproto@3.1.9", "", { "dependencies": { "@atcute/lexicons": "^1.2.2" } }, "sha512-DyWwHCTdR4hY2BPNbLXgVmm7lI+fceOwWbE4LXbGvbvVtSn+ejSVFaAv01Ra3kWDha0whsOmbJL8JP0QPpf1+w=="],
44
+
45
+
"@atcute/bluesky": ["@atcute/bluesky@3.2.11", "", { "dependencies": { "@atcute/atproto": "^3.1.9", "@atcute/lexicons": "^1.2.5" } }, "sha512-AboS6y4t+zaxIq7E4noue10csSpIuk/Uwo30/l6GgGBDPXrd7STw8Yb5nGZQP+TdG/uC8/c2mm7UnY65SDOh6A=="],
46
+
47
+
"@atcute/client": ["@atcute/client@4.1.0", "", { "dependencies": { "@atcute/identity": "^1.1.3", "@atcute/lexicons": "^1.2.5" } }, "sha512-AYhSu3RSDA2VDkVGOmad320NRbUUUf5pCFWJcOzlk25YC/4kyzmMFfpzhf1jjjEcY+anNBXGGhav/kKB1evggQ=="],
48
+
49
+
"@atcute/identity": ["@atcute/identity@1.1.3", "", { "dependencies": { "@atcute/lexicons": "^1.2.4", "@badrap/valita": "^0.4.6" } }, "sha512-oIqPoI8TwWeQxvcLmFEZLdN2XdWcaLVtlm8pNk0E72As9HNzzD9pwKPrLr3rmTLRIoULPPFmq9iFNsTeCIU9ng=="],
50
+
51
+
"@atcute/identity-resolver": ["@atcute/identity-resolver@1.1.4", "", { "dependencies": { "@atcute/lexicons": "^1.2.2", "@atcute/util-fetch": "^1.0.3", "@badrap/valita": "^0.4.6" }, "peerDependencies": { "@atcute/identity": "^1.0.0" } }, "sha512-/SVh8vf2cXFJenmBnGeYF2aY3WGQm3cJeew5NWTlkqoy3LvJ5wkvKq9PWu4Tv653VF40rPOp6LOdVr9Fa+q5rA=="],
52
+
53
+
"@atcute/lexicons": ["@atcute/lexicons@1.2.5", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "esm-env": "^1.2.2" } }, "sha512-9yO9WdgxW8jZ7SbzUycH710z+JmsQ9W9n5S6i6eghYju32kkluFmgBeS47r8e8p2+Dv4DemS7o/3SUGsX9FR5Q=="],
54
+
55
+
"@atcute/tangled": ["@atcute/tangled@1.0.12", "", { "dependencies": { "@atcute/atproto": "^3.1.9", "@atcute/lexicons": "^1.2.3" } }, "sha512-JKA5sOhd8SLhDFhY+PKHqLLytQBBKSiwcaEzfYUJBeyfvqXFPNNAwvRbe3VST4IQ3izoOu3O0R9/b1mjL45UzA=="],
56
+
57
+
"@atcute/util-fetch": ["@atcute/util-fetch@1.0.4", "", { "dependencies": { "@badrap/valita": "^0.4.6" } }, "sha512-sIU9Qk0dE8PLEXSfhy+gIJV+HpiiknMytCI2SqLlqd0vgZUtEKI/EQfP+23LHWvP+CLCzVDOa6cpH045OlmNBg=="],
58
+
59
+
"@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="],
60
+
61
+
"@babel/compat-data": ["@babel/compat-data@7.28.5", "", {}, "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA=="],
62
+
63
+
"@babel/core": ["@babel/core@7.28.5", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.28.3", "@babel/helpers": "^7.28.4", "@babel/parser": "^7.28.5", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw=="],
64
+
65
+
"@babel/generator": ["@babel/generator@7.28.5", "", { "dependencies": { "@babel/parser": "^7.28.5", "@babel/types": "^7.28.5", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ=="],
66
+
67
+
"@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.27.2", "", { "dependencies": { "@babel/compat-data": "^7.27.2", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ=="],
68
+
69
+
"@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="],
70
+
71
+
"@babel/helper-module-imports": ["@babel/helper-module-imports@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w=="],
72
+
73
+
"@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.3", "", { "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", "@babel/traverse": "^7.28.3" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw=="],
74
+
75
+
"@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.27.1", "", {}, "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw=="],
76
+
77
+
"@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
78
+
79
+
"@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="],
80
+
81
+
"@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],
82
+
83
+
"@babel/helpers": ["@babel/helpers@7.28.4", "", { "dependencies": { "@babel/template": "^7.27.2", "@babel/types": "^7.28.4" } }, "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w=="],
84
+
85
+
"@babel/parser": ["@babel/parser@7.28.5", "", { "dependencies": { "@babel/types": "^7.28.5" }, "bin": "./bin/babel-parser.js" }, "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ=="],
86
+
87
+
"@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw=="],
88
+
89
+
"@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw=="],
90
+
91
+
"@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="],
92
+
93
+
"@babel/traverse": ["@babel/traverse@7.28.5", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.5", "@babel/template": "^7.27.2", "@babel/types": "^7.28.5", "debug": "^4.3.1" } }, "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ=="],
94
+
95
+
"@babel/types": ["@babel/types@7.28.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="],
96
+
97
+
"@badrap/valita": ["@badrap/valita@0.4.6", "", {}, "sha512-4kdqcjyxo/8RQ8ayjms47HCWZIF5981oE5nIenbfThKDxWXtEHKipAOWlflpPJzZx9y/JWYQkp18Awr7VuepFg=="],
98
+
99
+
"@emnapi/core": ["@emnapi/core@1.7.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg=="],
100
+
101
+
"@emnapi/runtime": ["@emnapi/runtime@1.7.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA=="],
102
+
103
+
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
104
+
105
+
"@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g=="],
106
+
107
+
"@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="],
108
+
109
+
"@eslint/config-array": ["@eslint/config-array@0.21.1", "", { "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA=="],
110
+
111
+
"@eslint/config-helpers": ["@eslint/config-helpers@0.4.2", "", { "dependencies": { "@eslint/core": "^0.17.0" } }, "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw=="],
112
+
113
+
"@eslint/core": ["@eslint/core@0.17.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ=="],
114
+
115
+
"@eslint/eslintrc": ["@eslint/eslintrc@3.3.3", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.1", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ=="],
116
+
117
+
"@eslint/js": ["@eslint/js@9.39.1", "", {}, "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw=="],
118
+
119
+
"@eslint/object-schema": ["@eslint/object-schema@2.1.7", "", {}, "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA=="],
120
+
121
+
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.1", "", { "dependencies": { "@eslint/core": "^0.17.0", "levn": "^0.4.1" } }, "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA=="],
122
+
123
+
"@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="],
124
+
125
+
"@humanfs/node": ["@humanfs/node@0.16.7", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="],
126
+
127
+
"@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="],
128
+
129
+
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
130
+
131
+
"@isaacs/balanced-match": ["@isaacs/balanced-match@4.0.1", "", {}, "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="],
132
+
133
+
"@isaacs/brace-expansion": ["@isaacs/brace-expansion@5.0.0", "", { "dependencies": { "@isaacs/balanced-match": "^4.0.1" } }, "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA=="],
134
+
135
+
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
136
+
137
+
"@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
138
+
139
+
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
140
+
141
+
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
142
+
143
+
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
144
+
145
+
"@microsoft/api-extractor": ["@microsoft/api-extractor@7.55.1", "", { "dependencies": { "@microsoft/api-extractor-model": "7.32.1", "@microsoft/tsdoc": "~0.16.0", "@microsoft/tsdoc-config": "~0.18.0", "@rushstack/node-core-library": "5.19.0", "@rushstack/rig-package": "0.6.0", "@rushstack/terminal": "0.19.4", "@rushstack/ts-command-line": "5.1.4", "diff": "~8.0.2", "lodash": "~4.17.15", "minimatch": "10.0.3", "resolve": "~1.22.1", "semver": "~7.5.4", "source-map": "~0.6.1", "typescript": "5.8.2" }, "bin": { "api-extractor": "bin/api-extractor" } }, "sha512-l8Z+8qrLkZFM3HM95Dbpqs6G39fpCa7O5p8A7AkA6hSevxkgwsOlLrEuPv0ADOyj5dI1Af5WVDiwpKG/ya5G3w=="],
146
+
147
+
"@microsoft/api-extractor-model": ["@microsoft/api-extractor-model@7.32.1", "", { "dependencies": { "@microsoft/tsdoc": "~0.16.0", "@microsoft/tsdoc-config": "~0.18.0", "@rushstack/node-core-library": "5.19.0" } }, "sha512-u4yJytMYiUAnhcNQcZDTh/tVtlrzKlyKrQnLOV+4Qr/5gV+cpufWzCYAB1Q23URFqD6z2RoL2UYncM9xJVGNKA=="],
148
+
149
+
"@microsoft/tsdoc": ["@microsoft/tsdoc@0.16.0", "", {}, "sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA=="],
150
+
151
+
"@microsoft/tsdoc-config": ["@microsoft/tsdoc-config@0.18.0", "", { "dependencies": { "@microsoft/tsdoc": "0.16.0", "ajv": "~8.12.0", "jju": "~1.4.0", "resolve": "~1.22.2" } }, "sha512-8N/vClYyfOH+l4fLkkr9+myAoR6M7akc8ntBJ4DJdWH2b09uVfr71+LTMpNyG19fNqWDg8KEDZhx5wxuqHyGjw=="],
152
+
153
+
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.0", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" } }, "sha512-Fq6DJW+Bb5jaWE69/qOE0D1TUN9+6uWhCeZpdnSBk14pjLcCWR7Q8n49PTSPHazM37JqrsdpEthXy2xn6jWWiA=="],
154
+
155
+
"@oxc-project/runtime": ["@oxc-project/runtime@0.92.0", "", {}, "sha512-Z7x2dZOmznihvdvCvLKMl+nswtOSVxS2H2ocar+U9xx6iMfTp0VGIrX6a4xB1v80IwOPC7dT1LXIJrY70Xu3Jw=="],
156
+
157
+
"@oxc-project/types": ["@oxc-project/types@0.93.0", "", {}, "sha512-yNtwmWZIBtJsMr5TEfoZFDxIWV6OdScOpza/f5YxbqUMJk+j6QX3Cf3jgZShGEFYWQJ5j9mJ6jM0tZHu2J9Yrg=="],
158
+
159
+
"@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-beta.41", "", { "os": "android", "cpu": "arm64" }, "sha512-Edflndd9lU7JVhVIvJlZhdCj5DkhYDJPIRn4Dx0RUdfc8asP9xHOI5gMd8MesDDx+BJpdIT/uAmVTearteU/mQ=="],
160
+
161
+
"@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-beta.41", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XGCzqfjdk7550PlyZRTBKbypXrB7ATtXhw/+bjtxnklLQs0mKP/XkQVOKyn9qGKSlvH8I56JLYryVxl0PCvSNw=="],
162
+
163
+
"@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-beta.41", "", { "os": "darwin", "cpu": "x64" }, "sha512-Ho6lIwGJed98zub7n0xcRKuEtnZgbxevAmO4x3zn3C3N4GVXZD5xvCvTVxSMoeBJwTcIYzkVDRTIhylQNsTgLQ=="],
164
+
165
+
"@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-beta.41", "", { "os": "freebsd", "cpu": "x64" }, "sha512-ijAZETywvL+gACjbT4zBnCp5ez1JhTRs6OxRN4J+D6AzDRbU2zb01Esl51RP5/8ZOlvB37xxsRQ3X4YRVyYb3g=="],
166
+
167
+
"@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.41", "", { "os": "linux", "cpu": "arm" }, "sha512-EgIOZt7UildXKFEFvaiLNBXm+4ggQyGe3E5Z1QP9uRcJJs9omihOnm897FwOBQdCuMvI49iBgjFrkhH+wMJ2MA=="],
168
+
169
+
"@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-beta.41", "", { "os": "linux", "cpu": "arm64" }, "sha512-F8bUwJq8v/JAU8HSwgF4dztoqJ+FjdyjuvX4//3+Fbe2we9UktFeZ27U4lRMXF1vxWtdV4ey6oCSqI7yUrSEeg=="],
170
+
171
+
"@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-beta.41", "", { "os": "linux", "cpu": "arm64" }, "sha512-MioXcCIX/wB1pBnBoJx8q4OGucUAfC1+/X1ilKFsjDK05VwbLZGRgOVD5OJJpUQPK86DhQciNBrfOKDiatxNmg=="],
172
+
173
+
"@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-beta.41", "", { "os": "linux", "cpu": "x64" }, "sha512-m66M61fizvRCwt5pOEiZQMiwBL9/y0bwU/+Kc4Ce/Pef6YfoEkR28y+DzN9rMdjo8Z28NXjsDPq9nH4mXnAP0g=="],
174
+
175
+
"@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-beta.41", "", { "os": "linux", "cpu": "x64" }, "sha512-yRxlSfBvWnnfrdtJfvi9lg8xfG5mPuyoSHm0X01oiE8ArmLRvoJGHUTJydCYz+wbK2esbq5J4B4Tq9WAsOlP1Q=="],
176
+
177
+
"@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-beta.41", "", { "os": "none", "cpu": "arm64" }, "sha512-PHVxYhBpi8UViS3/hcvQQb9RFqCtvFmFU1PvUoTRiUdBtgHA6fONNHU4x796lgzNlVSD3DO/MZNk1s5/ozSMQg=="],
178
+
179
+
"@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-beta.41", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.0.5" }, "cpu": "none" }, "sha512-OAfcO37ME6GGWmj9qTaDT7jY4rM0T2z0/8ujdQIJQ2x2nl+ztO32EIwURfmXOK0U1tzkyuaKYvE34Pug/ucXlQ=="],
180
+
181
+
"@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-beta.41", "", { "os": "win32", "cpu": "arm64" }, "sha512-NIYGuCcuXaq5BC4Q3upbiMBvmZsTsEPG9k/8QKQdmrch+ocSy5Jv9tdpdmXJyighKqm182nh/zBt+tSJkYoNlg=="],
182
+
183
+
"@rolldown/binding-win32-ia32-msvc": ["@rolldown/binding-win32-ia32-msvc@1.0.0-beta.41", "", { "os": "win32", "cpu": "ia32" }, "sha512-kANdsDbE5FkEOb5NrCGBJBCaZ2Sabp3D7d4PRqMYJqyLljwh9mDyYyYSv5+QNvdAmifj+f3lviNEUUuUZPEFPw=="],
184
+
185
+
"@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-beta.41", "", { "os": "win32", "cpu": "x64" }, "sha512-UlpxKmFdik0Y2VjZrgUCgoYArZJiZllXgIipdBRV1hw6uK45UbQabSTW6Kp6enuOu7vouYWftwhuxfpE8J2JAg=="],
186
+
187
+
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.47", "", {}, "sha512-8QagwMH3kNCuzD8EWL8R2YPW5e4OrHNSAHRFDdmFqEwEaD/KcNKjVoumo+gP2vW5eKB2UPbM6vTYiGZX0ixLnw=="],
188
+
189
+
"@rollup/pluginutils": ["@rollup/pluginutils@4.2.1", "", { "dependencies": { "estree-walker": "^2.0.1", "picomatch": "^2.2.2" } }, "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ=="],
190
+
191
+
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.53.3", "", { "os": "android", "cpu": "arm" }, "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w=="],
192
+
193
+
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.53.3", "", { "os": "android", "cpu": "arm64" }, "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w=="],
194
+
195
+
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.53.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA=="],
196
+
197
+
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.53.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ=="],
198
+
199
+
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.53.3", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w=="],
200
+
201
+
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.53.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q=="],
202
+
203
+
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.53.3", "", { "os": "linux", "cpu": "arm" }, "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw=="],
204
+
205
+
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.53.3", "", { "os": "linux", "cpu": "arm" }, "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg=="],
206
+
207
+
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.53.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w=="],
208
+
209
+
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.53.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A=="],
210
+
211
+
"@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.53.3", "", { "os": "linux", "cpu": "none" }, "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g=="],
212
+
213
+
"@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.53.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw=="],
214
+
215
+
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.53.3", "", { "os": "linux", "cpu": "none" }, "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g=="],
216
+
217
+
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.53.3", "", { "os": "linux", "cpu": "none" }, "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A=="],
218
+
219
+
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.53.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg=="],
220
+
221
+
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.53.3", "", { "os": "linux", "cpu": "x64" }, "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w=="],
222
+
223
+
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.53.3", "", { "os": "linux", "cpu": "x64" }, "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q=="],
224
+
225
+
"@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.53.3", "", { "os": "none", "cpu": "arm64" }, "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw=="],
226
+
227
+
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.53.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw=="],
228
+
229
+
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.53.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA=="],
230
+
231
+
"@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.53.3", "", { "os": "win32", "cpu": "x64" }, "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg=="],
232
+
233
+
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.53.3", "", { "os": "win32", "cpu": "x64" }, "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ=="],
234
+
235
+
"@rushstack/node-core-library": ["@rushstack/node-core-library@5.19.0", "", { "dependencies": { "ajv": "~8.13.0", "ajv-draft-04": "~1.0.0", "ajv-formats": "~3.0.1", "fs-extra": "~11.3.0", "import-lazy": "~4.0.0", "jju": "~1.4.0", "resolve": "~1.22.1", "semver": "~7.5.4" }, "peerDependencies": { "@types/node": "*" }, "optionalPeers": ["@types/node"] }, "sha512-BxAopbeWBvNJ6VGiUL+5lbJXywTdsnMeOS8j57Cn/xY10r6sV/gbsTlfYKjzVCUBZATX2eRzJHSMCchsMTGN6A=="],
236
+
237
+
"@rushstack/problem-matcher": ["@rushstack/problem-matcher@0.1.1", "", { "peerDependencies": { "@types/node": "*" }, "optionalPeers": ["@types/node"] }, "sha512-Fm5XtS7+G8HLcJHCWpES5VmeMyjAKaWeyZU5qPzZC+22mPlJzAsOxymHiWIfuirtPckX3aptWws+K2d0BzniJA=="],
238
+
239
+
"@rushstack/rig-package": ["@rushstack/rig-package@0.6.0", "", { "dependencies": { "resolve": "~1.22.1", "strip-json-comments": "~3.1.1" } }, "sha512-ZQmfzsLE2+Y91GF15c65L/slMRVhF6Hycq04D4TwtdGaUAbIXXg9c5pKA5KFU7M4QMaihoobp9JJYpYcaY3zOw=="],
240
+
241
+
"@rushstack/terminal": ["@rushstack/terminal@0.19.4", "", { "dependencies": { "@rushstack/node-core-library": "5.19.0", "@rushstack/problem-matcher": "0.1.1", "supports-color": "~8.1.1" }, "peerDependencies": { "@types/node": "*" }, "optionalPeers": ["@types/node"] }, "sha512-f4XQk02CrKfrMgyOfhYd3qWI944dLC21S4I/LUhrlAP23GTMDNG6EK5effQtFkISwUKCgD9vMBrJZaPSUquxWQ=="],
242
+
243
+
"@rushstack/ts-command-line": ["@rushstack/ts-command-line@5.1.4", "", { "dependencies": { "@rushstack/terminal": "0.19.4", "@types/argparse": "1.0.38", "argparse": "~1.0.9", "string-argv": "~0.3.1" } }, "sha512-H0I6VdJ6sOUbktDFpP2VW5N29w8v4hRoNZOQz02vtEi6ZTYL1Ju8u+TcFiFawUDrUsx/5MQTUhd79uwZZVwVlA=="],
244
+
245
+
"@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="],
246
+
247
+
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
248
+
249
+
"@types/argparse": ["@types/argparse@1.0.38", "", {}, "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA=="],
250
+
251
+
"@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="],
252
+
253
+
"@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="],
254
+
255
+
"@types/babel__template": ["@types/babel__template@7.4.4", "", { "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A=="],
256
+
257
+
"@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="],
258
+
259
+
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
260
+
261
+
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
262
+
263
+
"@types/node": ["@types/node@24.10.1", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ=="],
264
+
265
+
"@types/react": ["@types/react@19.2.7", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg=="],
266
+
267
+
"@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="],
268
+
269
+
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.48.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.48.1", "@typescript-eslint/type-utils": "8.48.1", "@typescript-eslint/utils": "8.48.1", "@typescript-eslint/visitor-keys": "8.48.1", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.48.1", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-X63hI1bxl5ohelzr0LY5coufyl0LJNthld+abwxpCoo6Gq+hSqhKwci7MUWkXo67mzgUK6YFByhmaHmUcuBJmA=="],
270
+
271
+
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.48.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.48.1", "@typescript-eslint/types": "8.48.1", "@typescript-eslint/typescript-estree": "8.48.1", "@typescript-eslint/visitor-keys": "8.48.1", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA=="],
272
+
273
+
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.48.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.48.1", "@typescript-eslint/types": "^8.48.1", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-HQWSicah4s9z2/HifRPQ6b6R7G+SBx64JlFQpgSSHWPKdvCZX57XCbszg/bapbRsOEv42q5tayTYcEFpACcX1w=="],
274
+
275
+
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.48.1", "", { "dependencies": { "@typescript-eslint/types": "8.48.1", "@typescript-eslint/visitor-keys": "8.48.1" } }, "sha512-rj4vWQsytQbLxC5Bf4XwZ0/CKd362DkWMUkviT7DCS057SK64D5lH74sSGzhI6PDD2HCEq02xAP9cX68dYyg1w=="],
276
+
277
+
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.48.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-k0Jhs4CpEffIBm6wPaCXBAD7jxBtrHjrSgtfCjUvPp9AZ78lXKdTR8fxyZO5y4vWNlOvYXRtngSZNSn+H53Jkw=="],
278
+
279
+
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.48.1", "", { "dependencies": { "@typescript-eslint/types": "8.48.1", "@typescript-eslint/typescript-estree": "8.48.1", "@typescript-eslint/utils": "8.48.1", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-1jEop81a3LrJQLTf/1VfPQdhIY4PlGDBc/i67EVWObrtvcziysbLN3oReexHOM6N3jyXgCrkBsZpqwH0hiDOQg=="],
280
+
281
+
"@typescript-eslint/types": ["@typescript-eslint/types@8.48.1", "", {}, "sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q=="],
282
+
283
+
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.48.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.48.1", "@typescript-eslint/tsconfig-utils": "8.48.1", "@typescript-eslint/types": "8.48.1", "@typescript-eslint/visitor-keys": "8.48.1", "debug": "^4.3.4", "minimatch": "^9.0.4", "semver": "^7.6.0", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-/9wQ4PqaefTK6POVTjJaYS0bynCgzh6ClJHGSBj06XEHjkfylzB+A3qvyaXnErEZSaxhIo4YdyBgq6j4RysxDg=="],
284
+
285
+
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.48.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.48.1", "@typescript-eslint/types": "8.48.1", "@typescript-eslint/typescript-estree": "8.48.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-fAnhLrDjiVfey5wwFRwrweyRlCmdz5ZxXz2G/4cLn0YDLjTapmN4gcCsTBR1N2rWnZSDeWpYtgLDsJt+FpmcwA=="],
286
+
287
+
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.48.1", "", { "dependencies": { "@typescript-eslint/types": "8.48.1", "eslint-visitor-keys": "^4.2.1" } }, "sha512-BmxxndzEWhE4TIEEMBs8lP3MBWN3jFPs/p6gPm/wkv02o41hI6cq9AuSmGAaTTHPtA1FTi2jBre4A9rm5ZmX+Q=="],
288
+
289
+
"@vitejs/plugin-react": ["@vitejs/plugin-react@5.1.1", "", { "dependencies": { "@babel/core": "^7.28.5", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.47", "@types/babel__core": "^7.20.5", "react-refresh": "^0.18.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-WQfkSw0QbQ5aJ2CHYw23ZGkqnRwqKHD/KYsMeTkZzPT4Jcf0DcBxBtwMJxnu6E7oxw5+JC6ZAiePgh28uJ1HBA=="],
290
+
291
+
"@volar/language-core": ["@volar/language-core@2.4.26", "", { "dependencies": { "@volar/source-map": "2.4.26" } }, "sha512-hH0SMitMxnB43OZpyF1IFPS9bgb2I3bpCh76m2WEK7BE0A0EzpYsRp0CCH2xNKshr7kacU5TQBLYn4zj7CG60A=="],
292
+
293
+
"@volar/source-map": ["@volar/source-map@2.4.26", "", {}, "sha512-JJw0Tt/kSFsIRmgTQF4JSt81AUSI1aEye5Zl65EeZ8H35JHnTvFGmpDOBn5iOxd48fyGE+ZvZBp5FcgAy/1Qhw=="],
294
+
295
+
"@volar/typescript": ["@volar/typescript@2.4.26", "", { "dependencies": { "@volar/language-core": "2.4.26", "path-browserify": "^1.0.1", "vscode-uri": "^3.0.8" } }, "sha512-N87ecLD48Sp6zV9zID/5yuS1+5foj0DfuYGdQ6KHj/IbKvyKv1zNX6VCmnKYwtmHadEO6mFc2EKISiu3RDPAvA=="],
296
+
297
+
"acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
298
+
299
+
"acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
300
+
301
+
"ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="],
302
+
303
+
"ajv-draft-04": ["ajv-draft-04@1.0.0", "", { "peerDependencies": { "ajv": "^8.5.0" }, "optionalPeers": ["ajv"] }, "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw=="],
304
+
305
+
"ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="],
306
+
307
+
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
308
+
309
+
"ansis": ["ansis@4.2.0", "", {}, "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig=="],
310
+
311
+
"argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
312
+
313
+
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
314
+
315
+
"baseline-browser-mapping": ["baseline-browser-mapping@2.8.32", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-OPz5aBThlyLFgxyhdwf/s2+8ab3OvT7AdTNvKHBwpXomIYeXqpUUuT8LrdtxZSsWJ4R4CU1un4XGh5Ez3nlTpw=="],
316
+
317
+
"brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
318
+
319
+
"browserslist": ["browserslist@4.28.0", "", { "dependencies": { "baseline-browser-mapping": "^2.8.25", "caniuse-lite": "^1.0.30001754", "electron-to-chromium": "^1.5.249", "node-releases": "^2.0.27", "update-browserslist-db": "^1.1.4" }, "bin": { "browserslist": "cli.js" } }, "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ=="],
320
+
321
+
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
322
+
323
+
"caniuse-lite": ["caniuse-lite@1.0.30001759", "", {}, "sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw=="],
324
+
325
+
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
326
+
327
+
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
328
+
329
+
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
330
+
331
+
"commondir": ["commondir@1.0.1", "", {}, "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg=="],
332
+
333
+
"compare-versions": ["compare-versions@6.1.1", "", {}, "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg=="],
334
+
335
+
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
336
+
337
+
"confbox": ["confbox@0.2.2", "", {}, "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ=="],
338
+
339
+
"convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="],
340
+
341
+
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
342
+
343
+
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
344
+
345
+
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
346
+
347
+
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
348
+
349
+
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
350
+
351
+
"diff": ["diff@8.0.2", "", {}, "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg=="],
352
+
353
+
"electron-to-chromium": ["electron-to-chromium@1.5.263", "", {}, "sha512-DrqJ11Knd+lo+dv+lltvfMDLU27g14LMdH2b0O3Pio4uk0x+z7OR+JrmyacTPN2M8w3BrZ7/RTwG3R9B7irPlg=="],
354
+
355
+
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
356
+
357
+
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
358
+
359
+
"eslint": ["eslint@9.39.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.1", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.39.1", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g=="],
360
+
361
+
"eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@5.2.0", "", { "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg=="],
362
+
363
+
"eslint-plugin-react-refresh": ["eslint-plugin-react-refresh@0.4.24", "", { "peerDependencies": { "eslint": ">=8.40" } }, "sha512-nLHIW7TEq3aLrEYWpVaJ1dRgFR+wLDPN8e8FpYAql/bMV2oBEfC37K0gLEGgv9fy66juNShSMV8OkTqzltcG/w=="],
364
+
365
+
"eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="],
366
+
367
+
"eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="],
368
+
369
+
"esm-env": ["esm-env@1.2.2", "", {}, "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA=="],
370
+
371
+
"espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="],
372
+
373
+
"esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="],
374
+
375
+
"esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="],
376
+
377
+
"estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
378
+
379
+
"estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
380
+
381
+
"esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
382
+
383
+
"exsolve": ["exsolve@1.0.8", "", {}, "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA=="],
384
+
385
+
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
386
+
387
+
"fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
388
+
389
+
"fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="],
390
+
391
+
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
392
+
393
+
"file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="],
394
+
395
+
"find-cache-dir": ["find-cache-dir@3.3.2", "", { "dependencies": { "commondir": "^1.0.1", "make-dir": "^3.0.2", "pkg-dir": "^4.1.0" } }, "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig=="],
396
+
397
+
"find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
398
+
399
+
"flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="],
400
+
401
+
"flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="],
402
+
403
+
"fs-extra": ["fs-extra@10.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ=="],
404
+
405
+
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
406
+
407
+
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
408
+
409
+
"gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="],
410
+
411
+
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
412
+
413
+
"globals": ["globals@16.5.0", "", {}, "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ=="],
414
+
415
+
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
416
+
417
+
"graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="],
418
+
419
+
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
420
+
421
+
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
422
+
423
+
"ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
424
+
425
+
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
426
+
427
+
"import-lazy": ["import-lazy@4.0.0", "", {}, "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw=="],
428
+
429
+
"imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
430
+
431
+
"is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="],
432
+
433
+
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
434
+
435
+
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
436
+
437
+
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
438
+
439
+
"jju": ["jju@1.4.0", "", {}, "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA=="],
440
+
441
+
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
442
+
443
+
"js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
444
+
445
+
"jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
446
+
447
+
"json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
448
+
449
+
"json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
450
+
451
+
"json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="],
452
+
453
+
"json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
454
+
455
+
"jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="],
456
+
457
+
"keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
458
+
459
+
"kolorist": ["kolorist@1.8.0", "", {}, "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ=="],
460
+
461
+
"levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
462
+
463
+
"lightningcss": ["lightningcss@1.30.2", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.30.2", "lightningcss-darwin-arm64": "1.30.2", "lightningcss-darwin-x64": "1.30.2", "lightningcss-freebsd-x64": "1.30.2", "lightningcss-linux-arm-gnueabihf": "1.30.2", "lightningcss-linux-arm64-gnu": "1.30.2", "lightningcss-linux-arm64-musl": "1.30.2", "lightningcss-linux-x64-gnu": "1.30.2", "lightningcss-linux-x64-musl": "1.30.2", "lightningcss-win32-arm64-msvc": "1.30.2", "lightningcss-win32-x64-msvc": "1.30.2" } }, "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ=="],
464
+
465
+
"lightningcss-android-arm64": ["lightningcss-android-arm64@1.30.2", "", { "os": "android", "cpu": "arm64" }, "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A=="],
466
+
467
+
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA=="],
468
+
469
+
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ=="],
470
+
471
+
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA=="],
472
+
473
+
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.2", "", { "os": "linux", "cpu": "arm" }, "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA=="],
474
+
475
+
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A=="],
476
+
477
+
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA=="],
478
+
479
+
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w=="],
480
+
481
+
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA=="],
482
+
483
+
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ=="],
484
+
485
+
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw=="],
486
+
487
+
"local-pkg": ["local-pkg@1.1.2", "", { "dependencies": { "mlly": "^1.7.4", "pkg-types": "^2.3.0", "quansync": "^0.2.11" } }, "sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A=="],
488
+
489
+
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
490
+
491
+
"lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
492
+
493
+
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
494
+
495
+
"lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="],
496
+
497
+
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
498
+
499
+
"make-dir": ["make-dir@3.1.0", "", { "dependencies": { "semver": "^6.0.0" } }, "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw=="],
500
+
501
+
"minimatch": ["minimatch@10.0.3", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw=="],
502
+
503
+
"mlly": ["mlly@1.8.0", "", { "dependencies": { "acorn": "^8.15.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.1" } }, "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g=="],
504
+
505
+
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
506
+
507
+
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
508
+
509
+
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
510
+
511
+
"node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="],
512
+
513
+
"optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="],
514
+
515
+
"p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
516
+
517
+
"p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="],
518
+
519
+
"p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="],
520
+
521
+
"parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
522
+
523
+
"path-browserify": ["path-browserify@1.0.1", "", {}, "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="],
524
+
525
+
"path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
526
+
527
+
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
528
+
529
+
"path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
530
+
531
+
"pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
532
+
533
+
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
534
+
535
+
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
536
+
537
+
"pkg-dir": ["pkg-dir@4.2.0", "", { "dependencies": { "find-up": "^4.0.0" } }, "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ=="],
538
+
539
+
"pkg-types": ["pkg-types@2.3.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig=="],
540
+
541
+
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
542
+
543
+
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
544
+
545
+
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
546
+
547
+
"quansync": ["quansync@0.2.11", "", {}, "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA=="],
548
+
549
+
"react": ["react@19.2.0", "", {}, "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ=="],
550
+
551
+
"react-dom": ["react-dom@19.2.0", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.0" } }, "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ=="],
552
+
553
+
"react-refresh": ["react-refresh@0.18.0", "", {}, "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw=="],
554
+
555
+
"require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="],
556
+
557
+
"resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="],
558
+
559
+
"resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
560
+
561
+
"rolldown": ["rolldown@1.0.0-beta.41", "", { "dependencies": { "@oxc-project/types": "=0.93.0", "@rolldown/pluginutils": "1.0.0-beta.41", "ansis": "=4.2.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-beta.41", "@rolldown/binding-darwin-arm64": "1.0.0-beta.41", "@rolldown/binding-darwin-x64": "1.0.0-beta.41", "@rolldown/binding-freebsd-x64": "1.0.0-beta.41", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.41", "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.41", "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.41", "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.41", "@rolldown/binding-linux-x64-musl": "1.0.0-beta.41", "@rolldown/binding-openharmony-arm64": "1.0.0-beta.41", "@rolldown/binding-wasm32-wasi": "1.0.0-beta.41", "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.41", "@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.41", "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.41" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-U+NPR0Bkg3wm61dteD2L4nAM1U9dtaqVrpDXwC36IKRHpEO/Ubpid4Nijpa2imPchcVNHfxVFwSSMJdwdGFUbg=="],
562
+
563
+
"rollup": ["rollup@4.53.3", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.53.3", "@rollup/rollup-android-arm64": "4.53.3", "@rollup/rollup-darwin-arm64": "4.53.3", "@rollup/rollup-darwin-x64": "4.53.3", "@rollup/rollup-freebsd-arm64": "4.53.3", "@rollup/rollup-freebsd-x64": "4.53.3", "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", "@rollup/rollup-linux-arm-musleabihf": "4.53.3", "@rollup/rollup-linux-arm64-gnu": "4.53.3", "@rollup/rollup-linux-arm64-musl": "4.53.3", "@rollup/rollup-linux-loong64-gnu": "4.53.3", "@rollup/rollup-linux-ppc64-gnu": "4.53.3", "@rollup/rollup-linux-riscv64-gnu": "4.53.3", "@rollup/rollup-linux-riscv64-musl": "4.53.3", "@rollup/rollup-linux-s390x-gnu": "4.53.3", "@rollup/rollup-linux-x64-gnu": "4.53.3", "@rollup/rollup-linux-x64-musl": "4.53.3", "@rollup/rollup-openharmony-arm64": "4.53.3", "@rollup/rollup-win32-arm64-msvc": "4.53.3", "@rollup/rollup-win32-ia32-msvc": "4.53.3", "@rollup/rollup-win32-x64-gnu": "4.53.3", "@rollup/rollup-win32-x64-msvc": "4.53.3", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA=="],
564
+
565
+
"rollup-plugin-typescript2": ["rollup-plugin-typescript2@0.36.0", "", { "dependencies": { "@rollup/pluginutils": "^4.1.2", "find-cache-dir": "^3.3.2", "fs-extra": "^10.0.0", "semver": "^7.5.4", "tslib": "^2.6.2" }, "peerDependencies": { "rollup": ">=1.26.3", "typescript": ">=2.4.0" } }, "sha512-NB2CSQDxSe9+Oe2ahZbf+B4bh7pHwjV5L+RSYpCu7Q5ROuN94F9b6ioWwKfz3ueL3KTtmX4o2MUH2cgHDIEUsw=="],
566
+
567
+
"scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
568
+
569
+
"semver": ["semver@7.5.4", "", { "dependencies": { "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" } }, "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA=="],
570
+
571
+
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
572
+
573
+
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
574
+
575
+
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
576
+
577
+
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
578
+
579
+
"sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="],
580
+
581
+
"string-argv": ["string-argv@0.3.2", "", {}, "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q=="],
582
+
583
+
"strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
584
+
585
+
"supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
586
+
587
+
"supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
588
+
589
+
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
590
+
591
+
"ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="],
592
+
593
+
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
594
+
595
+
"type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
596
+
597
+
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
598
+
599
+
"typescript-eslint": ["typescript-eslint@8.48.1", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.48.1", "@typescript-eslint/parser": "8.48.1", "@typescript-eslint/typescript-estree": "8.48.1", "@typescript-eslint/utils": "8.48.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-FbOKN1fqNoXp1hIl5KYpObVrp0mCn+CLgn479nmu2IsRMrx2vyv74MmsBLVlhg8qVwNFGbXSp8fh1zp8pEoC2A=="],
600
+
601
+
"ufo": ["ufo@1.6.1", "", {}, "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA=="],
602
+
603
+
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
604
+
605
+
"universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="],
606
+
607
+
"unplugin": ["unplugin@2.3.11", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "acorn": "^8.15.0", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww=="],
608
+
609
+
"unplugin-dts": ["unplugin-dts@1.0.0-beta.6", "", { "dependencies": { "@rollup/pluginutils": "^5.1.4", "@volar/typescript": "^2.4.17", "compare-versions": "^6.1.1", "debug": "^4.4.0", "kolorist": "^1.8.0", "local-pkg": "^1.1.1", "magic-string": "^0.30.17", "unplugin": "^2.3.2" }, "peerDependencies": { "@microsoft/api-extractor": ">=7", "@rspack/core": "^1", "@vue/language-core": "~3.0.1", "esbuild": "*", "rolldown": "*", "rollup": ">=3", "typescript": ">=4", "vite": ">=3", "webpack": "^4 || ^5" }, "optionalPeers": ["@microsoft/api-extractor", "@rspack/core", "@vue/language-core", "esbuild", "rolldown", "rollup", "vite", "webpack"] }, "sha512-+xbFv5aVFtLZFNBAKI4+kXmd2h+T42/AaP8Bsp0YP/je/uOTN94Ame2Xt3e9isZS+Z7/hrLCLbsVJh+saqFMfQ=="],
610
+
611
+
"update-browserslist-db": ["update-browserslist-db@1.1.4", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A=="],
612
+
613
+
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
614
+
615
+
"vite": ["rolldown-vite@7.1.14", "", { "dependencies": { "@oxc-project/runtime": "0.92.0", "fdir": "^6.5.0", "lightningcss": "^1.30.1", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rolldown": "1.0.0-beta.41", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "esbuild": "^0.25.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-eSiiRJmovt8qDJkGyZuLnbxAOAdie6NCmmd0NkTC0RJI9duiSBTfr8X2mBYJOUFzxQa2USaHmL99J9uMxkjCyw=="],
616
+
617
+
"vscode-uri": ["vscode-uri@3.1.0", "", {}, "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ=="],
618
+
619
+
"webpack-virtual-modules": ["webpack-virtual-modules@0.6.2", "", {}, "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="],
620
+
621
+
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
622
+
623
+
"word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
624
+
625
+
"yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
626
+
627
+
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
628
+
629
+
"@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
630
+
631
+
"@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
632
+
633
+
"@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
634
+
635
+
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
636
+
637
+
"@eslint/config-array/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
638
+
639
+
"@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="],
640
+
641
+
"@eslint/eslintrc/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
642
+
643
+
"@microsoft/api-extractor/typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="],
644
+
645
+
"@microsoft/tsdoc-config/ajv": ["ajv@8.12.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js": "^4.2.2" } }, "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA=="],
646
+
647
+
"@rollup/pluginutils/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
648
+
649
+
"@rushstack/node-core-library/ajv": ["ajv@8.13.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js": "^4.4.1" } }, "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA=="],
650
+
651
+
"@rushstack/node-core-library/fs-extra": ["fs-extra@11.3.2", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A=="],
652
+
653
+
"@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
654
+
655
+
"@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
656
+
657
+
"@typescript-eslint/typescript-estree/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
658
+
659
+
"ajv-formats/ajv": ["ajv@8.13.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js": "^4.4.1" } }, "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA=="],
660
+
661
+
"chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
662
+
663
+
"eslint/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
664
+
665
+
"js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
666
+
667
+
"make-dir/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
668
+
669
+
"mlly/pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="],
670
+
671
+
"pkg-dir/find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="],
672
+
673
+
"rolldown/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.41", "", {}, "sha512-ycMEPrS3StOIeb87BT3/+bu+blEtyvwQ4zmo2IcJQy0Rd1DAAhKksA0iUZ3MYSpJtjlPhg0Eo6mvVS6ggPhRbw=="],
674
+
675
+
"rollup-plugin-typescript2/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
676
+
677
+
"unplugin-dts/@rollup/pluginutils": ["@rollup/pluginutils@5.3.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q=="],
678
+
679
+
"@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
680
+
681
+
"@microsoft/tsdoc-config/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
682
+
683
+
"@rushstack/node-core-library/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
684
+
685
+
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
686
+
687
+
"ajv-formats/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
688
+
689
+
"mlly/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="],
690
+
691
+
"pkg-dir/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="],
692
+
693
+
"pkg-dir/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="],
694
+
695
+
"pkg-dir/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
696
+
}
697
+
}
+325
-107
lib/components/BlueskyPost.tsx
+325
-107
lib/components/BlueskyPost.tsx
···
7
7
import { useBlob } from "../hooks/useBlob";
8
8
import { BLUESKY_PROFILE_COLLECTION } from "./BlueskyProfile";
9
9
import { getAvatarCid } from "../utils/profile";
10
-
import { formatDidForLabel } from "../utils/at-uri";
10
+
import { formatDidForLabel, parseAtUri } from "../utils/at-uri";
11
+
import { isBlobWithCdn } from "../utils/blob";
11
12
12
13
/**
13
14
* Props for rendering a single Bluesky post with optional customization hooks.
···
38
39
* React node displayed while the post fetch is actively loading.
39
40
*/
40
41
loadingIndicator?: React.ReactNode;
41
-
/**
42
-
* Preferred color scheme to pass through to renderers.
43
-
*/
44
-
colorScheme?: "light" | "dark" | "system";
42
+
45
43
/**
46
44
* Whether the default renderer should show the Bluesky icon.
47
45
* Defaults to `true`.
···
52
50
* Defaults to `'timestamp'`.
53
51
*/
54
52
iconPlacement?: "cardBottomRight" | "timestamp" | "linkInline";
53
+
/**
54
+
* Controls whether to show the parent post if this post is a reply.
55
+
* Defaults to `false`.
56
+
*/
57
+
showParent?: boolean;
58
+
/**
59
+
* Controls whether to recursively show all parent posts to the root.
60
+
* Only applies when `showParent` is `true`. Defaults to `false`.
61
+
*/
62
+
recursiveParent?: boolean;
55
63
}
56
64
57
65
/**
···
75
83
*/
76
84
authorHandle: string;
77
85
/**
86
+
* The author's display name from their profile.
87
+
*/
88
+
authorDisplayName?: string;
89
+
/**
78
90
* The DID that owns the post record.
79
91
*/
80
92
authorDid: string;
···
82
94
* Resolved URL for the author's avatar blob, if available.
83
95
*/
84
96
avatarUrl?: string;
85
-
/**
86
-
* Preferred color scheme bubbled down to children.
87
-
*/
88
-
colorScheme?: "light" | "dark" | "system";
97
+
89
98
/**
90
99
* Placement strategy for the Bluesky icon.
91
100
*/
···
102
111
* Optional override for the rendered embed contents.
103
112
*/
104
113
embed?: React.ReactNode;
114
+
/**
115
+
* Whether this post is part of a thread.
116
+
*/
117
+
isInThread?: boolean;
118
+
/**
119
+
* Depth of this post in a thread (0 = root, 1 = first reply, etc.).
120
+
*/
121
+
threadDepth?: number;
122
+
/**
123
+
* Whether to show border even when in thread context.
124
+
*/
125
+
showThreadBorder?: boolean;
105
126
};
106
127
107
-
/** NSID for the canonical Bluesky feed post collection. */
108
128
export const BLUESKY_POST_COLLECTION = "app.bsky.feed.post";
109
129
130
+
const threadContainerStyle: React.CSSProperties = {
131
+
display: "flex",
132
+
flexDirection: "column",
133
+
maxWidth: "600px",
134
+
width: "100%",
135
+
background: "var(--atproto-color-bg)",
136
+
position: "relative",
137
+
borderRadius: "12px",
138
+
overflow: "hidden"
139
+
};
140
+
141
+
const parentPostStyle: React.CSSProperties = {
142
+
position: "relative",
143
+
};
144
+
145
+
const replyPostStyle: React.CSSProperties = {
146
+
position: "relative",
147
+
};
148
+
149
+
const loadingStyle: React.CSSProperties = {
150
+
padding: "24px 18px",
151
+
fontSize: "14px",
152
+
textAlign: "center",
153
+
color: "var(--atproto-color-text-secondary)",
154
+
};
155
+
110
156
/**
111
157
* Fetches a Bluesky feed post, resolves metadata such as author handle and avatar,
112
158
* and renders it via a customizable renderer component.
113
159
*
114
160
* @param did - DID of the repository that stores the post.
115
161
* @param rkey - Record key for the post within the feed collection.
162
+
* @param record - Prefetched record for the post.
116
163
* @param renderer - Optional renderer component to override the default.
117
164
* @param fallback - Node rendered before the first fetch attempt resolves.
118
165
* @param loadingIndicator - Node rendered while the post is loading.
119
-
* @param colorScheme - Preferred color scheme forwarded to downstream components.
120
166
* @param showIcon - Controls whether the Bluesky icon should render alongside the post. Defaults to `true`.
121
167
* @param iconPlacement - Determines where the icon is positioned in the rendered post. Defaults to `'timestamp'`.
122
168
* @returns A component that renders loading/fallback states and the resolved post.
123
169
*/
124
-
export const BlueskyPost: React.FC<BlueskyPostProps> = ({
125
-
did: handleOrDid,
126
-
rkey,
127
-
record,
128
-
renderer,
129
-
fallback,
130
-
loadingIndicator,
131
-
colorScheme,
132
-
showIcon = true,
133
-
iconPlacement = "timestamp",
134
-
}) => {
135
-
const {
136
-
did: resolvedDid,
137
-
handle,
138
-
loading: resolvingIdentity,
139
-
error: resolutionError,
140
-
} = useDidResolution(handleOrDid);
141
-
const repoIdentifier = resolvedDid ?? handleOrDid;
142
-
const { record: profile } = useAtProtoRecord<ProfileRecord>({
143
-
did: repoIdentifier,
144
-
collection: BLUESKY_PROFILE_COLLECTION,
145
-
rkey: "self",
146
-
});
147
-
const avatarCid = getAvatarCid(profile);
170
+
export const BlueskyPost: React.FC<BlueskyPostProps> = React.memo(
171
+
({
172
+
did: handleOrDid,
173
+
rkey,
174
+
record,
175
+
renderer,
176
+
fallback,
177
+
loadingIndicator,
178
+
showIcon = true,
179
+
iconPlacement = "timestamp",
180
+
showParent = false,
181
+
recursiveParent = false,
182
+
}) => {
183
+
const {
184
+
did: resolvedDid,
185
+
handle,
186
+
loading: resolvingIdentity,
187
+
error: resolutionError,
188
+
} = useDidResolution(handleOrDid);
189
+
const repoIdentifier = resolvedDid ?? handleOrDid;
190
+
const { record: profile } = useAtProtoRecord<ProfileRecord>({
191
+
did: repoIdentifier,
192
+
collection: BLUESKY_PROFILE_COLLECTION,
193
+
rkey: "self",
194
+
});
195
+
const avatar = profile?.avatar;
196
+
const avatarCdnUrl = isBlobWithCdn(avatar) ? avatar.cdnUrl : undefined;
197
+
const avatarCid = avatarCdnUrl ? undefined : getAvatarCid(profile);
198
+
const authorDisplayName = profile?.displayName;
148
199
149
-
const Comp: React.ComponentType<BlueskyPostRendererInjectedProps> = useMemo(
150
-
() => renderer ?? ((props) => <BlueskyPostRenderer {...props} />),
151
-
[renderer]
152
-
);
200
+
const {
201
+
record: fetchedRecord,
202
+
loading: currentLoading,
203
+
error: currentError,
204
+
} = useAtProtoRecord<FeedPostRecord>({
205
+
did: showParent && !record ? repoIdentifier : "",
206
+
collection: showParent && !record ? BLUESKY_POST_COLLECTION : "",
207
+
rkey: showParent && !record ? rkey : "",
208
+
});
153
209
154
-
const displayHandle =
155
-
handle ?? (handleOrDid.startsWith("did:") ? undefined : handleOrDid);
156
-
const authorHandle =
157
-
displayHandle ?? formatDidForLabel(resolvedDid ?? handleOrDid);
158
-
const atUri = resolvedDid
159
-
? `at://${resolvedDid}/${BLUESKY_POST_COLLECTION}/${rkey}`
160
-
: undefined;
210
+
const currentRecord = record ?? fetchedRecord;
161
211
162
-
const Wrapped = useMemo(() => {
163
-
const WrappedComponent: React.FC<{
164
-
record: FeedPostRecord;
165
-
loading: boolean;
166
-
error?: Error;
167
-
}> = (props) => {
168
-
const { url: avatarUrl } = useBlob(repoIdentifier, avatarCid);
212
+
const parentUri = currentRecord?.reply?.parent?.uri;
213
+
const parsedParentUri = parentUri ? parseAtUri(parentUri) : null;
214
+
const parentDid = parsedParentUri?.did;
215
+
const parentRkey = parsedParentUri?.rkey;
216
+
217
+
const {
218
+
record: parentRecord,
219
+
loading: parentLoading,
220
+
error: parentError,
221
+
} = useAtProtoRecord<FeedPostRecord>({
222
+
did: showParent && parentDid ? parentDid : "",
223
+
collection: showParent && parentDid ? BLUESKY_POST_COLLECTION : "",
224
+
rkey: showParent && parentRkey ? parentRkey : "",
225
+
});
226
+
227
+
const Comp: React.ComponentType<BlueskyPostRendererInjectedProps> =
228
+
useMemo(
229
+
() =>
230
+
renderer ?? ((props) => <BlueskyPostRenderer {...props} />),
231
+
[renderer],
232
+
);
233
+
234
+
const displayHandle =
235
+
handle ??
236
+
(handleOrDid.startsWith("did:") ? undefined : handleOrDid);
237
+
const authorHandle =
238
+
displayHandle ?? formatDidForLabel(resolvedDid ?? handleOrDid);
239
+
const atUri = resolvedDid
240
+
? `at://${resolvedDid}/${BLUESKY_POST_COLLECTION}/${rkey}`
241
+
: undefined;
242
+
243
+
const Wrapped = useMemo(() => {
244
+
const WrappedComponent: React.FC<{
245
+
record: FeedPostRecord;
246
+
loading: boolean;
247
+
error?: Error;
248
+
}> = (props) => {
249
+
const { url: avatarUrlFromBlob } = useBlob(
250
+
repoIdentifier,
251
+
avatarCid,
252
+
);
253
+
const avatarUrl = avatarCdnUrl || avatarUrlFromBlob;
254
+
return (
255
+
<Comp
256
+
{...props}
257
+
authorHandle={authorHandle}
258
+
authorDisplayName={authorDisplayName}
259
+
authorDid={repoIdentifier}
260
+
avatarUrl={avatarUrl}
261
+
iconPlacement={iconPlacement}
262
+
showIcon={showIcon}
263
+
atUri={atUri}
264
+
isInThread
265
+
threadDepth={showParent ? 1 : 0}
266
+
showThreadBorder={!showParent && !!props.record?.reply?.parent}
267
+
/>
268
+
);
269
+
};
270
+
WrappedComponent.displayName = "BlueskyPostWrappedRenderer";
271
+
return WrappedComponent;
272
+
}, [
273
+
Comp,
274
+
repoIdentifier,
275
+
avatarCid,
276
+
avatarCdnUrl,
277
+
authorHandle,
278
+
authorDisplayName,
279
+
iconPlacement,
280
+
showIcon,
281
+
atUri,
282
+
showParent,
283
+
]);
284
+
285
+
const WrappedWithoutIcon = useMemo(() => {
286
+
const WrappedComponent: React.FC<{
287
+
record: FeedPostRecord;
288
+
loading: boolean;
289
+
error?: Error;
290
+
}> = (props) => {
291
+
const { url: avatarUrlFromBlob } = useBlob(
292
+
repoIdentifier,
293
+
avatarCid,
294
+
);
295
+
const avatarUrl = avatarCdnUrl || avatarUrlFromBlob;
296
+
return (
297
+
<Comp
298
+
{...props}
299
+
authorHandle={authorHandle}
300
+
authorDisplayName={authorDisplayName}
301
+
authorDid={repoIdentifier}
302
+
avatarUrl={avatarUrl}
303
+
iconPlacement={iconPlacement}
304
+
showIcon={false}
305
+
atUri={atUri}
306
+
isInThread
307
+
threadDepth={showParent ? 1 : 0}
308
+
showThreadBorder={!showParent && !!props.record?.reply?.parent}
309
+
/>
310
+
);
311
+
};
312
+
WrappedComponent.displayName = "BlueskyPostWrappedRendererWithoutIcon";
313
+
return WrappedComponent;
314
+
}, [
315
+
Comp,
316
+
repoIdentifier,
317
+
avatarCid,
318
+
avatarCdnUrl,
319
+
authorHandle,
320
+
authorDisplayName,
321
+
iconPlacement,
322
+
atUri,
323
+
showParent,
324
+
]);
325
+
326
+
if (!displayHandle && resolvingIdentity) {
327
+
return <div style={{ padding: 8 }}>Resolving handleโฆ</div>;
328
+
}
329
+
if (!displayHandle && resolutionError) {
169
330
return (
170
-
<Comp
171
-
{...props}
172
-
authorHandle={authorHandle}
173
-
authorDid={repoIdentifier}
174
-
avatarUrl={avatarUrl}
175
-
colorScheme={colorScheme}
176
-
iconPlacement={iconPlacement}
177
-
showIcon={showIcon}
178
-
atUri={atUri}
331
+
<div style={{ padding: 8, color: "crimson" }}>
332
+
Could not resolve handle.
333
+
</div>
334
+
);
335
+
}
336
+
337
+
const renderMainPost = (mainRecord?: FeedPostRecord) => {
338
+
if (mainRecord !== undefined) {
339
+
return (
340
+
<AtProtoRecord<FeedPostRecord>
341
+
record={mainRecord}
342
+
renderer={Wrapped}
343
+
fallback={fallback}
344
+
loadingIndicator={loadingIndicator}
345
+
/>
346
+
);
347
+
}
348
+
349
+
return (
350
+
<AtProtoRecord<FeedPostRecord>
351
+
did={repoIdentifier}
352
+
collection={BLUESKY_POST_COLLECTION}
353
+
rkey={rkey}
354
+
renderer={Wrapped}
355
+
fallback={fallback}
356
+
loadingIndicator={loadingIndicator}
179
357
/>
180
358
);
181
359
};
182
-
WrappedComponent.displayName = "BlueskyPostWrappedRenderer";
183
-
return WrappedComponent;
184
-
}, [
185
-
Comp,
186
-
repoIdentifier,
187
-
avatarCid,
188
-
authorHandle,
189
-
colorScheme,
190
-
iconPlacement,
191
-
showIcon,
192
-
atUri,
193
-
]);
194
360
195
-
if (!displayHandle && resolvingIdentity) {
196
-
return <div style={{ padding: 8 }}>Resolving handleโฆ</div>;
197
-
}
198
-
if (!displayHandle && resolutionError) {
199
-
return (
200
-
<div style={{ padding: 8, color: "crimson" }}>
201
-
Could not resolve handle.
202
-
</div>
203
-
);
204
-
}
361
+
const renderMainPostWithoutIcon = (mainRecord?: FeedPostRecord) => {
362
+
if (mainRecord !== undefined) {
363
+
return (
364
+
<AtProtoRecord<FeedPostRecord>
365
+
record={mainRecord}
366
+
renderer={WrappedWithoutIcon}
367
+
fallback={fallback}
368
+
loadingIndicator={loadingIndicator}
369
+
/>
370
+
);
371
+
}
205
372
206
-
// When record is provided, pass it directly to skip fetching
207
-
if (record) {
208
-
return (
209
-
<AtProtoRecord<FeedPostRecord>
210
-
record={record}
211
-
renderer={Wrapped}
212
-
fallback={fallback}
213
-
loadingIndicator={loadingIndicator}
214
-
/>
215
-
);
216
-
}
373
+
return (
374
+
<AtProtoRecord<FeedPostRecord>
375
+
did={repoIdentifier}
376
+
collection={BLUESKY_POST_COLLECTION}
377
+
rkey={rkey}
378
+
renderer={WrappedWithoutIcon}
379
+
fallback={fallback}
380
+
loadingIndicator={loadingIndicator}
381
+
/>
382
+
);
383
+
};
217
384
218
-
// Otherwise fetch the record using did, collection, and rkey
219
-
return (
220
-
<AtProtoRecord<FeedPostRecord>
221
-
did={repoIdentifier}
222
-
collection={BLUESKY_POST_COLLECTION}
223
-
rkey={rkey}
224
-
renderer={Wrapped}
225
-
fallback={fallback}
226
-
loadingIndicator={loadingIndicator}
227
-
/>
228
-
);
229
-
};
385
+
if (showParent) {
386
+
if (currentLoading || (parentLoading && !parentRecord)) {
387
+
return (
388
+
<div style={threadContainerStyle}>
389
+
<div style={loadingStyle}>Loading threadโฆ</div>
390
+
</div>
391
+
);
392
+
}
393
+
394
+
if (currentError) {
395
+
return (
396
+
<div style={{ padding: 8, color: "crimson" }}>
397
+
Failed to load post.
398
+
</div>
399
+
);
400
+
}
401
+
402
+
if (!parentDid || !parentRkey) {
403
+
return renderMainPost(record);
404
+
}
405
+
406
+
if (parentError) {
407
+
return (
408
+
<div style={{ padding: 8, color: "crimson" }}>
409
+
Failed to load parent post.
410
+
</div>
411
+
);
412
+
}
413
+
414
+
return (
415
+
<div style={threadContainerStyle}>
416
+
<div style={parentPostStyle}>
417
+
{recursiveParent && parentRecord?.reply?.parent?.uri ? (
418
+
<BlueskyPost
419
+
did={parentDid}
420
+
rkey={parentRkey}
421
+
record={parentRecord}
422
+
showParent={true}
423
+
recursiveParent={true}
424
+
showIcon={showIcon}
425
+
iconPlacement={iconPlacement}
426
+
/>
427
+
) : (
428
+
<BlueskyPost
429
+
did={parentDid}
430
+
rkey={parentRkey}
431
+
record={parentRecord}
432
+
showIcon={showIcon}
433
+
iconPlacement={iconPlacement}
434
+
/>
435
+
)}
436
+
</div>
437
+
438
+
<div style={replyPostStyle}>
439
+
{renderMainPostWithoutIcon(record || currentRecord)}
440
+
</div>
441
+
</div>
442
+
);
443
+
}
444
+
445
+
return renderMainPost(record);
446
+
},
447
+
);
230
448
231
449
export default BlueskyPost;
+355
-268
lib/components/BlueskyPostList.tsx
+355
-268
lib/components/BlueskyPostList.tsx
···
4
4
type AuthorFeedReason,
5
5
type ReplyParentInfo,
6
6
} from "../hooks/usePaginatedRecords";
7
-
import { useColorScheme } from "../hooks/useColorScheme";
8
-
import type { FeedPostRecord } from "../types/bluesky";
7
+
import type { FeedPostRecord, ProfileRecord } from "../types/bluesky";
9
8
import { useDidResolution } from "../hooks/useDidResolution";
10
9
import { BlueskyIcon } from "./BlueskyIcon";
11
10
import { parseAtUri } from "../utils/at-uri";
11
+
import { useAtProto } from "../providers/AtProtoProvider";
12
+
import { useAtProtoRecord } from "../hooks/useAtProtoRecord";
13
+
import { useBlob } from "../hooks/useBlob";
14
+
import { getAvatarCid } from "../utils/profile";
15
+
import { isBlobWithCdn } from "../utils/blob";
16
+
import { BLUESKY_PROFILE_COLLECTION } from "./BlueskyProfile";
17
+
import { RichText as BlueskyRichText } from "./RichText";
12
18
13
19
/**
14
20
* Options for rendering a paginated list of Bluesky posts.
···
26
32
* Enables pagination controls when `true`. Defaults to `true`.
27
33
*/
28
34
enablePagination?: boolean;
29
-
/**
30
-
* Preferred color scheme passed through to styling helpers.
31
-
* Defaults to `'system'` which follows the OS preference.
32
-
*/
33
-
colorScheme?: "light" | "dark" | "system";
34
35
}
35
36
36
37
/**
···
39
40
* @param did - DID whose posts should be displayed.
40
41
* @param limit - Maximum number of posts per page. Default `5`.
41
42
* @param enablePagination - Whether pagination controls should render. Default `true`.
42
-
* @param colorScheme - Preferred color scheme used for styling. Default `'system'`.
43
43
* @returns A card-like list element with loading, empty, and error handling.
44
44
*/
45
-
export const BlueskyPostList: React.FC<BlueskyPostListProps> = ({
45
+
export const BlueskyPostList: React.FC<BlueskyPostListProps> = React.memo(({
46
46
did,
47
47
limit = 5,
48
48
enablePagination = true,
49
-
colorScheme = "system",
50
49
}) => {
51
-
const scheme = useColorScheme(colorScheme);
52
-
const palette: ListPalette = scheme === "dark" ? darkPalette : lightPalette;
53
50
const { handle: resolvedHandle, did: resolvedDid } = useDidResolution(did);
54
51
const actorLabel = resolvedHandle ?? formatDid(did);
55
52
const actorPath = resolvedHandle ?? resolvedDid ?? did;
···
82
79
83
80
if (error)
84
81
return (
85
-
<div style={{ padding: 8, color: "crimson" }}>
82
+
<div role="alert" style={{ padding: 8, color: "crimson" }}>
86
83
Failed to load posts.
87
84
</div>
88
85
);
89
86
90
87
return (
91
-
<div style={{ ...listStyles.card, ...palette.card }}>
92
-
<div style={{ ...listStyles.header, ...palette.header }}>
88
+
<div style={{ ...listStyles.card, background: `var(--atproto-color-bg)`, borderWidth: "1px", borderStyle: "solid", borderColor: `var(--atproto-color-border)` }}>
89
+
<div style={{ ...listStyles.header, background: `var(--atproto-color-bg-elevated)`, color: `var(--atproto-color-text)` }}>
93
90
<div style={listStyles.headerInfo}>
94
91
<div style={listStyles.headerIcon}>
95
92
<BlueskyIcon size={20} />
···
99
96
<span
100
97
style={{
101
98
...listStyles.subtitle,
102
-
...palette.subtitle,
99
+
color: `var(--atproto-color-text-secondary)`,
103
100
}}
104
101
>
105
102
@{actorLabel}
···
108
105
</div>
109
106
{pageLabel && (
110
107
<span
111
-
style={{ ...listStyles.pageMeta, ...palette.pageMeta }}
108
+
style={{ ...listStyles.pageMeta, color: `var(--atproto-color-text-secondary)` }}
112
109
>
113
110
{pageLabel}
114
111
</span>
···
116
113
</div>
117
114
<div style={listStyles.items}>
118
115
{loading && records.length === 0 && (
119
-
<div style={{ ...listStyles.empty, ...palette.empty }}>
116
+
<div style={{ ...listStyles.empty, color: `var(--atproto-color-text-secondary)` }}>
120
117
Loading postsโฆ
121
118
</div>
122
119
)}
···
126
123
record={record.value}
127
124
rkey={record.rkey}
128
125
did={actorPath}
126
+
uri={record.uri}
129
127
reason={record.reason}
130
128
replyParent={record.replyParent}
131
-
palette={palette}
132
129
hasDivider={idx < records.length - 1}
133
130
/>
134
131
))}
135
132
{!loading && records.length === 0 && (
136
-
<div style={{ ...listStyles.empty, ...palette.empty }}>
133
+
<div style={{ ...listStyles.empty, color: `var(--atproto-color-text-secondary)` }}>
137
134
No posts found.
138
135
</div>
139
136
)}
140
137
</div>
141
138
{enablePagination && (
142
-
<div style={{ ...listStyles.footer, ...palette.footer }}>
139
+
<div style={{ ...listStyles.footer, borderTopColor: `var(--atproto-color-border)`, color: `var(--atproto-color-text)` }}>
143
140
<button
144
141
type="button"
145
142
style={{
146
-
...listStyles.navButton,
147
-
...palette.navButton,
143
+
...listStyles.pageButton,
144
+
background: `var(--atproto-color-button-bg)`,
145
+
color: `var(--atproto-color-button-text)`,
148
146
cursor: hasPrev ? "pointer" : "not-allowed",
149
147
opacity: hasPrev ? 1 : 0.5,
150
148
}}
···
157
155
<span
158
156
style={{
159
157
...listStyles.pageChipActive,
160
-
...palette.pageChipActive,
158
+
color: `var(--atproto-color-button-text)`,
159
+
background: `var(--atproto-color-button-bg)`,
160
+
borderWidth: "1px",
161
+
borderStyle: "solid",
162
+
borderColor: `var(--atproto-color-button-bg)`,
161
163
}}
162
164
>
163
165
{pageIndex + 1}
···
166
168
<span
167
169
style={{
168
170
...listStyles.pageChip,
169
-
...palette.pageChip,
171
+
color: `var(--atproto-color-text-secondary)`,
172
+
borderWidth: "1px",
173
+
borderStyle: "solid",
174
+
borderColor: `var(--atproto-color-border)`,
175
+
background: `var(--atproto-color-bg)`,
170
176
}}
171
177
>
172
178
{pageIndex + 2}
···
176
182
<button
177
183
type="button"
178
184
style={{
179
-
...listStyles.navButton,
180
-
...palette.navButton,
185
+
...listStyles.pageButton,
186
+
background: `var(--atproto-color-button-bg)`,
187
+
color: `var(--atproto-color-button-text)`,
181
188
cursor: hasNext ? "pointer" : "not-allowed",
182
189
opacity: hasNext ? 1 : 0.5,
183
190
}}
···
190
197
)}
191
198
{loading && records.length > 0 && (
192
199
<div
193
-
style={{ ...listStyles.loadingBar, ...palette.loadingBar }}
200
+
style={{ ...listStyles.loadingBar, background: `var(--atproto-color-bg-elevated)`, color: `var(--atproto-color-text-secondary)` }}
194
201
>
195
202
Updatingโฆ
196
203
</div>
197
204
)}
198
205
</div>
199
206
);
200
-
};
207
+
});
201
208
202
209
interface ListRowProps {
203
210
record: FeedPostRecord;
204
211
rkey: string;
205
212
did: string;
213
+
uri?: string;
206
214
reason?: AuthorFeedReason;
207
215
replyParent?: ReplyParentInfo;
208
-
palette: ListPalette;
209
216
hasDivider: boolean;
210
217
}
211
218
···
213
220
record,
214
221
rkey,
215
222
did,
223
+
uri,
216
224
reason,
217
225
replyParent,
218
-
palette,
219
226
hasDivider,
220
227
}) => {
228
+
const { blueskyAppBaseUrl } = useAtProto();
221
229
const text = record.text?.trim() ?? "";
222
230
const relative = record.createdAt
223
231
? formatRelativeTime(record.createdAt)
···
225
233
const absolute = record.createdAt
226
234
? new Date(record.createdAt).toLocaleString()
227
235
: undefined;
228
-
const href = `https://bsky.app/profile/${did}/post/${rkey}`;
229
-
const repostLabel =
230
-
reason?.$type === "app.bsky.feed.defs#reasonRepost"
231
-
? `${formatActor(reason.by) ?? "Someone"} reposted`
232
-
: undefined;
236
+
237
+
// Parse the URI to get the actual post's DID and rkey
238
+
const parsedUri = uri ? parseAtUri(uri) : undefined;
239
+
const postDid = parsedUri?.did ?? did;
240
+
const postRkey = parsedUri?.rkey ?? rkey;
241
+
const href = `${blueskyAppBaseUrl}/profile/${postDid}/post/${postRkey}`;
242
+
243
+
// Author profile and avatar
244
+
const { handle: authorHandle } = useDidResolution(postDid);
245
+
const { record: authorProfile } = useAtProtoRecord<ProfileRecord>({
246
+
did: postDid,
247
+
collection: BLUESKY_PROFILE_COLLECTION,
248
+
rkey: "self",
249
+
});
250
+
const authorDisplayName = authorProfile?.displayName;
251
+
const authorAvatar = authorProfile?.avatar;
252
+
const authorAvatarCdnUrl = isBlobWithCdn(authorAvatar) ? authorAvatar.cdnUrl : undefined;
253
+
const authorAvatarCid = authorAvatarCdnUrl ? undefined : getAvatarCid(authorProfile);
254
+
const { url: authorAvatarUrl } = useBlob(
255
+
postDid,
256
+
authorAvatarCid,
257
+
);
258
+
const finalAuthorAvatarUrl = authorAvatarCdnUrl ?? authorAvatarUrl;
259
+
260
+
// Repost metadata
261
+
const isRepost = reason?.$type === "app.bsky.feed.defs#reasonRepost";
262
+
const reposterDid = reason?.by?.did;
263
+
const { handle: reposterHandle } = useDidResolution(reposterDid);
264
+
const { record: reposterProfile } = useAtProtoRecord<ProfileRecord>({
265
+
did: reposterDid,
266
+
collection: BLUESKY_PROFILE_COLLECTION,
267
+
rkey: "self",
268
+
});
269
+
const reposterDisplayName = reposterProfile?.displayName;
270
+
const reposterAvatar = reposterProfile?.avatar;
271
+
const reposterAvatarCdnUrl = isBlobWithCdn(reposterAvatar) ? reposterAvatar.cdnUrl : undefined;
272
+
const reposterAvatarCid = reposterAvatarCdnUrl ? undefined : getAvatarCid(reposterProfile);
273
+
const { url: reposterAvatarUrl } = useBlob(
274
+
reposterDid,
275
+
reposterAvatarCid,
276
+
);
277
+
const finalReposterAvatarUrl = reposterAvatarCdnUrl ?? reposterAvatarUrl;
278
+
279
+
// Reply metadata
233
280
const parentUri = replyParent?.uri ?? record.reply?.parent?.uri;
234
-
const parentDid =
235
-
replyParent?.author?.did ??
236
-
(parentUri ? parseAtUri(parentUri)?.did : undefined);
237
-
const { handle: resolvedReplyHandle } = useDidResolution(
281
+
const parentDid = replyParent?.author?.did ?? (parentUri ? parseAtUri(parentUri)?.did : undefined);
282
+
const { handle: parentHandle } = useDidResolution(
238
283
replyParent?.author?.handle ? undefined : parentDid,
239
284
);
240
-
const replyLabel = formatReplyTarget(
241
-
parentUri,
242
-
replyParent,
243
-
resolvedReplyHandle,
285
+
const { record: parentProfile } = useAtProtoRecord<ProfileRecord>({
286
+
did: parentDid,
287
+
collection: BLUESKY_PROFILE_COLLECTION,
288
+
rkey: "self",
289
+
});
290
+
const parentAvatar = parentProfile?.avatar;
291
+
const parentAvatarCdnUrl = isBlobWithCdn(parentAvatar) ? parentAvatar.cdnUrl : undefined;
292
+
const parentAvatarCid = parentAvatarCdnUrl ? undefined : getAvatarCid(parentProfile);
293
+
const { url: parentAvatarUrl } = useBlob(
294
+
parentDid,
295
+
parentAvatarCid,
244
296
);
297
+
const finalParentAvatarUrl = parentAvatarCdnUrl ?? parentAvatarUrl;
298
+
299
+
const isReply = !!parentUri;
300
+
const replyTargetHandle = replyParent?.author?.handle ?? parentHandle;
301
+
302
+
const postPreview = text.slice(0, 100);
303
+
const ariaLabel = text
304
+
? `Post by ${authorDisplayName ?? authorHandle ?? did}: ${postPreview}${text.length > 100 ? "..." : ""}`
305
+
: `Post by ${authorDisplayName ?? authorHandle ?? did}`;
245
306
246
307
return (
247
-
<a
248
-
href={href}
249
-
target="_blank"
250
-
rel="noopener noreferrer"
308
+
<div
251
309
style={{
252
-
...listStyles.row,
253
-
...palette.row,
254
-
borderBottom: hasDivider
255
-
? `1px solid ${palette.divider}`
256
-
: "none",
310
+
...listStyles.rowContainer,
311
+
borderBottom: hasDivider ? `1px solid var(--atproto-color-border)` : "none",
257
312
}}
258
313
>
259
-
{repostLabel && (
260
-
<span style={{ ...listStyles.rowMeta, ...palette.rowMeta }}>
261
-
{repostLabel}
262
-
</span>
263
-
)}
264
-
{replyLabel && (
265
-
<span style={{ ...listStyles.rowMeta, ...palette.rowMeta }}>
266
-
{replyLabel}
267
-
</span>
268
-
)}
269
-
{relative && (
270
-
<span
271
-
style={{ ...listStyles.rowTime, ...palette.rowTime }}
272
-
title={absolute}
273
-
>
274
-
{relative}
275
-
</span>
314
+
{isRepost && (
315
+
<div style={listStyles.repostIndicator}>
316
+
{finalReposterAvatarUrl && (
317
+
<img
318
+
src={finalReposterAvatarUrl}
319
+
alt=""
320
+
style={listStyles.repostAvatar}
321
+
/>
322
+
)}
323
+
<svg
324
+
width="16"
325
+
height="16"
326
+
viewBox="0 0 16 16"
327
+
fill="none"
328
+
style={{ flexShrink: 0 }}
329
+
>
330
+
<path
331
+
d="M5.5 3.5L3 6L5.5 8.5M3 6H10C11.1046 6 12 6.89543 12 8V8.5M10.5 12.5L13 10L10.5 7.5M13 10H6C4.89543 10 4 9.10457 4 8V7.5"
332
+
stroke="var(--atproto-color-text-secondary)"
333
+
strokeWidth="1.5"
334
+
strokeLinecap="round"
335
+
strokeLinejoin="round"
336
+
/>
337
+
</svg>
338
+
<span style={{ ...listStyles.repostText, color: "var(--atproto-color-text-secondary)" }}>
339
+
{reposterDisplayName ?? reposterHandle ?? "Someone"} reposted
340
+
</span>
341
+
</div>
276
342
)}
277
-
{text && (
278
-
<p style={{ ...listStyles.rowBody, ...palette.rowBody }}>
279
-
{text}
280
-
</p>
343
+
344
+
{isReply && (
345
+
<div style={listStyles.replyIndicator}>
346
+
<svg
347
+
width="14"
348
+
height="14"
349
+
viewBox="0 0 14 14"
350
+
fill="none"
351
+
style={{ flexShrink: 0 }}
352
+
>
353
+
<path
354
+
d="M11 7H3M3 7L7 3M3 7L7 11"
355
+
stroke="#1185FE"
356
+
strokeWidth="1.5"
357
+
strokeLinecap="round"
358
+
strokeLinejoin="round"
359
+
/>
360
+
</svg>
361
+
<span style={{ ...listStyles.replyText, color: "var(--atproto-color-text-secondary)" }}>
362
+
Replying to
363
+
</span>
364
+
{finalParentAvatarUrl && (
365
+
<img
366
+
src={finalParentAvatarUrl}
367
+
alt=""
368
+
style={listStyles.replyAvatar}
369
+
/>
370
+
)}
371
+
<span style={{ color: "#1185FE", fontWeight: 600 }}>
372
+
@{replyTargetHandle ?? formatDid(parentDid ?? "")}
373
+
</span>
374
+
</div>
281
375
)}
282
-
{!text && (
283
-
<p
284
-
style={{
285
-
...listStyles.rowBody,
286
-
...palette.rowBody,
287
-
fontStyle: "italic",
288
-
}}
289
-
>
290
-
No text content.
291
-
</p>
292
-
)}
293
-
</a>
376
+
377
+
<div style={listStyles.postContent}>
378
+
<div style={listStyles.avatarContainer}>
379
+
{finalAuthorAvatarUrl ? (
380
+
<img
381
+
src={finalAuthorAvatarUrl}
382
+
alt={authorDisplayName ?? authorHandle ?? "User avatar"}
383
+
style={listStyles.avatar}
384
+
/>
385
+
) : (
386
+
<div style={listStyles.avatarPlaceholder}>
387
+
{(authorDisplayName ?? authorHandle ?? "?")[0].toUpperCase()}
388
+
</div>
389
+
)}
390
+
</div>
391
+
392
+
<div style={listStyles.postMain}>
393
+
<div style={listStyles.postHeader}>
394
+
<a
395
+
href={`${blueskyAppBaseUrl}/profile/${postDid}`}
396
+
target="_blank"
397
+
rel="noopener noreferrer"
398
+
style={{ ...listStyles.authorName, color: "var(--atproto-color-text)" }}
399
+
onClick={(e) => e.stopPropagation()}
400
+
>
401
+
{authorDisplayName ?? authorHandle ?? formatDid(postDid)}
402
+
</a>
403
+
<span style={{ ...listStyles.authorHandle, color: "var(--atproto-color-text-secondary)" }}>
404
+
@{authorHandle ?? formatDid(postDid)}
405
+
</span>
406
+
<span style={{ ...listStyles.separator, color: "var(--atproto-color-text-secondary)" }}>ยท</span>
407
+
<span
408
+
style={{ ...listStyles.timestamp, color: "var(--atproto-color-text-secondary)" }}
409
+
title={absolute}
410
+
>
411
+
{relative}
412
+
</span>
413
+
</div>
414
+
415
+
<a
416
+
href={href}
417
+
target="_blank"
418
+
rel="noopener noreferrer"
419
+
aria-label={ariaLabel}
420
+
style={{ ...listStyles.postLink, color: "var(--atproto-color-text)" }}
421
+
>
422
+
{text && (
423
+
<p style={listStyles.postText}>
424
+
<BlueskyRichText text={text} facets={record.facets} />
425
+
</p>
426
+
)}
427
+
{!text && (
428
+
<p style={{ ...listStyles.postText, fontStyle: "italic", color: "var(--atproto-color-text-secondary)" }}>
429
+
No text content
430
+
</p>
431
+
)}
432
+
</a>
433
+
</div>
434
+
</div>
435
+
</div>
294
436
);
295
437
};
296
438
···
323
465
return rtf.format(Math.round(value), threshold.unit);
324
466
}
325
467
326
-
interface ListPalette {
327
-
card: { background: string; borderColor: string };
328
-
header: { borderBottomColor: string; color: string };
329
-
pageMeta: { color: string };
330
-
subtitle: { color: string };
331
-
empty: { color: string };
332
-
row: { color: string };
333
-
rowTime: { color: string };
334
-
rowBody: { color: string };
335
-
rowMeta: { color: string };
336
-
divider: string;
337
-
footer: { borderTopColor: string; color: string };
338
-
navButton: { color: string; background: string };
339
-
pageChip: { color: string; borderColor: string; background: string };
340
-
pageChipActive: { color: string; background: string; borderColor: string };
341
-
loadingBar: { color: string };
342
-
}
343
468
344
469
const listStyles = {
345
470
card: {
346
471
borderRadius: 16,
347
-
border: "1px solid transparent",
472
+
borderWidth: "1px",
473
+
borderStyle: "solid",
474
+
borderColor: "transparent",
348
475
boxShadow: "0 8px 18px -12px rgba(15, 23, 42, 0.25)",
349
476
overflow: "hidden",
350
477
display: "flex",
···
370
497
display: "flex",
371
498
alignItems: "center",
372
499
justifyContent: "center",
373
-
//background: 'rgba(17, 133, 254, 0.14)',
374
500
borderRadius: "50%",
375
501
} satisfies React.CSSProperties,
376
502
headerText: {
···
398
524
fontSize: 13,
399
525
textAlign: "center",
400
526
} satisfies React.CSSProperties,
401
-
row: {
402
-
padding: "18px",
403
-
textDecoration: "none",
527
+
rowContainer: {
528
+
padding: "16px",
404
529
display: "flex",
405
530
flexDirection: "column",
406
-
gap: 6,
531
+
gap: 8,
407
532
transition: "background-color 120ms ease",
533
+
position: "relative",
408
534
} satisfies React.CSSProperties,
409
-
rowHeader: {
535
+
repostIndicator: {
410
536
display: "flex",
411
-
gap: 6,
412
-
alignItems: "baseline",
537
+
alignItems: "center",
538
+
gap: 8,
413
539
fontSize: 13,
540
+
fontWeight: 500,
541
+
paddingLeft: 8,
542
+
marginBottom: 4,
414
543
} satisfies React.CSSProperties,
415
-
rowTime: {
416
-
fontSize: 12,
544
+
repostAvatar: {
545
+
width: 16,
546
+
height: 16,
547
+
borderRadius: "50%",
548
+
objectFit: "cover",
549
+
} satisfies React.CSSProperties,
550
+
repostText: {
551
+
fontSize: 13,
417
552
fontWeight: 500,
418
553
} satisfies React.CSSProperties,
419
-
rowMeta: {
420
-
fontSize: 12,
554
+
replyIndicator: {
555
+
display: "flex",
556
+
alignItems: "center",
557
+
gap: 8,
558
+
fontSize: 13,
559
+
fontWeight: 500,
560
+
paddingLeft: 8,
561
+
marginBottom: 4,
562
+
} satisfies React.CSSProperties,
563
+
replyAvatar: {
564
+
width: 16,
565
+
height: 16,
566
+
borderRadius: "50%",
567
+
objectFit: "cover",
568
+
} satisfies React.CSSProperties,
569
+
replyText: {
570
+
fontSize: 13,
421
571
fontWeight: 500,
422
-
letterSpacing: "0.6px",
572
+
} satisfies React.CSSProperties,
573
+
postContent: {
574
+
display: "flex",
575
+
gap: 12,
423
576
} satisfies React.CSSProperties,
424
-
rowBody: {
577
+
avatarContainer: {
578
+
flexShrink: 0,
579
+
} satisfies React.CSSProperties,
580
+
avatar: {
581
+
width: 48,
582
+
height: 48,
583
+
borderRadius: "50%",
584
+
objectFit: "cover",
585
+
} satisfies React.CSSProperties,
586
+
avatarPlaceholder: {
587
+
width: 48,
588
+
height: 48,
589
+
borderRadius: "50%",
590
+
background: "var(--atproto-color-bg-elevated)",
591
+
color: "var(--atproto-color-text-secondary)",
592
+
display: "flex",
593
+
alignItems: "center",
594
+
justifyContent: "center",
595
+
fontSize: 18,
596
+
fontWeight: 600,
597
+
} satisfies React.CSSProperties,
598
+
postMain: {
599
+
flex: 1,
600
+
minWidth: 0,
601
+
display: "flex",
602
+
flexDirection: "column",
603
+
gap: 6,
604
+
} satisfies React.CSSProperties,
605
+
postHeader: {
606
+
display: "flex",
607
+
alignItems: "baseline",
608
+
gap: 6,
609
+
flexWrap: "wrap",
610
+
} satisfies React.CSSProperties,
611
+
authorName: {
612
+
fontWeight: 700,
613
+
fontSize: 15,
614
+
textDecoration: "none",
615
+
maxWidth: "200px",
616
+
overflow: "hidden",
617
+
textOverflow: "ellipsis",
618
+
whiteSpace: "nowrap",
619
+
} satisfies React.CSSProperties,
620
+
authorHandle: {
621
+
fontSize: 15,
622
+
fontWeight: 400,
623
+
maxWidth: "150px",
624
+
overflow: "hidden",
625
+
textOverflow: "ellipsis",
626
+
whiteSpace: "nowrap",
627
+
} satisfies React.CSSProperties,
628
+
separator: {
629
+
fontSize: 15,
630
+
fontWeight: 400,
631
+
} satisfies React.CSSProperties,
632
+
timestamp: {
633
+
fontSize: 15,
634
+
fontWeight: 400,
635
+
} satisfies React.CSSProperties,
636
+
postLink: {
637
+
textDecoration: "none",
638
+
display: "block",
639
+
} satisfies React.CSSProperties,
640
+
postText: {
425
641
margin: 0,
426
642
whiteSpace: "pre-wrap",
427
-
fontSize: 14,
428
-
lineHeight: 1.45,
643
+
fontSize: 15,
644
+
lineHeight: 1.5,
645
+
wordBreak: "break-word",
429
646
} satisfies React.CSSProperties,
430
647
footer: {
431
648
display: "flex",
···
435
652
borderTop: "1px solid transparent",
436
653
fontSize: 13,
437
654
} satisfies React.CSSProperties,
438
-
navButton: {
439
-
border: "none",
440
-
borderRadius: 999,
441
-
padding: "6px 12px",
442
-
fontSize: 13,
443
-
fontWeight: 500,
444
-
background: "transparent",
445
-
display: "flex",
446
-
alignItems: "center",
447
-
gap: 4,
448
-
transition: "background-color 120ms ease",
449
-
} satisfies React.CSSProperties,
450
655
pageChips: {
451
656
display: "flex",
452
657
gap: 6,
···
456
661
padding: "4px 10px",
457
662
borderRadius: 999,
458
663
fontSize: 13,
459
-
border: "1px solid transparent",
664
+
borderWidth: "1px",
665
+
borderStyle: "solid",
666
+
borderColor: "transparent",
460
667
} satisfies React.CSSProperties,
461
668
pageChipActive: {
462
669
padding: "4px 10px",
463
670
borderRadius: 999,
464
671
fontSize: 13,
465
672
fontWeight: 600,
466
-
border: "1px solid transparent",
673
+
borderWidth: "1px",
674
+
borderStyle: "solid",
675
+
borderColor: "transparent",
676
+
} satisfies React.CSSProperties,
677
+
pageButton: {
678
+
border: "none",
679
+
borderRadius: 999,
680
+
padding: "6px 12px",
681
+
fontSize: 13,
682
+
fontWeight: 500,
683
+
background: "transparent",
684
+
display: "flex",
685
+
alignItems: "center",
686
+
gap: 4,
687
+
transition: "background-color 120ms ease",
467
688
} satisfies React.CSSProperties,
468
689
loadingBar: {
469
690
padding: "4px 18px 14px",
···
473
694
} satisfies React.CSSProperties,
474
695
};
475
696
476
-
const lightPalette: ListPalette = {
477
-
card: {
478
-
background: "#ffffff",
479
-
borderColor: "#e2e8f0",
480
-
},
481
-
header: {
482
-
borderBottomColor: "#e2e8f0",
483
-
color: "#0f172a",
484
-
},
485
-
pageMeta: {
486
-
color: "#64748b",
487
-
},
488
-
subtitle: {
489
-
color: "#475569",
490
-
},
491
-
empty: {
492
-
color: "#64748b",
493
-
},
494
-
row: {
495
-
color: "#0f172a",
496
-
},
497
-
rowTime: {
498
-
color: "#94a3b8",
499
-
},
500
-
rowBody: {
501
-
color: "#0f172a",
502
-
},
503
-
rowMeta: {
504
-
color: "#64748b",
505
-
},
506
-
divider: "#e2e8f0",
507
-
footer: {
508
-
borderTopColor: "#e2e8f0",
509
-
color: "#0f172a",
510
-
},
511
-
navButton: {
512
-
color: "#0f172a",
513
-
background: "#f1f5f9",
514
-
},
515
-
pageChip: {
516
-
color: "#475569",
517
-
borderColor: "#e2e8f0",
518
-
background: "#ffffff",
519
-
},
520
-
pageChipActive: {
521
-
color: "#ffffff",
522
-
background: "#0f172a",
523
-
borderColor: "#0f172a",
524
-
},
525
-
loadingBar: {
526
-
color: "#64748b",
527
-
},
528
-
};
529
-
530
-
const darkPalette: ListPalette = {
531
-
card: {
532
-
background: "#0f172a",
533
-
borderColor: "#1e293b",
534
-
},
535
-
header: {
536
-
borderBottomColor: "#1e293b",
537
-
color: "#e2e8f0",
538
-
},
539
-
pageMeta: {
540
-
color: "#94a3b8",
541
-
},
542
-
subtitle: {
543
-
color: "#94a3b8",
544
-
},
545
-
empty: {
546
-
color: "#94a3b8",
547
-
},
548
-
row: {
549
-
color: "#e2e8f0",
550
-
},
551
-
rowTime: {
552
-
color: "#94a3b8",
553
-
},
554
-
rowBody: {
555
-
color: "#e2e8f0",
556
-
},
557
-
rowMeta: {
558
-
color: "#94a3b8",
559
-
},
560
-
divider: "#1e293b",
561
-
footer: {
562
-
borderTopColor: "#1e293b",
563
-
color: "#e2e8f0",
564
-
},
565
-
navButton: {
566
-
color: "#e2e8f0",
567
-
background: "#111c31",
568
-
},
569
-
pageChip: {
570
-
color: "#cbd5f5",
571
-
borderColor: "#1e293b",
572
-
background: "#0f172a",
573
-
},
574
-
pageChipActive: {
575
-
color: "#0f172a",
576
-
background: "#38bdf8",
577
-
borderColor: "#38bdf8",
578
-
},
579
-
loadingBar: {
580
-
color: "#94a3b8",
581
-
},
582
-
};
583
-
584
697
export default BlueskyPostList;
585
-
586
-
function formatActor(actor?: { handle?: string; did?: string }) {
587
-
if (!actor) return undefined;
588
-
if (actor.handle) return `@${actor.handle}`;
589
-
if (actor.did) return `@${formatDid(actor.did)}`;
590
-
return undefined;
591
-
}
592
-
593
-
function formatReplyTarget(
594
-
parentUri?: string,
595
-
feedParent?: ReplyParentInfo,
596
-
resolvedHandle?: string,
597
-
) {
598
-
const directHandle = feedParent?.author?.handle;
599
-
const handle = directHandle ?? resolvedHandle;
600
-
if (handle) {
601
-
return `Replying to @${handle}`;
602
-
}
603
-
const parentDid = feedParent?.author?.did;
604
-
const targetUri = feedParent?.uri ?? parentUri;
605
-
if (!targetUri) return undefined;
606
-
const parsed = parseAtUri(targetUri);
607
-
const did = parentDid ?? parsed?.did;
608
-
if (!did) return undefined;
609
-
return `Replying to @${formatDid(did)}`;
610
-
}
+13
-18
lib/components/BlueskyProfile.tsx
+13
-18
lib/components/BlueskyProfile.tsx
···
6
6
import { getAvatarCid } from "../utils/profile";
7
7
import { useDidResolution } from "../hooks/useDidResolution";
8
8
import { formatDidForLabel } from "../utils/at-uri";
9
+
import { isBlobWithCdn } from "../utils/blob";
9
10
10
11
/**
11
12
* Props used to render a Bluesky actor profile record.
···
40
41
* Pre-resolved handle to display when available externally.
41
42
*/
42
43
handle?: string;
43
-
/**
44
-
* Preferred color scheme forwarded to renderer implementations.
45
-
*/
46
-
colorScheme?: "light" | "dark" | "system";
44
+
47
45
}
48
46
49
47
/**
···
74
72
* Blob URL for the user's avatar, when available.
75
73
*/
76
74
avatarUrl?: string;
77
-
/**
78
-
* Preferred color scheme for theming downstream components.
79
-
*/
80
-
colorScheme?: "light" | "dark" | "system";
75
+
81
76
};
82
77
83
78
/** NSID for the canonical Bluesky profile collection. */
···
93
88
* @param fallback - Node rendered prior to loading state initialization.
94
89
* @param loadingIndicator - Node rendered while the profile request is in-flight.
95
90
* @param handle - Optional pre-resolved handle to display.
96
-
* @param colorScheme - Preferred color scheme forwarded to the renderer.
97
91
* @returns A rendered profile component with loading/error states handled.
98
92
*/
99
-
export const BlueskyProfile: React.FC<BlueskyProfileProps> = ({
93
+
export const BlueskyProfile: React.FC<BlueskyProfileProps> = React.memo(({
100
94
did: handleOrDid,
101
95
rkey = "self",
102
96
record,
···
104
98
fallback,
105
99
loadingIndicator,
106
100
handle,
107
-
colorScheme,
108
101
}) => {
109
102
const Component: React.ComponentType<BlueskyProfileRendererInjectedProps> =
110
103
renderer ?? ((props) => <BlueskyProfileRenderer {...props} />);
···
122
115
loading: boolean;
123
116
error?: Error;
124
117
}> = (props) => {
125
-
const avatarCid = getAvatarCid(props.record);
126
-
const { url: avatarUrl } = useBlob(repoIdentifier, avatarCid);
118
+
// Check if the avatar has a CDN URL from the appview (preferred)
119
+
const avatar = props.record?.avatar;
120
+
const avatarCdnUrl = isBlobWithCdn(avatar) ? avatar.cdnUrl : undefined;
121
+
const avatarCid = avatarCdnUrl ? undefined : getAvatarCid(props.record);
122
+
const { url: avatarUrlFromBlob } = useBlob(repoIdentifier, avatarCid);
123
+
const avatarUrl = avatarCdnUrl || avatarUrlFromBlob;
124
+
127
125
return (
128
126
<Component
129
127
{...props}
130
128
did={repoIdentifier}
131
129
handle={effectiveHandle}
132
130
avatarUrl={avatarUrl}
133
-
colorScheme={colorScheme}
134
131
/>
135
132
);
136
133
};
137
134
138
-
// When record is provided, pass it directly to skip fetching
139
-
if (record) {
135
+
if (record !== undefined) {
140
136
return (
141
137
<AtProtoRecord<ProfileRecord>
142
138
record={record}
···
147
143
);
148
144
}
149
145
150
-
// Otherwise fetch the record using did, collection, and rkey
151
146
return (
152
147
<AtProtoRecord<ProfileRecord>
153
148
did={repoIdentifier}
···
158
153
loadingIndicator={loadingIndicator}
159
154
/>
160
155
);
161
-
};
156
+
});
162
157
163
158
export default BlueskyProfile;
+4
-15
lib/components/BlueskyQuotePost.tsx
+4
-15
lib/components/BlueskyQuotePost.tsx
···
20
20
*/
21
21
rkey: string;
22
22
/**
23
-
* Preferred color scheme propagated to nested renders.
24
-
*/
25
-
colorScheme?: "light" | "dark" | "system";
26
-
/**
27
23
* Custom renderer override applied to the parent post.
28
24
*/
29
25
renderer?: React.ComponentType<BlueskyPostRendererInjectedProps>;
···
50
46
*
51
47
* @param did - DID that owns the quoted parent post.
52
48
* @param rkey - Record key identifying the parent post.
53
-
* @param colorScheme - Preferred color scheme for both parent and quoted posts.
54
49
* @param renderer - Optional renderer override applied to the parent post.
55
50
* @param fallback - Node rendered before parent post data loads.
56
51
* @param loadingIndicator - Node rendered while the parent post request is in-flight.
···
61
56
const BlueskyQuotePostComponent: React.FC<BlueskyQuotePostProps> = ({
62
57
did,
63
58
rkey,
64
-
colorScheme,
65
59
renderer,
66
60
fallback,
67
61
loadingIndicator,
···
73
67
const QuoteRenderer: React.FC<BlueskyPostRendererInjectedProps> = (
74
68
props,
75
69
) => {
76
-
const resolvedColorScheme = props.colorScheme ?? colorScheme;
77
70
const embedSource = props.record.embed as
78
71
| QuoteRecordEmbed
79
72
| undefined;
80
73
const embedNode = useMemo(
81
-
() => createQuoteEmbed(embedSource, resolvedColorScheme),
82
-
[embedSource, resolvedColorScheme],
74
+
() => createQuoteEmbed(embedSource),
75
+
[embedSource],
83
76
);
84
-
return <BaseRenderer {...props} embed={embedNode} />;
77
+
return <BaseRenderer isQuotePost={true} {...props} embed={embedNode} />;
85
78
};
86
79
QuoteRenderer.displayName = "BlueskyQuotePostRenderer";
87
80
const MemoizedQuoteRenderer = memo(QuoteRenderer);
88
81
MemoizedQuoteRenderer.displayName = "BlueskyQuotePostRenderer";
89
82
return MemoizedQuoteRenderer;
90
-
}, [BaseRenderer, colorScheme]);
83
+
}, [BaseRenderer]);
91
84
92
85
return (
93
86
<BlueskyPost
94
87
did={did}
95
88
rkey={rkey}
96
-
colorScheme={colorScheme}
97
89
renderer={Renderer}
98
90
fallback={fallback}
99
91
loadingIndicator={loadingIndicator}
···
113
105
* Builds the quoted post embed node when the parent record contains a record embed.
114
106
*
115
107
* @param embed - Embed payload containing a possible quote reference.
116
-
* @param colorScheme - Desired visual theme for the nested quote.
117
108
* @returns A nested `BlueskyPost` or `null` if no compatible embed exists.
118
109
*/
119
110
type QuoteRecordEmbed = { $type?: string; record?: { uri?: string } };
120
111
121
112
function createQuoteEmbed(
122
113
embed: QuoteRecordEmbed | undefined,
123
-
colorScheme?: "light" | "dark" | "system",
124
114
) {
125
115
if (!embed || embed.$type !== "app.bsky.embed.record") return null;
126
116
const quoted = embed.record;
···
132
122
<BlueskyPost
133
123
did={parsed.did}
134
124
rkey={parsed.rkey}
135
-
colorScheme={colorScheme}
136
125
showIcon={false}
137
126
/>
138
127
</div>
-129
lib/components/ColorSchemeToggle.tsx
-129
lib/components/ColorSchemeToggle.tsx
···
1
-
import React from "react";
2
-
import type { ColorSchemePreference } from "../hooks/useColorScheme";
3
-
4
-
/**
5
-
* Props for the `ColorSchemeToggle` segmented control.
6
-
*/
7
-
export interface ColorSchemeToggleProps {
8
-
/**
9
-
* Current color scheme preference selection.
10
-
*/
11
-
value: ColorSchemePreference;
12
-
/**
13
-
* Change handler invoked when the user selects a new scheme.
14
-
*/
15
-
onChange: (value: ColorSchemePreference) => void;
16
-
/**
17
-
* Theme used to style the control itself; defaults to `'light'`.
18
-
*/
19
-
scheme?: "light" | "dark";
20
-
}
21
-
22
-
const options: Array<{
23
-
label: string;
24
-
value: ColorSchemePreference;
25
-
description: string;
26
-
}> = [
27
-
{ label: "System", value: "system", description: "Follow OS preference" },
28
-
{ label: "Light", value: "light", description: "Always light mode" },
29
-
{ label: "Dark", value: "dark", description: "Always dark mode" },
30
-
];
31
-
32
-
/**
33
-
* A button group that lets users choose between light, dark, or system color modes.
34
-
*
35
-
* @param value - Current scheme selection displayed as active.
36
-
* @param onChange - Callback fired when a new option is selected.
37
-
* @param scheme - Theme used to style the control itself. Defaults to `'light'`.
38
-
* @returns A fully keyboard-accessible toggle rendered as a radio group.
39
-
*/
40
-
export const ColorSchemeToggle: React.FC<ColorSchemeToggleProps> = ({
41
-
value,
42
-
onChange,
43
-
scheme = "light",
44
-
}) => {
45
-
const palette = scheme === "dark" ? darkTheme : lightTheme;
46
-
47
-
return (
48
-
<div
49
-
aria-label="Color scheme"
50
-
role="radiogroup"
51
-
style={{ ...containerStyle, ...palette.container }}
52
-
>
53
-
{options.map((option) => {
54
-
const isActive = option.value === value;
55
-
const activeStyles = isActive ? palette.active : undefined;
56
-
return (
57
-
<button
58
-
key={option.value}
59
-
role="radio"
60
-
aria-checked={isActive}
61
-
type="button"
62
-
onClick={() => onChange(option.value)}
63
-
style={{
64
-
...buttonStyle,
65
-
...palette.button,
66
-
...(activeStyles ?? {}),
67
-
}}
68
-
title={option.description}
69
-
>
70
-
{option.label}
71
-
</button>
72
-
);
73
-
})}
74
-
</div>
75
-
);
76
-
};
77
-
78
-
const containerStyle: React.CSSProperties = {
79
-
display: "inline-flex",
80
-
borderRadius: 999,
81
-
padding: 4,
82
-
gap: 4,
83
-
border: "1px solid transparent",
84
-
background: "#f8fafc",
85
-
};
86
-
87
-
const buttonStyle: React.CSSProperties = {
88
-
border: "1px solid transparent",
89
-
borderRadius: 999,
90
-
padding: "4px 12px",
91
-
fontSize: 12,
92
-
fontWeight: 500,
93
-
cursor: "pointer",
94
-
background: "transparent",
95
-
transition:
96
-
"background-color 160ms ease, border-color 160ms ease, color 160ms ease",
97
-
};
98
-
99
-
const lightTheme = {
100
-
container: {
101
-
borderColor: "#e2e8f0",
102
-
background: "rgba(241, 245, 249, 0.8)",
103
-
},
104
-
button: {
105
-
color: "#334155",
106
-
},
107
-
active: {
108
-
background: "#2563eb",
109
-
borderColor: "#2563eb",
110
-
color: "#f8fafc",
111
-
},
112
-
} satisfies Record<string, React.CSSProperties>;
113
-
114
-
const darkTheme = {
115
-
container: {
116
-
borderColor: "#2e3540ff",
117
-
background: "rgba(30, 38, 49, 0.6)",
118
-
},
119
-
button: {
120
-
color: "#e2e8f0",
121
-
},
122
-
active: {
123
-
background: "#38bdf8",
124
-
borderColor: "#38bdf8",
125
-
color: "#020617",
126
-
},
127
-
} satisfies Record<string, React.CSSProperties>;
128
-
129
-
export default ColorSchemeToggle;
+143
lib/components/CurrentlyPlaying.tsx
+143
lib/components/CurrentlyPlaying.tsx
···
1
+
import React from "react";
2
+
import { AtProtoRecord } from "../core/AtProtoRecord";
3
+
import { CurrentlyPlayingRenderer } from "../renderers/CurrentlyPlayingRenderer";
4
+
import { useDidResolution } from "../hooks/useDidResolution";
5
+
import type { TealActorStatusRecord } from "../types/teal";
6
+
7
+
/**
8
+
* Props for rendering teal.fm currently playing status.
9
+
*/
10
+
export interface CurrentlyPlayingProps {
11
+
/** DID of the user whose currently playing status to display. */
12
+
did: string;
13
+
/** Record key within the `fm.teal.alpha.actor.status` collection (usually "self"). */
14
+
rkey?: string;
15
+
/** Prefetched teal.fm status record. When provided, skips fetching from the network. */
16
+
record?: TealActorStatusRecord;
17
+
/** Optional renderer override for custom presentation. */
18
+
renderer?: React.ComponentType<CurrentlyPlayingRendererInjectedProps>;
19
+
/** Fallback node displayed before loading begins. */
20
+
fallback?: React.ReactNode;
21
+
/** Indicator node shown while data is loading. */
22
+
loadingIndicator?: React.ReactNode;
23
+
/** Preferred color scheme for theming. */
24
+
colorScheme?: "light" | "dark" | "system";
25
+
/** Auto-refresh music data and album art. When true, refreshes every 15 seconds. Defaults to true. */
26
+
autoRefresh?: boolean;
27
+
/** Refresh interval in milliseconds. Defaults to 15000 (15 seconds). Only used when autoRefresh is true. */
28
+
refreshInterval?: number;
29
+
}
30
+
31
+
/**
32
+
* Values injected into custom currently playing renderer implementations.
33
+
*/
34
+
export type CurrentlyPlayingRendererInjectedProps = {
35
+
/** Loaded teal.fm status record value. */
36
+
record: TealActorStatusRecord;
37
+
/** Indicates whether the record is currently loading. */
38
+
loading: boolean;
39
+
/** Fetch error, if any. */
40
+
error?: Error;
41
+
/** Preferred color scheme for downstream components. */
42
+
colorScheme?: "light" | "dark" | "system";
43
+
/** DID associated with the record. */
44
+
did: string;
45
+
/** Record key for the status. */
46
+
rkey: string;
47
+
/** Label to display. */
48
+
label?: string;
49
+
/** Handle to display in not listening state */
50
+
handle?: string;
51
+
};
52
+
53
+
/** NSID for teal.fm actor status records. */
54
+
export const CURRENTLY_PLAYING_COLLECTION = "fm.teal.alpha.actor.status";
55
+
56
+
/**
57
+
* Compares two teal.fm status records to determine if the track has changed.
58
+
* Used to prevent unnecessary re-renders during auto-refresh when the same track is still playing.
59
+
*/
60
+
const compareTealRecords = (
61
+
prev: TealActorStatusRecord | undefined,
62
+
next: TealActorStatusRecord | undefined
63
+
): boolean => {
64
+
if (!prev || !next) return prev === next;
65
+
66
+
const prevTrack = prev.item.trackName;
67
+
const nextTrack = next.item.trackName;
68
+
const prevArtist = prev.item.artists[0]?.artistName;
69
+
const nextArtist = next.item.artists[0]?.artistName;
70
+
71
+
return prevTrack === nextTrack && prevArtist === nextArtist;
72
+
};
73
+
74
+
/**
75
+
* Displays the currently playing track from teal.fm with auto-refresh.
76
+
*
77
+
* @param did - DID whose currently playing status should be fetched.
78
+
* @param rkey - Record key within the teal.fm status collection (defaults to "self").
79
+
* @param renderer - Optional component override that will receive injected props.
80
+
* @param fallback - Node rendered before the first load begins.
81
+
* @param loadingIndicator - Node rendered while the status is loading.
82
+
* @param colorScheme - Preferred color scheme for theming the renderer.
83
+
* @param autoRefresh - When true (default), refreshes the record every 15 seconds (or custom interval).
84
+
* @param refreshInterval - Custom refresh interval in milliseconds. Defaults to 15000 (15 seconds).
85
+
* @returns A JSX subtree representing the currently playing track with loading states handled.
86
+
*/
87
+
export const CurrentlyPlaying: React.FC<CurrentlyPlayingProps> = React.memo(({
88
+
did,
89
+
rkey = "self",
90
+
record,
91
+
renderer,
92
+
fallback,
93
+
loadingIndicator,
94
+
colorScheme,
95
+
autoRefresh = true,
96
+
refreshInterval = 15000,
97
+
}) => {
98
+
// Resolve handle from DID
99
+
const { handle } = useDidResolution(did);
100
+
101
+
const Comp: React.ComponentType<CurrentlyPlayingRendererInjectedProps> =
102
+
renderer ?? ((props) => <CurrentlyPlayingRenderer {...props} />);
103
+
const Wrapped: React.FC<{
104
+
record: TealActorStatusRecord;
105
+
loading: boolean;
106
+
error?: Error;
107
+
}> = (props) => (
108
+
<Comp
109
+
{...props}
110
+
colorScheme={colorScheme}
111
+
did={did}
112
+
rkey={rkey}
113
+
label="CURRENTLY PLAYING"
114
+
handle={handle}
115
+
/>
116
+
);
117
+
118
+
if (record !== undefined) {
119
+
return (
120
+
<AtProtoRecord<TealActorStatusRecord>
121
+
record={record}
122
+
renderer={Wrapped}
123
+
fallback={fallback}
124
+
loadingIndicator={loadingIndicator}
125
+
/>
126
+
);
127
+
}
128
+
129
+
return (
130
+
<AtProtoRecord<TealActorStatusRecord>
131
+
did={did}
132
+
collection={CURRENTLY_PLAYING_COLLECTION}
133
+
rkey={rkey}
134
+
renderer={Wrapped}
135
+
fallback={fallback}
136
+
loadingIndicator={loadingIndicator}
137
+
refreshInterval={autoRefresh ? refreshInterval : undefined}
138
+
compareRecords={compareTealRecords}
139
+
/>
140
+
);
141
+
});
142
+
143
+
export default CurrentlyPlaying;
+327
lib/components/GrainGallery.tsx
+327
lib/components/GrainGallery.tsx
···
1
+
import React, { useMemo, useEffect, useState } from "react";
2
+
import { GrainGalleryRenderer, type GrainGalleryPhoto } from "../renderers/GrainGalleryRenderer";
3
+
import type { GrainGalleryRecord, GrainGalleryItemRecord, GrainPhotoRecord } from "../types/grain";
4
+
import type { ProfileRecord } from "../types/bluesky";
5
+
import { useDidResolution } from "../hooks/useDidResolution";
6
+
import { useAtProtoRecord } from "../hooks/useAtProtoRecord";
7
+
import { useBacklinks } from "../hooks/useBacklinks";
8
+
import { useBlob } from "../hooks/useBlob";
9
+
import { BLUESKY_PROFILE_COLLECTION } from "./BlueskyProfile";
10
+
import { getAvatarCid } from "../utils/profile";
11
+
import { formatDidForLabel, parseAtUri } from "../utils/at-uri";
12
+
import { isBlobWithCdn } from "../utils/blob";
13
+
import { createAtprotoClient } from "../utils/atproto-client";
14
+
15
+
/**
16
+
* Props for rendering a grain.social gallery.
17
+
*/
18
+
export interface GrainGalleryProps {
19
+
/**
20
+
* Decentralized identifier for the repository that owns the gallery.
21
+
*/
22
+
did: string;
23
+
/**
24
+
* Record key identifying the specific gallery within the collection.
25
+
*/
26
+
rkey: string;
27
+
/**
28
+
* Prefetched gallery record. When provided, skips fetching the gallery from the network.
29
+
*/
30
+
record?: GrainGalleryRecord;
31
+
/**
32
+
* Custom renderer component that receives resolved gallery data and status flags.
33
+
*/
34
+
renderer?: React.ComponentType<GrainGalleryRendererInjectedProps>;
35
+
/**
36
+
* React node shown while the gallery query has not yet produced data or an error.
37
+
*/
38
+
fallback?: React.ReactNode;
39
+
/**
40
+
* React node displayed while the gallery fetch is actively loading.
41
+
*/
42
+
loadingIndicator?: React.ReactNode;
43
+
/**
44
+
* Constellation API base URL for fetching backlinks.
45
+
*/
46
+
constellationBaseUrl?: string;
47
+
}
48
+
49
+
/**
50
+
* Values injected by `GrainGallery` into a downstream renderer component.
51
+
*/
52
+
export type GrainGalleryRendererInjectedProps = {
53
+
/**
54
+
* Resolved gallery record
55
+
*/
56
+
gallery: GrainGalleryRecord;
57
+
/**
58
+
* Array of photos in the gallery with their records and metadata
59
+
*/
60
+
photos: GrainGalleryPhoto[];
61
+
/**
62
+
* `true` while network operations are in-flight.
63
+
*/
64
+
loading: boolean;
65
+
/**
66
+
* Error encountered during loading, if any.
67
+
*/
68
+
error?: Error;
69
+
/**
70
+
* The author's public handle derived from the DID.
71
+
*/
72
+
authorHandle?: string;
73
+
/**
74
+
* The author's display name from their profile.
75
+
*/
76
+
authorDisplayName?: string;
77
+
/**
78
+
* Resolved URL for the author's avatar blob, if available.
79
+
*/
80
+
avatarUrl?: string;
81
+
};
82
+
83
+
export const GRAIN_GALLERY_COLLECTION = "social.grain.gallery";
84
+
export const GRAIN_GALLERY_ITEM_COLLECTION = "social.grain.gallery.item";
85
+
export const GRAIN_PHOTO_COLLECTION = "social.grain.photo";
86
+
87
+
/**
88
+
* Fetches a grain.social gallery, resolves all photos via constellation backlinks,
89
+
* and renders them in a grid layout.
90
+
*
91
+
* @param did - DID of the repository that stores the gallery.
92
+
* @param rkey - Record key for the gallery.
93
+
* @param record - Prefetched gallery record.
94
+
* @param renderer - Optional renderer component to override the default.
95
+
* @param fallback - Node rendered before the first fetch attempt resolves.
96
+
* @param loadingIndicator - Node rendered while the gallery is loading.
97
+
* @param constellationBaseUrl - Constellation API base URL.
98
+
* @returns A component that renders loading/fallback states and the resolved gallery.
99
+
*/
100
+
export const GrainGallery: React.FC<GrainGalleryProps> = React.memo(
101
+
({
102
+
did: handleOrDid,
103
+
rkey,
104
+
record,
105
+
renderer,
106
+
fallback,
107
+
loadingIndicator,
108
+
constellationBaseUrl,
109
+
}) => {
110
+
const {
111
+
did: resolvedDid,
112
+
handle,
113
+
loading: resolvingIdentity,
114
+
error: resolutionError,
115
+
} = useDidResolution(handleOrDid);
116
+
117
+
const repoIdentifier = resolvedDid ?? handleOrDid;
118
+
119
+
// Fetch author profile
120
+
const { record: profile } = useAtProtoRecord<ProfileRecord>({
121
+
did: repoIdentifier,
122
+
collection: BLUESKY_PROFILE_COLLECTION,
123
+
rkey: "self",
124
+
});
125
+
const avatar = profile?.avatar;
126
+
const avatarCdnUrl = isBlobWithCdn(avatar) ? avatar.cdnUrl : undefined;
127
+
const avatarCid = avatarCdnUrl ? undefined : getAvatarCid(profile);
128
+
const authorDisplayName = profile?.displayName;
129
+
const { url: avatarUrlFromBlob } = useBlob(repoIdentifier, avatarCid);
130
+
const avatarUrl = avatarCdnUrl || avatarUrlFromBlob;
131
+
132
+
// Fetch gallery record
133
+
const {
134
+
record: fetchedGallery,
135
+
loading: galleryLoading,
136
+
error: galleryError,
137
+
} = useAtProtoRecord<GrainGalleryRecord>({
138
+
did: record ? "" : repoIdentifier,
139
+
collection: record ? "" : GRAIN_GALLERY_COLLECTION,
140
+
rkey: record ? "" : rkey,
141
+
});
142
+
143
+
const galleryRecord = record ?? fetchedGallery;
144
+
const galleryUri = resolvedDid
145
+
? `at://${resolvedDid}/${GRAIN_GALLERY_COLLECTION}/${rkey}`
146
+
: undefined;
147
+
148
+
// Fetch backlinks to get gallery items
149
+
const {
150
+
backlinks,
151
+
loading: backlinksLoading,
152
+
error: backlinksError,
153
+
} = useBacklinks({
154
+
subject: galleryUri || "",
155
+
source: `${GRAIN_GALLERY_ITEM_COLLECTION}:gallery`,
156
+
enabled: !!galleryUri && !!galleryRecord,
157
+
constellationBaseUrl,
158
+
});
159
+
160
+
// Fetch all gallery item records and photo records
161
+
const [photos, setPhotos] = useState<GrainGalleryPhoto[]>([]);
162
+
const [photosLoading, setPhotosLoading] = useState(false);
163
+
const [photosError, setPhotosError] = useState<Error | undefined>(undefined);
164
+
165
+
useEffect(() => {
166
+
if (!backlinks || backlinks.length === 0) {
167
+
setPhotos([]);
168
+
return;
169
+
}
170
+
171
+
let cancelled = false;
172
+
setPhotosLoading(true);
173
+
setPhotosError(undefined);
174
+
175
+
(async () => {
176
+
try {
177
+
const photoPromises = backlinks.map(async (backlink) => {
178
+
// Create client for gallery item DID (uses slingshot + PDS fallback)
179
+
const { rpc: galleryItemClient } = await createAtprotoClient({
180
+
did: backlink.did,
181
+
});
182
+
183
+
// Fetch gallery item record
184
+
const galleryItemRes = await (
185
+
galleryItemClient as unknown as {
186
+
get: (
187
+
nsid: string,
188
+
opts: {
189
+
params: {
190
+
repo: string;
191
+
collection: string;
192
+
rkey: string;
193
+
};
194
+
},
195
+
) => Promise<{ ok: boolean; data: { value: GrainGalleryItemRecord } }>;
196
+
}
197
+
).get("com.atproto.repo.getRecord", {
198
+
params: {
199
+
repo: backlink.did,
200
+
collection: GRAIN_GALLERY_ITEM_COLLECTION,
201
+
rkey: backlink.rkey,
202
+
},
203
+
});
204
+
205
+
if (!galleryItemRes.ok) return null;
206
+
207
+
const galleryItem = galleryItemRes.data.value;
208
+
209
+
// Parse photo URI
210
+
const photoUri = parseAtUri(galleryItem.item);
211
+
if (!photoUri) return null;
212
+
213
+
// Create client for photo DID (uses slingshot + PDS fallback)
214
+
const { rpc: photoClient } = await createAtprotoClient({
215
+
did: photoUri.did,
216
+
});
217
+
218
+
// Fetch photo record
219
+
const photoRes = await (
220
+
photoClient as unknown as {
221
+
get: (
222
+
nsid: string,
223
+
opts: {
224
+
params: {
225
+
repo: string;
226
+
collection: string;
227
+
rkey: string;
228
+
};
229
+
},
230
+
) => Promise<{ ok: boolean; data: { value: GrainPhotoRecord } }>;
231
+
}
232
+
).get("com.atproto.repo.getRecord", {
233
+
params: {
234
+
repo: photoUri.did,
235
+
collection: photoUri.collection,
236
+
rkey: photoUri.rkey,
237
+
},
238
+
});
239
+
240
+
if (!photoRes.ok) return null;
241
+
242
+
const photoRecord = photoRes.data.value;
243
+
244
+
return {
245
+
record: photoRecord,
246
+
did: photoUri.did,
247
+
rkey: photoUri.rkey,
248
+
position: galleryItem.position,
249
+
} as GrainGalleryPhoto;
250
+
});
251
+
252
+
const resolvedPhotos = await Promise.all(photoPromises);
253
+
const validPhotos = resolvedPhotos.filter((p): p is NonNullable<typeof p> => p !== null) as GrainGalleryPhoto[];
254
+
255
+
if (!cancelled) {
256
+
setPhotos(validPhotos);
257
+
setPhotosLoading(false);
258
+
}
259
+
} catch (err) {
260
+
if (!cancelled) {
261
+
setPhotosError(err instanceof Error ? err : new Error("Failed to fetch photos"));
262
+
setPhotosLoading(false);
263
+
}
264
+
}
265
+
})();
266
+
267
+
return () => {
268
+
cancelled = true;
269
+
};
270
+
}, [backlinks]);
271
+
272
+
const Comp: React.ComponentType<GrainGalleryRendererInjectedProps> =
273
+
useMemo(
274
+
() =>
275
+
renderer ?? ((props) => <GrainGalleryRenderer {...props} />),
276
+
[renderer],
277
+
);
278
+
279
+
const displayHandle =
280
+
handle ??
281
+
(handleOrDid.startsWith("did:") ? undefined : handleOrDid);
282
+
const authorHandle =
283
+
displayHandle ?? formatDidForLabel(resolvedDid ?? handleOrDid);
284
+
285
+
if (!displayHandle && resolvingIdentity) {
286
+
return loadingIndicator || <div role="status" aria-live="polite" style={{ padding: 8 }}>Resolving handleโฆ</div>;
287
+
}
288
+
if (!displayHandle && resolutionError) {
289
+
return (
290
+
<div style={{ padding: 8, color: "crimson" }}>
291
+
Could not resolve handle.
292
+
</div>
293
+
);
294
+
}
295
+
296
+
if (galleryError || backlinksError || photosError) {
297
+
return (
298
+
<div style={{ padding: 8, color: "crimson" }}>
299
+
Failed to load gallery.
300
+
</div>
301
+
);
302
+
}
303
+
304
+
if (!galleryRecord && galleryLoading) {
305
+
return loadingIndicator || <div style={{ padding: 8 }}>Loading galleryโฆ</div>;
306
+
}
307
+
308
+
if (!galleryRecord) {
309
+
return fallback || <div style={{ padding: 8 }}>Gallery not found.</div>;
310
+
}
311
+
312
+
const loading = galleryLoading || backlinksLoading || photosLoading;
313
+
314
+
return (
315
+
<Comp
316
+
gallery={galleryRecord}
317
+
photos={photos}
318
+
loading={loading}
319
+
authorHandle={authorHandle}
320
+
authorDisplayName={authorDisplayName}
321
+
avatarUrl={avatarUrl}
322
+
/>
323
+
);
324
+
},
325
+
);
326
+
327
+
export default GrainGallery;
+165
lib/components/LastPlayed.tsx
+165
lib/components/LastPlayed.tsx
···
1
+
import React, { useMemo } from "react";
2
+
import { useLatestRecord } from "../hooks/useLatestRecord";
3
+
import { useDidResolution } from "../hooks/useDidResolution";
4
+
import { CurrentlyPlayingRenderer } from "../renderers/CurrentlyPlayingRenderer";
5
+
import type { TealFeedPlayRecord, TealActorStatusRecord } from "../types/teal";
6
+
7
+
/**
8
+
* Props for rendering the last played track from teal.fm feed.
9
+
*/
10
+
export interface LastPlayedProps {
11
+
/** DID of the user whose last played track to display. */
12
+
did: string;
13
+
/** Optional renderer override for custom presentation. */
14
+
renderer?: React.ComponentType<LastPlayedRendererInjectedProps>;
15
+
/** Fallback node displayed before loading begins. */
16
+
fallback?: React.ReactNode;
17
+
/** Indicator node shown while data is loading. */
18
+
loadingIndicator?: React.ReactNode;
19
+
/** Preferred color scheme for theming. */
20
+
colorScheme?: "light" | "dark" | "system";
21
+
/** Auto-refresh music data and album art. Defaults to false for last played. */
22
+
autoRefresh?: boolean;
23
+
/** Refresh interval in milliseconds. Defaults to 60000 (60 seconds). */
24
+
refreshInterval?: number;
25
+
}
26
+
27
+
/**
28
+
* Values injected into custom last played renderer implementations.
29
+
*/
30
+
export type LastPlayedRendererInjectedProps = {
31
+
/** Loaded teal.fm feed play record value. */
32
+
record: TealActorStatusRecord;
33
+
/** Indicates whether the record is currently loading. */
34
+
loading: boolean;
35
+
/** Fetch error, if any. */
36
+
error?: Error;
37
+
/** Preferred color scheme for downstream components. */
38
+
colorScheme?: "light" | "dark" | "system";
39
+
/** DID associated with the record. */
40
+
did: string;
41
+
/** Record key for the play record. */
42
+
rkey: string;
43
+
/** Handle to display in not listening state */
44
+
handle?: string;
45
+
};
46
+
47
+
/** NSID for teal.fm feed play records. */
48
+
export const LAST_PLAYED_COLLECTION = "fm.teal.alpha.feed.play";
49
+
50
+
/**
51
+
* Displays the last played track from teal.fm feed.
52
+
*
53
+
* @param did - DID whose last played track should be fetched.
54
+
* @param renderer - Optional component override that will receive injected props.
55
+
* @param fallback - Node rendered before the first load begins.
56
+
* @param loadingIndicator - Node rendered while the data is loading.
57
+
* @param colorScheme - Preferred color scheme for theming the renderer.
58
+
* @param autoRefresh - When true, refreshes album art and streaming platform links at the specified interval. Defaults to false.
59
+
* @param refreshInterval - Refresh interval in milliseconds. Defaults to 60000 (60 seconds).
60
+
* @returns A JSX subtree representing the last played track with loading states handled.
61
+
*/
62
+
export const LastPlayed: React.FC<LastPlayedProps> = React.memo(({
63
+
did,
64
+
renderer,
65
+
fallback,
66
+
loadingIndicator,
67
+
colorScheme,
68
+
autoRefresh = false,
69
+
refreshInterval = 60000,
70
+
}) => {
71
+
// Resolve handle from DID
72
+
const { handle } = useDidResolution(did);
73
+
74
+
// Auto-refresh key for refetching teal.fm record
75
+
const [refreshKey, setRefreshKey] = React.useState(0);
76
+
77
+
// Auto-refresh interval
78
+
React.useEffect(() => {
79
+
if (!autoRefresh) return;
80
+
81
+
const interval = setInterval(() => {
82
+
setRefreshKey((prev) => prev + 1);
83
+
}, refreshInterval);
84
+
85
+
return () => clearInterval(interval);
86
+
}, [autoRefresh, refreshInterval]);
87
+
88
+
const { record, rkey, loading, error, empty } = useLatestRecord<TealFeedPlayRecord>(
89
+
did,
90
+
LAST_PLAYED_COLLECTION,
91
+
refreshKey,
92
+
);
93
+
94
+
// Normalize TealFeedPlayRecord to match TealActorStatusRecord structure
95
+
// Use useMemo to prevent creating new object on every render
96
+
// MUST be called before any conditional returns (Rules of Hooks)
97
+
const normalizedRecord = useMemo(() => {
98
+
if (!record) return null;
99
+
100
+
return {
101
+
$type: "fm.teal.alpha.actor.status" as const,
102
+
item: {
103
+
artists: record.artists,
104
+
originUrl: record.originUrl,
105
+
trackName: record.trackName,
106
+
playedTime: record.playedTime,
107
+
releaseName: record.releaseName,
108
+
recordingMbId: record.recordingMbId,
109
+
releaseMbId: record.releaseMbId,
110
+
submissionClientAgent: record.submissionClientAgent,
111
+
musicServiceBaseDomain: record.musicServiceBaseDomain,
112
+
isrc: record.isrc,
113
+
duration: record.duration,
114
+
},
115
+
time: new Date(record.playedTime).getTime().toString(),
116
+
expiry: undefined,
117
+
};
118
+
}, [record]);
119
+
120
+
const Comp = renderer ?? CurrentlyPlayingRenderer;
121
+
122
+
// Now handle conditional returns after all hooks
123
+
if (error) {
124
+
return (
125
+
<div style={{ padding: 8, color: "var(--atproto-color-error)" }}>
126
+
Failed to load last played track.
127
+
</div>
128
+
);
129
+
}
130
+
131
+
if (loading && !record) {
132
+
return loadingIndicator ? (
133
+
<>{loadingIndicator}</>
134
+
) : (
135
+
<div style={{ padding: 8, color: "var(--atproto-color-text-secondary)" }}>
136
+
Loadingโฆ
137
+
</div>
138
+
);
139
+
}
140
+
141
+
if (empty || !record || !normalizedRecord) {
142
+
return fallback ? (
143
+
<>{fallback}</>
144
+
) : (
145
+
<div style={{ padding: 8, color: "var(--atproto-color-text-secondary)" }}>
146
+
No plays found.
147
+
</div>
148
+
);
149
+
}
150
+
151
+
return (
152
+
<Comp
153
+
record={normalizedRecord}
154
+
loading={loading}
155
+
error={error}
156
+
colorScheme={colorScheme}
157
+
did={did}
158
+
rkey={rkey || "unknown"}
159
+
label="LAST PLAYED"
160
+
handle={handle}
161
+
/>
162
+
);
163
+
});
164
+
165
+
export default LastPlayed;
+3
-12
lib/components/LeafletDocument.tsx
+3
-12
lib/components/LeafletDocument.tsx
···
8
8
LeafletDocumentRecord,
9
9
LeafletPublicationRecord,
10
10
} from "../types/leaflet";
11
-
import type { ColorSchemePreference } from "../hooks/useColorScheme";
12
11
import {
13
12
parseAtUri,
14
13
toBlueskyPostUrl,
···
45
44
* Indicator rendered while data is being fetched from the PDS.
46
45
*/
47
46
loadingIndicator?: React.ReactNode;
48
-
/**
49
-
* Preferred color scheme to forward to the renderer.
50
-
*/
51
-
colorScheme?: ColorSchemePreference;
52
47
}
53
48
54
49
/**
···
71
66
* @param colorScheme - Preferred color scheme forwarded to the renderer.
72
67
* @returns A JSX subtree that renders a Leaflet document with contextual metadata.
73
68
*/
74
-
export const LeafletDocument: React.FC<LeafletDocumentProps> = ({
69
+
export const LeafletDocument: React.FC<LeafletDocumentProps> = React.memo(({
75
70
did,
76
71
rkey,
77
72
record,
78
73
renderer,
79
74
fallback,
80
75
loadingIndicator,
81
-
colorScheme,
82
76
}) => {
83
77
const Comp: React.ComponentType<LeafletDocumentRendererInjectedProps> =
84
78
renderer ?? ((props) => <LeafletDocumentRenderer {...props} />);
···
111
105
return (
112
106
<Comp
113
107
{...props}
114
-
colorScheme={colorScheme}
115
108
did={did}
116
109
rkey={rkey}
117
110
canonicalUrl={canonicalUrl}
···
121
114
);
122
115
};
123
116
124
-
// When record is provided, pass it directly to skip fetching
125
-
if (record) {
117
+
if (record !== undefined) {
126
118
return (
127
119
<AtProtoRecord<LeafletDocumentRecord>
128
120
record={record}
···
133
125
);
134
126
}
135
127
136
-
// Otherwise fetch the record using did, collection, and rkey
137
128
return (
138
129
<AtProtoRecord<LeafletDocumentRecord>
139
130
did={did}
···
144
135
loadingIndicator={loadingIndicator}
145
136
/>
146
137
);
147
-
};
138
+
});
148
139
149
140
/**
150
141
* Determines the best canonical URL to expose for a Leaflet document.
+125
lib/components/RichText.tsx
+125
lib/components/RichText.tsx
···
1
+
import React from "react";
2
+
import type { AppBskyRichtextFacet } from "@atcute/bluesky";
3
+
import { createTextSegments, type TextSegment } from "../utils/richtext";
4
+
import { useAtProto } from "../providers/AtProtoProvider";
5
+
6
+
export interface RichTextProps {
7
+
text: string;
8
+
facets?: AppBskyRichtextFacet.Main[];
9
+
style?: React.CSSProperties;
10
+
}
11
+
12
+
/**
13
+
* RichText component that renders text with facets (mentions, links, hashtags).
14
+
* Properly handles byte offsets and multi-byte characters.
15
+
*/
16
+
export const RichText: React.FC<RichTextProps> = ({ text, facets, style }) => {
17
+
const { blueskyAppBaseUrl } = useAtProto();
18
+
const segments = createTextSegments(text, facets);
19
+
20
+
return (
21
+
<span style={style}>
22
+
{segments.map((segment, idx) => (
23
+
<RichTextSegment key={idx} segment={segment} blueskyAppBaseUrl={blueskyAppBaseUrl} />
24
+
))}
25
+
</span>
26
+
);
27
+
};
28
+
29
+
interface RichTextSegmentProps {
30
+
segment: TextSegment;
31
+
blueskyAppBaseUrl: string;
32
+
}
33
+
34
+
const RichTextSegment: React.FC<RichTextSegmentProps> = ({ segment, blueskyAppBaseUrl }) => {
35
+
if (!segment.facet) {
36
+
return <>{segment.text}</>;
37
+
}
38
+
39
+
// Find the first feature in the facet
40
+
const feature = segment.facet.features?.[0];
41
+
if (!feature) {
42
+
return <>{segment.text}</>;
43
+
}
44
+
45
+
const featureType = (feature as { $type?: string }).$type;
46
+
47
+
// Render based on feature type
48
+
switch (featureType) {
49
+
case "app.bsky.richtext.facet#link": {
50
+
const linkFeature = feature as AppBskyRichtextFacet.Link;
51
+
return (
52
+
<a
53
+
href={linkFeature.uri}
54
+
target="_blank"
55
+
rel="noopener noreferrer"
56
+
style={{
57
+
color: "var(--atproto-color-link)",
58
+
textDecoration: "none",
59
+
}}
60
+
onMouseEnter={(e) => {
61
+
e.currentTarget.style.textDecoration = "underline";
62
+
}}
63
+
onMouseLeave={(e) => {
64
+
e.currentTarget.style.textDecoration = "none";
65
+
}}
66
+
>
67
+
{segment.text}
68
+
</a>
69
+
);
70
+
}
71
+
72
+
case "app.bsky.richtext.facet#mention": {
73
+
const mentionFeature = feature as AppBskyRichtextFacet.Mention;
74
+
const profileUrl = `${blueskyAppBaseUrl}/profile/${mentionFeature.did}`;
75
+
return (
76
+
<a
77
+
href={profileUrl}
78
+
target="_blank"
79
+
rel="noopener noreferrer"
80
+
style={{
81
+
color: "var(--atproto-color-link)",
82
+
textDecoration: "none",
83
+
}}
84
+
onMouseEnter={(e) => {
85
+
e.currentTarget.style.textDecoration = "underline";
86
+
}}
87
+
onMouseLeave={(e) => {
88
+
e.currentTarget.style.textDecoration = "none";
89
+
}}
90
+
>
91
+
{segment.text}
92
+
</a>
93
+
);
94
+
}
95
+
96
+
case "app.bsky.richtext.facet#tag": {
97
+
const tagFeature = feature as AppBskyRichtextFacet.Tag;
98
+
const tagUrl = `${blueskyAppBaseUrl}/hashtag/${encodeURIComponent(tagFeature.tag)}`;
99
+
return (
100
+
<a
101
+
href={tagUrl}
102
+
target="_blank"
103
+
rel="noopener noreferrer"
104
+
style={{
105
+
color: "var(--atproto-color-link)",
106
+
textDecoration: "none",
107
+
}}
108
+
onMouseEnter={(e) => {
109
+
e.currentTarget.style.textDecoration = "underline";
110
+
}}
111
+
onMouseLeave={(e) => {
112
+
e.currentTarget.style.textDecoration = "none";
113
+
}}
114
+
>
115
+
{segment.text}
116
+
</a>
117
+
);
118
+
}
119
+
120
+
default:
121
+
return <>{segment.text}</>;
122
+
}
123
+
};
124
+
125
+
export default RichText;
+648
lib/components/SongHistoryList.tsx
+648
lib/components/SongHistoryList.tsx
···
1
+
import React, { useState, useEffect, useMemo } from "react";
2
+
import { usePaginatedRecords } from "../hooks/usePaginatedRecords";
3
+
import { useDidResolution } from "../hooks/useDidResolution";
4
+
import type { TealFeedPlayRecord } from "../types/teal";
5
+
6
+
/**
7
+
* Options for rendering a paginated list of song history from teal.fm.
8
+
*/
9
+
export interface SongHistoryListProps {
10
+
/**
11
+
* DID whose song history should be fetched.
12
+
*/
13
+
did: string;
14
+
/**
15
+
* Maximum number of records to list per page. Defaults to `6`.
16
+
*/
17
+
limit?: number;
18
+
/**
19
+
* Enables pagination controls when `true`. Defaults to `true`.
20
+
*/
21
+
enablePagination?: boolean;
22
+
}
23
+
24
+
interface SonglinkResponse {
25
+
linksByPlatform: {
26
+
[platform: string]: {
27
+
url: string;
28
+
entityUniqueId: string;
29
+
};
30
+
};
31
+
entitiesByUniqueId: {
32
+
[id: string]: {
33
+
thumbnailUrl?: string;
34
+
title?: string;
35
+
artistName?: string;
36
+
};
37
+
};
38
+
entityUniqueId?: string;
39
+
}
40
+
41
+
/**
42
+
* Fetches a user's song history from teal.fm and renders them with album art focus.
43
+
*
44
+
* @param did - DID whose song history should be displayed.
45
+
* @param limit - Maximum number of songs per page. Default `6`.
46
+
* @param enablePagination - Whether pagination controls should render. Default `true`.
47
+
* @returns A card-like list element with loading, empty, and error handling.
48
+
*/
49
+
export const SongHistoryList: React.FC<SongHistoryListProps> = React.memo(({
50
+
did,
51
+
limit = 6,
52
+
enablePagination = true,
53
+
}) => {
54
+
const { handle: resolvedHandle } = useDidResolution(did);
55
+
const actorLabel = resolvedHandle ?? formatDid(did);
56
+
57
+
const {
58
+
records,
59
+
loading,
60
+
error,
61
+
hasNext,
62
+
hasPrev,
63
+
loadNext,
64
+
loadPrev,
65
+
pageIndex,
66
+
pagesCount,
67
+
} = usePaginatedRecords<TealFeedPlayRecord>({
68
+
did,
69
+
collection: "fm.teal.alpha.feed.play",
70
+
limit,
71
+
});
72
+
73
+
const pageLabel = useMemo(() => {
74
+
const knownTotal = Math.max(pageIndex + 1, pagesCount);
75
+
if (!enablePagination) return undefined;
76
+
if (hasNext && knownTotal === pageIndex + 1)
77
+
return `${pageIndex + 1}/โฆ`;
78
+
return `${pageIndex + 1}/${knownTotal}`;
79
+
}, [enablePagination, hasNext, pageIndex, pagesCount]);
80
+
81
+
if (error)
82
+
return (
83
+
<div role="alert" style={{ padding: 8, color: "crimson" }}>
84
+
Failed to load song history.
85
+
</div>
86
+
);
87
+
88
+
return (
89
+
<div style={{ ...listStyles.card, background: `var(--atproto-color-bg)`, borderWidth: "1px", borderStyle: "solid", borderColor: `var(--atproto-color-border)` }}>
90
+
<div style={{ ...listStyles.header, background: `var(--atproto-color-bg-elevated)`, color: `var(--atproto-color-text)` }}>
91
+
<div style={listStyles.headerInfo}>
92
+
<div style={listStyles.headerIcon}>
93
+
<svg
94
+
width="24"
95
+
height="24"
96
+
viewBox="0 0 24 24"
97
+
fill="none"
98
+
stroke="currentColor"
99
+
strokeWidth="2"
100
+
strokeLinecap="round"
101
+
strokeLinejoin="round"
102
+
>
103
+
<path d="M9 18V5l12-2v13" />
104
+
<circle cx="6" cy="18" r="3" />
105
+
<circle cx="18" cy="16" r="3" />
106
+
</svg>
107
+
</div>
108
+
<div style={listStyles.headerText}>
109
+
<span style={listStyles.title}>Listening History</span>
110
+
<span
111
+
style={{
112
+
...listStyles.subtitle,
113
+
color: `var(--atproto-color-text-secondary)`,
114
+
}}
115
+
>
116
+
@{actorLabel}
117
+
</span>
118
+
</div>
119
+
</div>
120
+
{pageLabel && (
121
+
<span
122
+
style={{ ...listStyles.pageMeta, color: `var(--atproto-color-text-secondary)` }}
123
+
>
124
+
{pageLabel}
125
+
</span>
126
+
)}
127
+
</div>
128
+
<div style={listStyles.items}>
129
+
{loading && records.length === 0 && (
130
+
<div style={{ ...listStyles.empty, color: `var(--atproto-color-text-secondary)` }}>
131
+
Loading songsโฆ
132
+
</div>
133
+
)}
134
+
{records.map((record, idx) => (
135
+
<SongRow
136
+
key={`${record.rkey}-${record.value.playedTime}`}
137
+
record={record.value}
138
+
hasDivider={idx < records.length - 1}
139
+
/>
140
+
))}
141
+
{!loading && records.length === 0 && (
142
+
<div style={{ ...listStyles.empty, color: `var(--atproto-color-text-secondary)` }}>
143
+
No songs found.
144
+
</div>
145
+
)}
146
+
</div>
147
+
{enablePagination && (
148
+
<div style={{ ...listStyles.footer, borderTopColor: `var(--atproto-color-border)`, color: `var(--atproto-color-text)` }}>
149
+
<button
150
+
type="button"
151
+
style={{
152
+
...listStyles.pageButton,
153
+
background: `var(--atproto-color-button-bg)`,
154
+
color: `var(--atproto-color-button-text)`,
155
+
cursor: hasPrev ? "pointer" : "not-allowed",
156
+
opacity: hasPrev ? 1 : 0.5,
157
+
}}
158
+
onClick={loadPrev}
159
+
disabled={!hasPrev}
160
+
>
161
+
โน Prev
162
+
</button>
163
+
<div style={listStyles.pageChips}>
164
+
<span
165
+
style={{
166
+
...listStyles.pageChipActive,
167
+
color: `var(--atproto-color-button-text)`,
168
+
background: `var(--atproto-color-button-bg)`,
169
+
borderWidth: "1px",
170
+
borderStyle: "solid",
171
+
borderColor: `var(--atproto-color-button-bg)`,
172
+
}}
173
+
>
174
+
{pageIndex + 1}
175
+
</span>
176
+
{(hasNext || pagesCount > pageIndex + 1) && (
177
+
<span
178
+
style={{
179
+
...listStyles.pageChip,
180
+
color: `var(--atproto-color-text-secondary)`,
181
+
borderWidth: "1px",
182
+
borderStyle: "solid",
183
+
borderColor: `var(--atproto-color-border)`,
184
+
background: `var(--atproto-color-bg)`,
185
+
}}
186
+
>
187
+
{pageIndex + 2}
188
+
</span>
189
+
)}
190
+
</div>
191
+
<button
192
+
type="button"
193
+
style={{
194
+
...listStyles.pageButton,
195
+
background: `var(--atproto-color-button-bg)`,
196
+
color: `var(--atproto-color-button-text)`,
197
+
cursor: hasNext ? "pointer" : "not-allowed",
198
+
opacity: hasNext ? 1 : 0.5,
199
+
}}
200
+
onClick={loadNext}
201
+
disabled={!hasNext}
202
+
>
203
+
Next โบ
204
+
</button>
205
+
</div>
206
+
)}
207
+
{loading && records.length > 0 && (
208
+
<div
209
+
style={{ ...listStyles.loadingBar, background: `var(--atproto-color-bg-elevated)`, color: `var(--atproto-color-text-secondary)` }}
210
+
>
211
+
Updatingโฆ
212
+
</div>
213
+
)}
214
+
</div>
215
+
);
216
+
});
217
+
218
+
interface SongRowProps {
219
+
record: TealFeedPlayRecord;
220
+
hasDivider: boolean;
221
+
}
222
+
223
+
const SongRow: React.FC<SongRowProps> = ({ record, hasDivider }) => {
224
+
const [albumArt, setAlbumArt] = useState<string | undefined>(undefined);
225
+
const [artLoading, setArtLoading] = useState(true);
226
+
227
+
const artistNames = record.artists.map((a) => a.artistName).join(", ");
228
+
const relative = record.playedTime
229
+
? formatRelativeTime(record.playedTime)
230
+
: undefined;
231
+
const absolute = record.playedTime
232
+
? new Date(record.playedTime).toLocaleString()
233
+
: undefined;
234
+
235
+
useEffect(() => {
236
+
let cancelled = false;
237
+
setArtLoading(true);
238
+
setAlbumArt(undefined);
239
+
240
+
const fetchAlbumArt = async () => {
241
+
try {
242
+
// Try ISRC first
243
+
if (record.isrc) {
244
+
const response = await fetch(
245
+
`https://api.song.link/v1-alpha.1/links?platform=isrc&type=song&id=${encodeURIComponent(record.isrc)}&songIfSingle=true`
246
+
);
247
+
if (cancelled) return;
248
+
if (response.ok) {
249
+
const data: SonglinkResponse = await response.json();
250
+
const entityId = data.entityUniqueId;
251
+
const entity = entityId ? data.entitiesByUniqueId?.[entityId] : undefined;
252
+
if (entity?.thumbnailUrl) {
253
+
setAlbumArt(entity.thumbnailUrl);
254
+
setArtLoading(false);
255
+
return;
256
+
}
257
+
}
258
+
}
259
+
260
+
// Fallback to iTunes search
261
+
const iTunesSearchUrl = `https://itunes.apple.com/search?term=${encodeURIComponent(
262
+
`${record.trackName} ${artistNames}`
263
+
)}&media=music&entity=song&limit=1`;
264
+
265
+
const iTunesResponse = await fetch(iTunesSearchUrl);
266
+
if (cancelled) return;
267
+
268
+
if (iTunesResponse.ok) {
269
+
const iTunesData = await iTunesResponse.json();
270
+
if (iTunesData.results && iTunesData.results.length > 0) {
271
+
const match = iTunesData.results[0];
272
+
const artworkUrl = match.artworkUrl100?.replace('100x100', '600x600') || match.artworkUrl100;
273
+
if (artworkUrl) {
274
+
setAlbumArt(artworkUrl);
275
+
}
276
+
}
277
+
}
278
+
setArtLoading(false);
279
+
} catch (err) {
280
+
console.error(`Failed to fetch album art for "${record.trackName}":`, err);
281
+
setArtLoading(false);
282
+
}
283
+
};
284
+
285
+
fetchAlbumArt();
286
+
287
+
return () => {
288
+
cancelled = true;
289
+
};
290
+
}, [record.trackName, artistNames, record.isrc]);
291
+
292
+
return (
293
+
<div
294
+
style={{
295
+
...listStyles.row,
296
+
color: `var(--atproto-color-text)`,
297
+
borderBottom: hasDivider
298
+
? `1px solid var(--atproto-color-border)`
299
+
: "none",
300
+
}}
301
+
>
302
+
{/* Album Art - Large and prominent */}
303
+
<div style={listStyles.albumArtContainer}>
304
+
{artLoading ? (
305
+
<div style={listStyles.albumArtPlaceholder}>
306
+
<div style={listStyles.loadingSpinner} />
307
+
</div>
308
+
) : albumArt ? (
309
+
<img
310
+
src={albumArt}
311
+
alt={`${record.releaseName || "Album"} cover`}
312
+
style={listStyles.albumArt}
313
+
onError={(e) => {
314
+
e.currentTarget.style.display = "none";
315
+
const parent = e.currentTarget.parentElement;
316
+
if (parent) {
317
+
const placeholder = document.createElement("div");
318
+
Object.assign(placeholder.style, listStyles.albumArtPlaceholder);
319
+
placeholder.innerHTML = `
320
+
<svg
321
+
width="48"
322
+
height="48"
323
+
viewBox="0 0 24 24"
324
+
fill="none"
325
+
stroke="currentColor"
326
+
stroke-width="1.5"
327
+
>
328
+
<circle cx="12" cy="12" r="10" />
329
+
<circle cx="12" cy="12" r="3" />
330
+
<path d="M12 2v3M12 19v3M2 12h3M19 12h3" />
331
+
</svg>
332
+
`;
333
+
parent.appendChild(placeholder);
334
+
}
335
+
}}
336
+
/>
337
+
) : (
338
+
<div style={listStyles.albumArtPlaceholder}>
339
+
<svg
340
+
width="48"
341
+
height="48"
342
+
viewBox="0 0 24 24"
343
+
fill="none"
344
+
stroke="currentColor"
345
+
strokeWidth="1.5"
346
+
>
347
+
<circle cx="12" cy="12" r="10" />
348
+
<circle cx="12" cy="12" r="3" />
349
+
<path d="M12 2v3M12 19v3M2 12h3M19 12h3" />
350
+
</svg>
351
+
</div>
352
+
)}
353
+
</div>
354
+
355
+
{/* Song Info */}
356
+
<div style={listStyles.songInfo}>
357
+
<div style={listStyles.trackName}>{record.trackName}</div>
358
+
<div style={{ ...listStyles.artistName, color: `var(--atproto-color-text-secondary)` }}>
359
+
{artistNames}
360
+
</div>
361
+
{record.releaseName && (
362
+
<div style={{ ...listStyles.releaseName, color: `var(--atproto-color-text-secondary)` }}>
363
+
{record.releaseName}
364
+
</div>
365
+
)}
366
+
{relative && (
367
+
<div
368
+
style={{ ...listStyles.playedTime, color: `var(--atproto-color-text-secondary)` }}
369
+
title={absolute}
370
+
>
371
+
{relative}
372
+
</div>
373
+
)}
374
+
</div>
375
+
376
+
{/* External Link */}
377
+
{record.originUrl && (
378
+
<a
379
+
href={record.originUrl}
380
+
target="_blank"
381
+
rel="noopener noreferrer"
382
+
style={listStyles.externalLink}
383
+
title="Listen on streaming service"
384
+
aria-label={`Listen to ${record.trackName} by ${artistNames}`}
385
+
>
386
+
<svg
387
+
width="20"
388
+
height="20"
389
+
viewBox="0 0 24 24"
390
+
fill="none"
391
+
stroke="currentColor"
392
+
strokeWidth="2"
393
+
strokeLinecap="round"
394
+
strokeLinejoin="round"
395
+
>
396
+
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />
397
+
<polyline points="15 3 21 3 21 9" />
398
+
<line x1="10" y1="14" x2="21" y2="3" />
399
+
</svg>
400
+
</a>
401
+
)}
402
+
</div>
403
+
);
404
+
};
405
+
406
+
function formatDid(did: string) {
407
+
return did.replace(/^did:(plc:)?/, "");
408
+
}
409
+
410
+
function formatRelativeTime(iso: string): string {
411
+
const date = new Date(iso);
412
+
const diffSeconds = (date.getTime() - Date.now()) / 1000;
413
+
const absSeconds = Math.abs(diffSeconds);
414
+
const thresholds: Array<{
415
+
limit: number;
416
+
unit: Intl.RelativeTimeFormatUnit;
417
+
divisor: number;
418
+
}> = [
419
+
{ limit: 60, unit: "second", divisor: 1 },
420
+
{ limit: 3600, unit: "minute", divisor: 60 },
421
+
{ limit: 86400, unit: "hour", divisor: 3600 },
422
+
{ limit: 604800, unit: "day", divisor: 86400 },
423
+
{ limit: 2629800, unit: "week", divisor: 604800 },
424
+
{ limit: 31557600, unit: "month", divisor: 2629800 },
425
+
{ limit: Infinity, unit: "year", divisor: 31557600 },
426
+
];
427
+
const threshold =
428
+
thresholds.find((t) => absSeconds < t.limit) ??
429
+
thresholds[thresholds.length - 1];
430
+
const value = diffSeconds / threshold.divisor;
431
+
const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" });
432
+
return rtf.format(Math.round(value), threshold.unit);
433
+
}
434
+
435
+
const listStyles = {
436
+
card: {
437
+
borderRadius: 16,
438
+
borderWidth: "1px",
439
+
borderStyle: "solid",
440
+
borderColor: "transparent",
441
+
boxShadow: "0 8px 18px -12px rgba(15, 23, 42, 0.25)",
442
+
overflow: "hidden",
443
+
display: "flex",
444
+
flexDirection: "column",
445
+
} satisfies React.CSSProperties,
446
+
header: {
447
+
display: "flex",
448
+
alignItems: "center",
449
+
justifyContent: "space-between",
450
+
padding: "14px 18px",
451
+
fontSize: 14,
452
+
fontWeight: 500,
453
+
borderBottom: "1px solid var(--atproto-color-border)",
454
+
} satisfies React.CSSProperties,
455
+
headerInfo: {
456
+
display: "flex",
457
+
alignItems: "center",
458
+
gap: 12,
459
+
} satisfies React.CSSProperties,
460
+
headerIcon: {
461
+
width: 28,
462
+
height: 28,
463
+
display: "flex",
464
+
alignItems: "center",
465
+
justifyContent: "center",
466
+
borderRadius: "50%",
467
+
color: "var(--atproto-color-text)",
468
+
} satisfies React.CSSProperties,
469
+
headerText: {
470
+
display: "flex",
471
+
flexDirection: "column",
472
+
gap: 2,
473
+
} satisfies React.CSSProperties,
474
+
title: {
475
+
fontSize: 15,
476
+
fontWeight: 600,
477
+
} satisfies React.CSSProperties,
478
+
subtitle: {
479
+
fontSize: 12,
480
+
fontWeight: 500,
481
+
} satisfies React.CSSProperties,
482
+
pageMeta: {
483
+
fontSize: 12,
484
+
} satisfies React.CSSProperties,
485
+
items: {
486
+
display: "flex",
487
+
flexDirection: "column",
488
+
} satisfies React.CSSProperties,
489
+
empty: {
490
+
padding: "24px 18px",
491
+
fontSize: 13,
492
+
textAlign: "center",
493
+
} satisfies React.CSSProperties,
494
+
row: {
495
+
padding: "18px",
496
+
display: "flex",
497
+
gap: 16,
498
+
alignItems: "center",
499
+
transition: "background-color 120ms ease",
500
+
position: "relative",
501
+
} satisfies React.CSSProperties,
502
+
albumArtContainer: {
503
+
width: 96,
504
+
height: 96,
505
+
flexShrink: 0,
506
+
borderRadius: 8,
507
+
overflow: "hidden",
508
+
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
509
+
} satisfies React.CSSProperties,
510
+
albumArt: {
511
+
width: "100%",
512
+
height: "100%",
513
+
objectFit: "cover",
514
+
display: "block",
515
+
} satisfies React.CSSProperties,
516
+
albumArtPlaceholder: {
517
+
width: "100%",
518
+
height: "100%",
519
+
display: "flex",
520
+
alignItems: "center",
521
+
justifyContent: "center",
522
+
background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
523
+
color: "rgba(255, 255, 255, 0.6)",
524
+
} satisfies React.CSSProperties,
525
+
loadingSpinner: {
526
+
width: 28,
527
+
height: 28,
528
+
border: "3px solid rgba(255, 255, 255, 0.3)",
529
+
borderTop: "3px solid rgba(255, 255, 255, 0.9)",
530
+
borderRadius: "50%",
531
+
animation: "spin 1s linear infinite",
532
+
} satisfies React.CSSProperties,
533
+
songInfo: {
534
+
flex: 1,
535
+
display: "flex",
536
+
flexDirection: "column",
537
+
gap: 4,
538
+
minWidth: 0,
539
+
} satisfies React.CSSProperties,
540
+
trackName: {
541
+
fontSize: 16,
542
+
fontWeight: 600,
543
+
lineHeight: 1.3,
544
+
color: "var(--atproto-color-text)",
545
+
overflow: "hidden",
546
+
textOverflow: "ellipsis",
547
+
whiteSpace: "nowrap",
548
+
} satisfies React.CSSProperties,
549
+
artistName: {
550
+
fontSize: 14,
551
+
fontWeight: 500,
552
+
overflow: "hidden",
553
+
textOverflow: "ellipsis",
554
+
whiteSpace: "nowrap",
555
+
} satisfies React.CSSProperties,
556
+
releaseName: {
557
+
fontSize: 13,
558
+
overflow: "hidden",
559
+
textOverflow: "ellipsis",
560
+
whiteSpace: "nowrap",
561
+
} satisfies React.CSSProperties,
562
+
playedTime: {
563
+
fontSize: 12,
564
+
fontWeight: 500,
565
+
marginTop: 2,
566
+
} satisfies React.CSSProperties,
567
+
externalLink: {
568
+
flexShrink: 0,
569
+
width: 36,
570
+
height: 36,
571
+
display: "flex",
572
+
alignItems: "center",
573
+
justifyContent: "center",
574
+
borderRadius: "50%",
575
+
background: "var(--atproto-color-bg-elevated)",
576
+
border: "1px solid var(--atproto-color-border)",
577
+
color: "var(--atproto-color-text-secondary)",
578
+
cursor: "pointer",
579
+
transition: "all 0.2s ease",
580
+
textDecoration: "none",
581
+
} satisfies React.CSSProperties,
582
+
footer: {
583
+
display: "flex",
584
+
alignItems: "center",
585
+
justifyContent: "space-between",
586
+
padding: "12px 18px",
587
+
borderTop: "1px solid transparent",
588
+
fontSize: 13,
589
+
} satisfies React.CSSProperties,
590
+
pageChips: {
591
+
display: "flex",
592
+
gap: 6,
593
+
alignItems: "center",
594
+
} satisfies React.CSSProperties,
595
+
pageChip: {
596
+
padding: "4px 10px",
597
+
borderRadius: 999,
598
+
fontSize: 13,
599
+
borderWidth: "1px",
600
+
borderStyle: "solid",
601
+
borderColor: "transparent",
602
+
} satisfies React.CSSProperties,
603
+
pageChipActive: {
604
+
padding: "4px 10px",
605
+
borderRadius: 999,
606
+
fontSize: 13,
607
+
fontWeight: 600,
608
+
borderWidth: "1px",
609
+
borderStyle: "solid",
610
+
borderColor: "transparent",
611
+
} satisfies React.CSSProperties,
612
+
pageButton: {
613
+
border: "none",
614
+
borderRadius: 999,
615
+
padding: "6px 12px",
616
+
fontSize: 13,
617
+
fontWeight: 500,
618
+
background: "transparent",
619
+
display: "flex",
620
+
alignItems: "center",
621
+
gap: 4,
622
+
transition: "background-color 120ms ease",
623
+
} satisfies React.CSSProperties,
624
+
loadingBar: {
625
+
padding: "4px 18px 14px",
626
+
fontSize: 12,
627
+
textAlign: "right",
628
+
color: "#64748b",
629
+
} satisfies React.CSSProperties,
630
+
};
631
+
632
+
// Add keyframes and hover styles
633
+
if (typeof document !== "undefined") {
634
+
const styleId = "song-history-styles";
635
+
if (!document.getElementById(styleId)) {
636
+
const styleElement = document.createElement("style");
637
+
styleElement.id = styleId;
638
+
styleElement.textContent = `
639
+
@keyframes spin {
640
+
0% { transform: rotate(0deg); }
641
+
100% { transform: rotate(360deg); }
642
+
}
643
+
`;
644
+
document.head.appendChild(styleElement);
645
+
}
646
+
}
647
+
648
+
export default SongHistoryList;
+131
lib/components/TangledRepo.tsx
+131
lib/components/TangledRepo.tsx
···
1
+
import React from "react";
2
+
import { AtProtoRecord } from "../core/AtProtoRecord";
3
+
import { TangledRepoRenderer } from "../renderers/TangledRepoRenderer";
4
+
import type { TangledRepoRecord } from "../types/tangled";
5
+
import { useAtProto } from "../providers/AtProtoProvider";
6
+
7
+
/**
8
+
* Props for rendering Tangled Repo records.
9
+
*/
10
+
export interface TangledRepoProps {
11
+
/** DID of the repository that stores the repo record. */
12
+
did: string;
13
+
/** Record key within the `sh.tangled.repo` collection. */
14
+
rkey: string;
15
+
/** Prefetched Tangled Repo record. When provided, skips fetching from the network. */
16
+
record?: TangledRepoRecord;
17
+
/** Optional renderer override for custom presentation. */
18
+
renderer?: React.ComponentType<TangledRepoRendererInjectedProps>;
19
+
/** Fallback node displayed before loading begins. */
20
+
fallback?: React.ReactNode;
21
+
/** Indicator node shown while data is loading. */
22
+
loadingIndicator?: React.ReactNode;
23
+
/** Preferred color scheme for theming. */
24
+
colorScheme?: "light" | "dark" | "system";
25
+
/** Whether to show star count from backlinks. Defaults to true. */
26
+
showStarCount?: boolean;
27
+
/** Branch to query for language information. Defaults to trying "main", then "master". */
28
+
branch?: string;
29
+
/** Prefetched language names (e.g., ['TypeScript', 'React']). When provided, skips fetching languages from the knot server. */
30
+
languages?: string[];
31
+
}
32
+
33
+
/**
34
+
* Values injected into custom Tangled Repo renderer implementations.
35
+
*/
36
+
export type TangledRepoRendererInjectedProps = {
37
+
/** Loaded Tangled Repo record value. */
38
+
record: TangledRepoRecord;
39
+
/** Indicates whether the record is currently loading. */
40
+
loading: boolean;
41
+
/** Fetch error, if any. */
42
+
error?: Error;
43
+
/** Preferred color scheme for downstream components. */
44
+
colorScheme?: "light" | "dark" | "system";
45
+
/** DID associated with the record. */
46
+
did: string;
47
+
/** Record key for the repo. */
48
+
rkey: string;
49
+
/** Canonical external URL for linking to the repo. */
50
+
canonicalUrl: string;
51
+
/** Whether to show star count from backlinks. */
52
+
showStarCount?: boolean;
53
+
/** Branch to query for language information. */
54
+
branch?: string;
55
+
/** Prefetched language names. */
56
+
languages?: string[];
57
+
};
58
+
59
+
/** NSID for Tangled Repo records. */
60
+
export const TANGLED_REPO_COLLECTION = "sh.tangled.repo";
61
+
62
+
/**
63
+
* Resolves a Tangled Repo record and renders it with optional overrides while computing a canonical link.
64
+
*
65
+
* @param did - DID whose Tangled Repo should be fetched.
66
+
* @param rkey - Record key within the Tangled Repo collection.
67
+
* @param renderer - Optional component override that will receive injected props.
68
+
* @param fallback - Node rendered before the first load begins.
69
+
* @param loadingIndicator - Node rendered while the Tangled Repo is loading.
70
+
* @param colorScheme - Preferred color scheme for theming the renderer.
71
+
* @param showStarCount - Whether to show star count from backlinks. Defaults to true.
72
+
* @param branch - Branch to query for language information. Defaults to trying "main", then "master".
73
+
* @param languages - Prefetched language names (e.g., ['TypeScript', 'React']). When provided, skips fetching languages from the knot server.
74
+
* @returns A JSX subtree representing the Tangled Repo record with loading states handled.
75
+
*/
76
+
export const TangledRepo: React.FC<TangledRepoProps> = React.memo(({
77
+
did,
78
+
rkey,
79
+
record,
80
+
renderer,
81
+
fallback,
82
+
loadingIndicator,
83
+
colorScheme,
84
+
showStarCount = true,
85
+
branch,
86
+
languages,
87
+
}) => {
88
+
const { tangledBaseUrl } = useAtProto();
89
+
const Comp: React.ComponentType<TangledRepoRendererInjectedProps> =
90
+
renderer ?? ((props) => <TangledRepoRenderer {...props} />);
91
+
const Wrapped: React.FC<{
92
+
record: TangledRepoRecord;
93
+
loading: boolean;
94
+
error?: Error;
95
+
}> = (props) => (
96
+
<Comp
97
+
{...props}
98
+
colorScheme={colorScheme}
99
+
did={did}
100
+
rkey={rkey}
101
+
canonicalUrl={`${tangledBaseUrl}/${did}/${encodeURIComponent(props.record.name)}`}
102
+
showStarCount={showStarCount}
103
+
branch={branch}
104
+
languages={languages}
105
+
/>
106
+
);
107
+
108
+
if (record !== undefined) {
109
+
return (
110
+
<AtProtoRecord<TangledRepoRecord>
111
+
record={record}
112
+
renderer={Wrapped}
113
+
fallback={fallback}
114
+
loadingIndicator={loadingIndicator}
115
+
/>
116
+
);
117
+
}
118
+
119
+
return (
120
+
<AtProtoRecord<TangledRepoRecord>
121
+
did={did}
122
+
collection={TANGLED_REPO_COLLECTION}
123
+
rkey={rkey}
124
+
renderer={Wrapped}
125
+
fallback={fallback}
126
+
loadingIndicator={loadingIndicator}
127
+
/>
128
+
);
129
+
});
130
+
131
+
export default TangledRepo;
+7
-7
lib/components/TangledString.tsx
+7
-7
lib/components/TangledString.tsx
···
1
1
import React from "react";
2
2
import { AtProtoRecord } from "../core/AtProtoRecord";
3
3
import { TangledStringRenderer } from "../renderers/TangledStringRenderer";
4
-
import type { TangledStringRecord } from "../renderers/TangledStringRenderer";
4
+
import type { TangledStringRecord } from "../types/tangled";
5
+
import { useAtProto } from "../providers/AtProtoProvider";
5
6
6
7
/**
7
8
* Props for rendering Tangled String records.
···
57
58
* @param colorScheme - Preferred color scheme for theming the renderer.
58
59
* @returns A JSX subtree representing the Tangled String record with loading states handled.
59
60
*/
60
-
export const TangledString: React.FC<TangledStringProps> = ({
61
+
export const TangledString: React.FC<TangledStringProps> = React.memo(({
61
62
did,
62
63
rkey,
63
64
record,
···
66
67
loadingIndicator,
67
68
colorScheme,
68
69
}) => {
70
+
const { tangledBaseUrl } = useAtProto();
69
71
const Comp: React.ComponentType<TangledStringRendererInjectedProps> =
70
72
renderer ?? ((props) => <TangledStringRenderer {...props} />);
71
73
const Wrapped: React.FC<{
···
78
80
colorScheme={colorScheme}
79
81
did={did}
80
82
rkey={rkey}
81
-
canonicalUrl={`https://tangled.org/strings/${did}/${encodeURIComponent(rkey)}`}
83
+
canonicalUrl={`${tangledBaseUrl}/strings/${did}/${encodeURIComponent(rkey)}`}
82
84
/>
83
85
);
84
86
85
-
// When record is provided, pass it directly to skip fetching
86
-
if (record) {
87
+
if (record !== undefined) {
87
88
return (
88
89
<AtProtoRecord<TangledStringRecord>
89
90
record={record}
···
94
95
);
95
96
}
96
97
97
-
// Otherwise fetch the record using did, collection, and rkey
98
98
return (
99
99
<AtProtoRecord<TangledStringRecord>
100
100
did={did}
···
105
105
loadingIndicator={loadingIndicator}
106
106
/>
107
107
);
108
-
};
108
+
});
109
109
110
110
export default TangledString;
+123
-6
lib/core/AtProtoRecord.tsx
+123
-6
lib/core/AtProtoRecord.tsx
···
1
-
import React from "react";
1
+
import React, { useState, useEffect, useRef } from "react";
2
2
import { useAtProtoRecord } from "../hooks/useAtProtoRecord";
3
3
4
+
/**
5
+
* Common rendering customization props for AT Protocol records.
6
+
*/
4
7
interface AtProtoRecordRenderProps<T> {
8
+
/** Custom renderer component that receives the fetched record and loading state. */
5
9
renderer?: React.ComponentType<{
6
10
record: T;
7
11
loading: boolean;
8
12
error?: Error;
9
13
}>;
14
+
/** React node displayed when no record is available (after error or before load). */
10
15
fallback?: React.ReactNode;
16
+
/** React node shown while the record is being fetched. */
11
17
loadingIndicator?: React.ReactNode;
18
+
/** Auto-refresh interval in milliseconds. When set, the record will be refetched at this interval. */
19
+
refreshInterval?: number;
20
+
/** Comparison function to determine if a record has changed. Used to prevent unnecessary re-renders during auto-refresh. */
21
+
compareRecords?: (prev: T | undefined, next: T | undefined) => boolean;
12
22
}
13
23
24
+
/**
25
+
* Props for fetching an AT Protocol record from the network.
26
+
*/
14
27
type AtProtoRecordFetchProps<T> = AtProtoRecordRenderProps<T> & {
28
+
/** Repository DID that owns the record. */
15
29
did: string;
30
+
/** NSID collection containing the record. */
16
31
collection: string;
32
+
/** Record key identifying the specific record. */
17
33
rkey: string;
34
+
/** Must be undefined when fetching (discriminates the union type). */
18
35
record?: undefined;
19
36
};
20
37
38
+
/**
39
+
* Props for rendering a prefetched AT Protocol record.
40
+
*/
21
41
type AtProtoRecordProvidedRecordProps<T> = AtProtoRecordRenderProps<T> & {
42
+
/** Prefetched record value to render (skips network fetch). */
22
43
record: T;
44
+
/** Optional DID for context (not used for fetching). */
23
45
did?: string;
46
+
/** Optional collection for context (not used for fetching). */
24
47
collection?: string;
48
+
/** Optional rkey for context (not used for fetching). */
25
49
rkey?: string;
26
50
};
27
51
52
+
/**
53
+
* Union type for AT Protocol record props - supports both fetching and prefetched records.
54
+
*/
28
55
export type AtProtoRecordProps<T = unknown> =
29
56
| AtProtoRecordFetchProps<T>
30
57
| AtProtoRecordProvidedRecordProps<T>;
31
58
59
+
/**
60
+
* Core component for fetching and rendering AT Protocol records with customizable presentation.
61
+
*
62
+
* Supports two modes:
63
+
* 1. **Fetch mode**: Provide `did`, `collection`, and `rkey` to fetch the record from the network
64
+
* 2. **Prefetch mode**: Provide a `record` directly to skip fetching (useful for SSR/caching)
65
+
*
66
+
* When no custom renderer is provided, displays the record as formatted JSON.
67
+
*
68
+
* **Auto-refresh**: Set `refreshInterval` to automatically refetch the record at the specified interval.
69
+
* The component intelligently avoids re-rendering if the record hasn't changed (using `compareRecords`).
70
+
*
71
+
* @example
72
+
* ```tsx
73
+
* // Fetch mode - retrieves record from network
74
+
* <AtProtoRecord
75
+
* did="did:plc:example"
76
+
* collection="app.bsky.feed.post"
77
+
* rkey="3k2aexample"
78
+
* renderer={MyCustomRenderer}
79
+
* />
80
+
* ```
81
+
*
82
+
* @example
83
+
* ```tsx
84
+
* // Prefetch mode - uses provided record
85
+
* <AtProtoRecord
86
+
* record={myPrefetchedRecord}
87
+
* renderer={MyCustomRenderer}
88
+
* />
89
+
* ```
90
+
*
91
+
* @example
92
+
* ```tsx
93
+
* // Auto-refresh mode - refetches every 15 seconds
94
+
* <AtProtoRecord
95
+
* did="did:plc:example"
96
+
* collection="fm.teal.alpha.actor.status"
97
+
* rkey="self"
98
+
* refreshInterval={15000}
99
+
* compareRecords={(prev, next) => JSON.stringify(prev) === JSON.stringify(next)}
100
+
* renderer={MyCustomRenderer}
101
+
* />
102
+
* ```
103
+
*
104
+
* @param props - Either fetch props (did/collection/rkey) or prefetch props (record).
105
+
* @returns A rendered AT Protocol record with loading/error states handled.
106
+
*/
32
107
export function AtProtoRecord<T = unknown>(props: AtProtoRecordProps<T>) {
33
108
const {
34
109
renderer: Renderer,
35
110
fallback = null,
36
111
loadingIndicator = "Loadingโฆ",
112
+
refreshInterval,
113
+
compareRecords,
37
114
} = props;
38
115
const hasProvidedRecord = "record" in props;
39
116
const providedRecord = hasProvidedRecord ? props.record : undefined;
40
117
118
+
// Extract fetch props for logging
119
+
const fetchDid = hasProvidedRecord ? undefined : (props as any).did;
120
+
const fetchCollection = hasProvidedRecord ? undefined : (props as any).collection;
121
+
const fetchRkey = hasProvidedRecord ? undefined : (props as any).rkey;
122
+
123
+
// State for managing auto-refresh
124
+
const [refreshKey, setRefreshKey] = useState(0);
125
+
const [stableRecord, setStableRecord] = useState<T | undefined>(providedRecord);
126
+
const previousRecordRef = useRef<T | undefined>(providedRecord);
127
+
128
+
// Auto-refresh interval
129
+
useEffect(() => {
130
+
if (!refreshInterval || hasProvidedRecord) return;
131
+
132
+
const interval = setInterval(() => {
133
+
setRefreshKey((prev) => prev + 1);
134
+
}, refreshInterval);
135
+
136
+
return () => clearInterval(interval);
137
+
}, [refreshInterval, hasProvidedRecord, fetchCollection, fetchDid]);
138
+
41
139
const {
42
140
record: fetchedRecord,
43
141
error,
44
142
loading,
45
143
} = useAtProtoRecord<T>({
46
-
did: hasProvidedRecord ? undefined : props.did,
47
-
collection: hasProvidedRecord ? undefined : props.collection,
48
-
rkey: hasProvidedRecord ? undefined : props.rkey,
144
+
did: fetchDid,
145
+
collection: fetchCollection,
146
+
rkey: fetchRkey,
147
+
bypassCache: !!refreshInterval && refreshKey > 0, // Bypass cache on auto-refresh (but not initial load)
148
+
_refreshKey: refreshKey, // Force hook to re-run
49
149
});
50
150
51
-
const record = providedRecord ?? fetchedRecord;
52
-
const isLoading = loading && !providedRecord;
151
+
// Determine which record to use
152
+
const currentRecord = providedRecord ?? fetchedRecord;
153
+
154
+
// Handle record changes with optional comparison
155
+
useEffect(() => {
156
+
if (!currentRecord) return;
157
+
158
+
const hasChanged = compareRecords
159
+
? !compareRecords(previousRecordRef.current, currentRecord)
160
+
: previousRecordRef.current !== currentRecord;
161
+
162
+
if (hasChanged) {
163
+
setStableRecord(currentRecord);
164
+
previousRecordRef.current = currentRecord;
165
+
}
166
+
}, [currentRecord, compareRecords]);
167
+
168
+
const record = stableRecord;
169
+
const isLoading = loading && !providedRecord && !stableRecord;
53
170
54
171
if (error && !record) return <>{fallback}</>;
55
172
if (!record) return <>{isLoading ? loadingIndicator : fallback}</>;
+182
-27
lib/hooks/useAtProtoRecord.ts
+182
-27
lib/hooks/useAtProtoRecord.ts
···
1
-
import { useEffect, useState } from "react";
1
+
import { useEffect, useState, useRef } from "react";
2
2
import { useDidResolution } from "./useDidResolution";
3
3
import { usePdsEndpoint } from "./usePdsEndpoint";
4
4
import { createAtprotoClient } from "../utils/atproto-client";
5
+
import { useBlueskyAppview } from "./useBlueskyAppview";
6
+
import { useAtProto } from "../providers/AtProtoProvider";
5
7
6
8
/**
7
9
* Identifier trio required to address an AT Protocol record.
···
13
15
collection?: string;
14
16
/** Record key string uniquely identifying the record within the collection. */
15
17
rkey?: string;
18
+
/** Force bypass cache and refetch from network. Useful for auto-refresh scenarios. */
19
+
bypassCache?: boolean;
20
+
/** Internal refresh trigger - changes to this value force a refetch. */
21
+
_refreshKey?: number;
16
22
}
17
23
18
24
/**
···
29
35
30
36
/**
31
37
* React hook that fetches a single AT Protocol record and tracks loading/error state.
38
+
*
39
+
* For Bluesky collections (app.bsky.*), uses a three-tier fallback strategy:
40
+
* 1. Try Bluesky appview API first
41
+
* 2. Fall back to Slingshot getRecord
42
+
* 3. Finally query the PDS directly
43
+
*
44
+
* For other collections, queries the PDS directly (with Slingshot fallback via the client handler).
32
45
*
33
46
* @param did - DID (or handle before resolution) that owns the record.
34
47
* @param collection - NSID collection from which to fetch the record.
35
48
* @param rkey - Record key identifying the record within the collection.
49
+
* @param bypassCache - Force bypass cache and refetch from network. Useful for auto-refresh scenarios.
50
+
* @param _refreshKey - Internal parameter used to trigger refetches.
36
51
* @returns {AtProtoRecordState<T>} Object containing the resolved record, any error, and a loading flag.
37
52
*/
38
53
export function useAtProtoRecord<T = unknown>({
39
54
did: handleOrDid,
40
55
collection,
41
56
rkey,
57
+
bypassCache = false,
58
+
_refreshKey = 0,
42
59
}: AtProtoRecordKey): AtProtoRecordState<T> {
60
+
const { recordCache } = useAtProto();
61
+
const isBlueskyCollection = collection?.startsWith("app.bsky.");
62
+
63
+
// Always call all hooks (React rules) - conditionally use results
64
+
const blueskyResult = useBlueskyAppview<T>({
65
+
did: isBlueskyCollection ? handleOrDid : undefined,
66
+
collection: isBlueskyCollection ? collection : undefined,
67
+
rkey: isBlueskyCollection ? rkey : undefined,
68
+
});
69
+
43
70
const {
44
71
did,
45
72
error: didError,
···
53
80
const [state, setState] = useState<AtProtoRecordState<T>>({
54
81
loading: !!(handleOrDid && collection && rkey),
55
82
});
83
+
84
+
const releaseRef = useRef<(() => void) | undefined>(undefined);
56
85
57
86
useEffect(() => {
58
87
let cancelled = false;
···
70
99
});
71
100
return () => {
72
101
cancelled = true;
102
+
if (releaseRef.current) {
103
+
releaseRef.current();
104
+
releaseRef.current = undefined;
105
+
}
73
106
};
74
107
}
75
108
···
77
110
assignState({ loading: false, error: didError });
78
111
return () => {
79
112
cancelled = true;
113
+
if (releaseRef.current) {
114
+
releaseRef.current();
115
+
releaseRef.current = undefined;
116
+
}
80
117
};
81
118
}
82
119
···
84
121
assignState({ loading: false, error: endpointError });
85
122
return () => {
86
123
cancelled = true;
124
+
if (releaseRef.current) {
125
+
releaseRef.current();
126
+
releaseRef.current = undefined;
127
+
}
87
128
};
88
129
}
89
130
···
91
132
assignState({ loading: true, error: undefined });
92
133
return () => {
93
134
cancelled = true;
135
+
if (releaseRef.current) {
136
+
releaseRef.current();
137
+
releaseRef.current = undefined;
138
+
}
94
139
};
95
140
}
96
141
97
142
assignState({ loading: true, error: undefined, record: undefined });
98
143
99
-
(async () => {
100
-
try {
101
-
const { rpc } = await createAtprotoClient({
102
-
service: endpoint,
144
+
// Bypass cache if requested (for auto-refresh scenarios)
145
+
if (bypassCache) {
146
+
assignState({ loading: true, error: undefined });
147
+
148
+
// Skip cache and fetch directly
149
+
const controller = new AbortController();
150
+
151
+
const fetchPromise = (async () => {
152
+
try {
153
+
const { rpc } = await createAtprotoClient({
154
+
service: endpoint,
155
+
});
156
+
const res = await (
157
+
rpc as unknown as {
158
+
get: (
159
+
nsid: string,
160
+
opts: {
161
+
params: {
162
+
repo: string;
163
+
collection: string;
164
+
rkey: string;
165
+
};
166
+
},
167
+
) => Promise<{ ok: boolean; data: { value: T } }>;
168
+
}
169
+
).get("com.atproto.repo.getRecord", {
170
+
params: { repo: did, collection, rkey },
171
+
});
172
+
if (!res.ok) throw new Error("Failed to load record");
173
+
return (res.data as { value: T }).value;
174
+
} catch (err) {
175
+
// Provide helpful error for banned/unreachable Bluesky PDSes
176
+
if (endpoint.includes('.bsky.network')) {
177
+
throw new Error(
178
+
`Record unavailable. The Bluesky PDS (${endpoint}) may be unreachable or the account may be banned.`
179
+
);
180
+
}
181
+
throw err;
182
+
}
183
+
})();
184
+
185
+
fetchPromise
186
+
.then((record) => {
187
+
if (!cancelled) {
188
+
assignState({ record, loading: false });
189
+
}
190
+
})
191
+
.catch((e) => {
192
+
if (!cancelled) {
193
+
const err = e instanceof Error ? e : new Error(String(e));
194
+
assignState({ error: err, loading: false });
195
+
}
103
196
});
104
-
const res = await (
105
-
rpc as unknown as {
106
-
get: (
107
-
nsid: string,
108
-
opts: {
109
-
params: {
110
-
repo: string;
111
-
collection: string;
112
-
rkey: string;
113
-
};
114
-
},
115
-
) => Promise<{ ok: boolean; data: { value: T } }>;
197
+
198
+
return () => {
199
+
cancelled = true;
200
+
controller.abort();
201
+
};
202
+
}
203
+
204
+
// Use recordCache.ensure for deduplication and caching
205
+
const { promise, release } = recordCache.ensure<T>(
206
+
did,
207
+
collection,
208
+
rkey,
209
+
() => {
210
+
const controller = new AbortController();
211
+
212
+
const fetchPromise = (async () => {
213
+
try {
214
+
const { rpc } = await createAtprotoClient({
215
+
service: endpoint,
216
+
});
217
+
const res = await (
218
+
rpc as unknown as {
219
+
get: (
220
+
nsid: string,
221
+
opts: {
222
+
params: {
223
+
repo: string;
224
+
collection: string;
225
+
rkey: string;
226
+
};
227
+
},
228
+
) => Promise<{ ok: boolean; data: { value: T } }>;
229
+
}
230
+
).get("com.atproto.repo.getRecord", {
231
+
params: { repo: did, collection, rkey },
232
+
});
233
+
if (!res.ok) throw new Error("Failed to load record");
234
+
return (res.data as { value: T }).value;
235
+
} catch (err) {
236
+
// Provide helpful error for banned/unreachable Bluesky PDSes
237
+
if (endpoint.includes('.bsky.network')) {
238
+
throw new Error(
239
+
`Record unavailable. The Bluesky PDS (${endpoint}) may be unreachable or the account may be banned.`
240
+
);
241
+
}
242
+
throw err;
116
243
}
117
-
).get("com.atproto.repo.getRecord", {
118
-
params: { repo: did, collection, rkey },
119
-
});
120
-
if (!res.ok) throw new Error("Failed to load record");
121
-
const record = (res.data as { value: T }).value;
122
-
assignState({ record, loading: false });
123
-
} catch (e) {
124
-
const err = e instanceof Error ? e : new Error(String(e));
125
-
assignState({ error: err, loading: false });
244
+
})();
245
+
246
+
return {
247
+
promise: fetchPromise,
248
+
abort: () => controller.abort(),
249
+
};
126
250
}
127
-
})();
251
+
);
252
+
253
+
releaseRef.current = release;
254
+
255
+
promise
256
+
.then((record) => {
257
+
if (!cancelled) {
258
+
assignState({ record, loading: false });
259
+
}
260
+
})
261
+
.catch((e) => {
262
+
if (!cancelled) {
263
+
const err = e instanceof Error ? e : new Error(String(e));
264
+
assignState({ error: err, loading: false });
265
+
}
266
+
});
128
267
129
268
return () => {
130
269
cancelled = true;
270
+
if (releaseRef.current) {
271
+
releaseRef.current();
272
+
releaseRef.current = undefined;
273
+
}
131
274
};
132
275
}, [
133
276
handleOrDid,
···
139
282
resolvingEndpoint,
140
283
didError,
141
284
endpointError,
285
+
recordCache,
286
+
bypassCache,
287
+
_refreshKey,
142
288
]);
289
+
290
+
// Return Bluesky result for app.bsky.* collections
291
+
if (isBlueskyCollection) {
292
+
return {
293
+
record: blueskyResult.record,
294
+
error: blueskyResult.error,
295
+
loading: blueskyResult.loading,
296
+
};
297
+
}
143
298
144
299
return state;
145
300
}
+163
lib/hooks/useBacklinks.ts
+163
lib/hooks/useBacklinks.ts
···
1
+
import { useEffect, useState, useCallback, useRef } from "react";
2
+
3
+
/**
4
+
* Individual backlink record returned by Microcosm Constellation.
5
+
*/
6
+
export interface BacklinkRecord {
7
+
/** DID of the author who created the backlink. */
8
+
did: string;
9
+
/** Collection type of the backlink record (e.g., "sh.tangled.feed.star"). */
10
+
collection: string;
11
+
/** Record key of the backlink. */
12
+
rkey: string;
13
+
}
14
+
15
+
/**
16
+
* Response from Microcosm Constellation API.
17
+
*/
18
+
export interface BacklinksResponse {
19
+
/** Total count of backlinks. */
20
+
total: number;
21
+
/** Array of backlink records. */
22
+
records: BacklinkRecord[];
23
+
/** Cursor for pagination (optional). */
24
+
cursor?: string;
25
+
}
26
+
27
+
/**
28
+
* Parameters for fetching backlinks.
29
+
*/
30
+
export interface UseBacklinksParams {
31
+
/** The AT-URI subject to get backlinks for (e.g., "at://did:plc:xxx/sh.tangled.repo/yyy"). */
32
+
subject: string;
33
+
/** The source collection and path (e.g., "sh.tangled.feed.star:subject"). */
34
+
source: string;
35
+
/** Maximum number of results to fetch (default: 16, max: 100). */
36
+
limit?: number;
37
+
/** Base URL for the Microcosm Constellation API. */
38
+
constellationBaseUrl?: string;
39
+
/** Whether to automatically fetch backlinks on mount. */
40
+
enabled?: boolean;
41
+
}
42
+
43
+
const DEFAULT_CONSTELLATION = "https://constellation.microcosm.blue";
44
+
45
+
/**
46
+
* Hook to fetch backlinks from Microcosm Constellation API.
47
+
*
48
+
* Backlinks are records that reference another record. For example,
49
+
* `sh.tangled.feed.star` records are backlinks to `sh.tangled.repo` records,
50
+
* representing users who have starred a repository.
51
+
*
52
+
* @param params - Configuration for fetching backlinks
53
+
* @returns Object containing backlinks data, loading state, error, and refetch function
54
+
*
55
+
* @example
56
+
* ```tsx
57
+
* const { backlinks, loading, error, count } = useBacklinks({
58
+
* subject: "at://did:plc:example/sh.tangled.repo/3k2aexample",
59
+
* source: "sh.tangled.feed.star:subject",
60
+
* });
61
+
* ```
62
+
*/
63
+
export function useBacklinks({
64
+
subject,
65
+
source,
66
+
limit = 16,
67
+
constellationBaseUrl = DEFAULT_CONSTELLATION,
68
+
enabled = true,
69
+
}: UseBacklinksParams) {
70
+
const [backlinks, setBacklinks] = useState<BacklinkRecord[]>([]);
71
+
const [total, setTotal] = useState(0);
72
+
const [loading, setLoading] = useState(false);
73
+
const [error, setError] = useState<Error | undefined>(undefined);
74
+
const [cursor, setCursor] = useState<string | undefined>(undefined);
75
+
const abortControllerRef = useRef<AbortController | null>(null);
76
+
77
+
const fetchBacklinks = useCallback(
78
+
async (signal?: AbortSignal) => {
79
+
if (!subject || !source || !enabled) return;
80
+
81
+
try {
82
+
setLoading(true);
83
+
setError(undefined);
84
+
85
+
const baseUrl = constellationBaseUrl.endsWith("/")
86
+
? constellationBaseUrl.slice(0, -1)
87
+
: constellationBaseUrl;
88
+
89
+
const params = new URLSearchParams({
90
+
subject: subject,
91
+
source: source,
92
+
limit: limit.toString(),
93
+
});
94
+
95
+
const url = `${baseUrl}/xrpc/blue.microcosm.links.getBacklinks?${params}`;
96
+
97
+
const response = await fetch(url, { signal });
98
+
99
+
if (!response.ok) {
100
+
throw new Error(
101
+
`Failed to fetch backlinks: ${response.status} ${response.statusText}`,
102
+
);
103
+
}
104
+
105
+
const data: BacklinksResponse = await response.json();
106
+
setBacklinks(data.records || []);
107
+
setTotal(data.total || 0);
108
+
setCursor(data.cursor);
109
+
} catch (err) {
110
+
if (err instanceof Error && err.name === "AbortError") {
111
+
// Ignore abort errors
112
+
return;
113
+
}
114
+
setError(
115
+
err instanceof Error ? err : new Error("Unknown error fetching backlinks"),
116
+
);
117
+
} finally {
118
+
setLoading(false);
119
+
}
120
+
},
121
+
[subject, source, limit, constellationBaseUrl, enabled],
122
+
);
123
+
124
+
const refetch = useCallback(() => {
125
+
// Abort any in-flight request
126
+
if (abortControllerRef.current) {
127
+
abortControllerRef.current.abort();
128
+
}
129
+
130
+
const controller = new AbortController();
131
+
abortControllerRef.current = controller;
132
+
fetchBacklinks(controller.signal);
133
+
}, [fetchBacklinks]);
134
+
135
+
useEffect(() => {
136
+
if (!enabled) return;
137
+
138
+
const controller = new AbortController();
139
+
abortControllerRef.current = controller;
140
+
fetchBacklinks(controller.signal);
141
+
142
+
return () => {
143
+
controller.abort();
144
+
};
145
+
}, [fetchBacklinks, enabled]);
146
+
147
+
return {
148
+
/** Array of backlink records. */
149
+
backlinks,
150
+
/** Whether backlinks are currently being fetched. */
151
+
loading,
152
+
/** Error if fetch failed. */
153
+
error,
154
+
/** Pagination cursor (not yet implemented for pagination). */
155
+
cursor,
156
+
/** Total count of backlinks from the API. */
157
+
total,
158
+
/** Total count of backlinks (alias for total). */
159
+
count: total,
160
+
/** Function to manually refetch backlinks. */
161
+
refetch,
162
+
};
163
+
}
+727
lib/hooks/useBlueskyAppview.ts
+727
lib/hooks/useBlueskyAppview.ts
···
1
+
import { useEffect, useReducer, useRef } from "react";
2
+
import { useDidResolution } from "./useDidResolution";
3
+
import { usePdsEndpoint } from "./usePdsEndpoint";
4
+
import { createAtprotoClient } from "../utils/atproto-client";
5
+
import { useAtProto } from "../providers/AtProtoProvider";
6
+
7
+
/**
8
+
* Extended blob reference that includes CDN URL from appview responses.
9
+
*/
10
+
export interface BlobWithCdn {
11
+
$type: "blob";
12
+
ref: { $link: string };
13
+
mimeType: string;
14
+
size: number;
15
+
/** CDN URL from Bluesky appview (e.g., https://cdn.bsky.app/img/avatar/plain/did:plc:xxx/bafkreixxx@jpeg) */
16
+
cdnUrl?: string;
17
+
}
18
+
19
+
20
+
21
+
/**
22
+
* Appview getProfile response structure.
23
+
*/
24
+
interface AppviewProfileResponse {
25
+
did: string;
26
+
handle: string;
27
+
displayName?: string;
28
+
description?: string;
29
+
avatar?: string;
30
+
banner?: string;
31
+
createdAt?: string;
32
+
pronouns?: string;
33
+
website?: string;
34
+
[key: string]: unknown;
35
+
}
36
+
37
+
/**
38
+
* Appview getPostThread response structure.
39
+
*/
40
+
interface AppviewPostThreadResponse<T = unknown> {
41
+
thread?: {
42
+
post?: {
43
+
record?: T;
44
+
embed?: {
45
+
$type?: string;
46
+
images?: Array<{
47
+
thumb?: string;
48
+
fullsize?: string;
49
+
alt?: string;
50
+
aspectRatio?: { width: number; height: number };
51
+
}>;
52
+
media?: {
53
+
images?: Array<{
54
+
thumb?: string;
55
+
fullsize?: string;
56
+
alt?: string;
57
+
aspectRatio?: { width: number; height: number };
58
+
}>;
59
+
};
60
+
};
61
+
};
62
+
};
63
+
}
64
+
65
+
/**
66
+
* Options for {@link useBlueskyAppview}.
67
+
*/
68
+
export interface UseBlueskyAppviewOptions {
69
+
/** DID or handle of the actor. */
70
+
did?: string;
71
+
/** NSID collection (e.g., "app.bsky.feed.post"). */
72
+
collection?: string;
73
+
/** Record key within the collection. */
74
+
rkey?: string;
75
+
/** Override for the Bluesky appview service URL. Defaults to public.api.bsky.app. */
76
+
appviewService?: string;
77
+
/** If true, skip the appview and go straight to Slingshot/PDS fallback. */
78
+
skipAppview?: boolean;
79
+
}
80
+
81
+
/**
82
+
* Result returned from {@link useBlueskyAppview}.
83
+
*/
84
+
export interface UseBlueskyAppviewResult<T = unknown> {
85
+
/** The fetched record value. */
86
+
record?: T;
87
+
/** Indicates whether a fetch is in progress. */
88
+
loading: boolean;
89
+
/** Error encountered during fetch. */
90
+
error?: Error;
91
+
/** Source from which the record was successfully fetched. */
92
+
source?: "appview" | "slingshot" | "pds";
93
+
}
94
+
95
+
/**
96
+
* Maps Bluesky collection NSIDs to their corresponding appview API endpoints.
97
+
* Only includes endpoints that can fetch individual records (not list endpoints).
98
+
*/
99
+
const BLUESKY_COLLECTION_TO_ENDPOINT: Record<string, string> = {
100
+
"app.bsky.actor.profile": "app.bsky.actor.getProfile",
101
+
"app.bsky.feed.post": "app.bsky.feed.getPostThread",
102
+
103
+
};
104
+
105
+
/**
106
+
* React hook that fetches a Bluesky record with a three-tier fallback strategy:
107
+
* 1. Try the Bluesky appview API endpoint (e.g., getProfile, getPostThread)
108
+
* 2. Fall back to Slingshot's getRecord
109
+
* 3. As a last resort, query the actor's PDS directly
110
+
*
111
+
* The hook automatically handles DID resolution and determines the appropriate API endpoint
112
+
* based on the collection type. The `source` field in the result indicates which tier
113
+
* successfully returned the record.
114
+
*
115
+
* @example
116
+
* ```tsx
117
+
* // Fetch a Bluesky post with automatic fallback
118
+
* import { useBlueskyAppview } from 'atproto-ui';
119
+
* import type { FeedPostRecord } from 'atproto-ui';
120
+
*
121
+
* function MyPost({ did, rkey }: { did: string; rkey: string }) {
122
+
* const { record, loading, error, source } = useBlueskyAppview<FeedPostRecord>({
123
+
* did,
124
+
* collection: 'app.bsky.feed.post',
125
+
* rkey,
126
+
* });
127
+
*
128
+
* if (loading) return <p>Loading post...</p>;
129
+
* if (error) return <p>Error: {error.message}</p>;
130
+
* if (!record) return <p>No post found</p>;
131
+
*
132
+
* return (
133
+
* <article>
134
+
* <p>{record.text}</p>
135
+
* <small>Fetched from: {source}</small>
136
+
* </article>
137
+
* );
138
+
* }
139
+
* ```
140
+
*
141
+
* @example
142
+
* ```tsx
143
+
* // Fetch a Bluesky profile
144
+
* import { useBlueskyAppview } from 'atproto-ui';
145
+
* import type { ProfileRecord } from 'atproto-ui';
146
+
*
147
+
* function MyProfile({ handle }: { handle: string }) {
148
+
* const { record, loading, error } = useBlueskyAppview<ProfileRecord>({
149
+
* did: handle, // Handles are automatically resolved to DIDs
150
+
* collection: 'app.bsky.actor.profile',
151
+
* rkey: 'self',
152
+
* });
153
+
*
154
+
* if (loading) return <p>Loading profile...</p>;
155
+
* if (!record) return null;
156
+
*
157
+
* return (
158
+
* <div>
159
+
* <h2>{record.displayName}</h2>
160
+
* <p>{record.description}</p>
161
+
* </div>
162
+
* );
163
+
* }
164
+
* ```
165
+
*
166
+
* @example
167
+
* ```tsx
168
+
* // Skip the appview and go directly to Slingshot/PDS
169
+
* const { record } = useBlueskyAppview({
170
+
* did: 'did:plc:example',
171
+
* collection: 'app.bsky.feed.post',
172
+
* rkey: '3k2aexample',
173
+
* skipAppview: true, // Bypasses Bluesky API, starts with Slingshot
174
+
* });
175
+
* ```
176
+
*
177
+
* @param options - Configuration object with did, collection, rkey, and optional overrides.
178
+
* @returns {UseBlueskyAppviewResult<T>} Object containing the record, loading state, error, and source.
179
+
*/
180
+
181
+
// Reducer action types for useBlueskyAppview
182
+
type BlueskyAppviewAction<T> =
183
+
| { type: "SET_LOADING"; loading: boolean }
184
+
| { type: "SET_SUCCESS"; record: T; source: "appview" | "slingshot" | "pds" }
185
+
| { type: "SET_ERROR"; error: Error }
186
+
| { type: "RESET" };
187
+
188
+
// Reducer function for atomic state updates
189
+
function blueskyAppviewReducer<T>(
190
+
state: UseBlueskyAppviewResult<T>,
191
+
action: BlueskyAppviewAction<T>
192
+
): UseBlueskyAppviewResult<T> {
193
+
switch (action.type) {
194
+
case "SET_LOADING":
195
+
return {
196
+
...state,
197
+
loading: action.loading,
198
+
error: undefined,
199
+
};
200
+
case "SET_SUCCESS":
201
+
return {
202
+
record: action.record,
203
+
loading: false,
204
+
error: undefined,
205
+
source: action.source,
206
+
};
207
+
case "SET_ERROR":
208
+
// Only update if error message changed (stabilize error reference)
209
+
if (state.error?.message === action.error.message) {
210
+
return state;
211
+
}
212
+
return {
213
+
...state,
214
+
loading: false,
215
+
error: action.error,
216
+
source: undefined,
217
+
};
218
+
case "RESET":
219
+
return {
220
+
record: undefined,
221
+
loading: false,
222
+
error: undefined,
223
+
source: undefined,
224
+
};
225
+
default:
226
+
return state;
227
+
}
228
+
}
229
+
230
+
export function useBlueskyAppview<T = unknown>({
231
+
did: handleOrDid,
232
+
collection,
233
+
rkey,
234
+
appviewService,
235
+
skipAppview = false,
236
+
}: UseBlueskyAppviewOptions): UseBlueskyAppviewResult<T> {
237
+
const { recordCache, blueskyAppviewService, resolver } = useAtProto();
238
+
const effectiveAppviewService = appviewService ?? blueskyAppviewService;
239
+
240
+
// Only use this hook for Bluesky collections (app.bsky.*)
241
+
const isBlueskyCollection = collection?.startsWith("app.bsky.");
242
+
243
+
const {
244
+
did,
245
+
error: didError,
246
+
loading: resolvingDid,
247
+
} = useDidResolution(handleOrDid);
248
+
const {
249
+
endpoint: pdsEndpoint,
250
+
error: endpointError,
251
+
loading: resolvingEndpoint,
252
+
} = usePdsEndpoint(did);
253
+
254
+
const [state, dispatch] = useReducer(blueskyAppviewReducer<T>, {
255
+
record: undefined,
256
+
loading: false,
257
+
error: undefined,
258
+
source: undefined,
259
+
});
260
+
261
+
const releaseRef = useRef<(() => void) | undefined>(undefined);
262
+
263
+
useEffect(() => {
264
+
let cancelled = false;
265
+
266
+
// Early returns for missing inputs or resolution errors
267
+
if (!handleOrDid || !collection || !rkey) {
268
+
if (!cancelled) dispatch({ type: "RESET" });
269
+
return () => {
270
+
cancelled = true;
271
+
if (releaseRef.current) {
272
+
releaseRef.current();
273
+
releaseRef.current = undefined;
274
+
}
275
+
};
276
+
}
277
+
278
+
// Return early if not a Bluesky collection - this hook should not be used for other lexicons
279
+
if (!isBlueskyCollection) {
280
+
if (!cancelled) dispatch({ type: "RESET" });
281
+
return () => {
282
+
cancelled = true;
283
+
if (releaseRef.current) {
284
+
releaseRef.current();
285
+
releaseRef.current = undefined;
286
+
}
287
+
};
288
+
}
289
+
290
+
if (didError) {
291
+
if (!cancelled) dispatch({ type: "SET_ERROR", error: didError });
292
+
return () => {
293
+
cancelled = true;
294
+
if (releaseRef.current) {
295
+
releaseRef.current();
296
+
releaseRef.current = undefined;
297
+
}
298
+
};
299
+
}
300
+
301
+
if (endpointError) {
302
+
if (!cancelled) dispatch({ type: "SET_ERROR", error: endpointError });
303
+
return () => {
304
+
cancelled = true;
305
+
if (releaseRef.current) {
306
+
releaseRef.current();
307
+
releaseRef.current = undefined;
308
+
}
309
+
};
310
+
}
311
+
312
+
if (resolvingDid || resolvingEndpoint || !did || !pdsEndpoint) {
313
+
if (!cancelled) dispatch({ type: "SET_LOADING", loading: true });
314
+
return () => {
315
+
cancelled = true;
316
+
if (releaseRef.current) {
317
+
releaseRef.current();
318
+
releaseRef.current = undefined;
319
+
}
320
+
};
321
+
}
322
+
323
+
// Start fetching
324
+
dispatch({ type: "SET_LOADING", loading: true });
325
+
326
+
// Use recordCache.ensure for deduplication and caching
327
+
const { promise, release } = recordCache.ensure<{ record: T; source: "appview" | "slingshot" | "pds" }>(
328
+
did,
329
+
collection,
330
+
rkey,
331
+
() => {
332
+
const controller = new AbortController();
333
+
334
+
const fetchPromise = (async (): Promise<{ record: T; source: "appview" | "slingshot" | "pds" }> => {
335
+
let lastError: Error | undefined;
336
+
337
+
// Tier 1: Try Bluesky appview API
338
+
if (!skipAppview && BLUESKY_COLLECTION_TO_ENDPOINT[collection]) {
339
+
try {
340
+
const result = await fetchFromAppview<T>(
341
+
did,
342
+
collection,
343
+
rkey,
344
+
effectiveAppviewService,
345
+
);
346
+
if (result) {
347
+
return { record: result, source: "appview" };
348
+
}
349
+
} catch (err) {
350
+
lastError = err as Error;
351
+
// Continue to next tier
352
+
}
353
+
}
354
+
355
+
// Tier 2: Try Slingshot getRecord
356
+
try {
357
+
const slingshotUrl = resolver.getSlingshotUrl();
358
+
const result = await fetchFromSlingshot<T>(did, collection, rkey, slingshotUrl);
359
+
if (result) {
360
+
return { record: result, source: "slingshot" };
361
+
}
362
+
} catch (err) {
363
+
lastError = err as Error;
364
+
// Continue to next tier
365
+
}
366
+
367
+
// Tier 3: Try PDS directly
368
+
try {
369
+
const result = await fetchFromPds<T>(
370
+
did,
371
+
collection,
372
+
rkey,
373
+
pdsEndpoint,
374
+
);
375
+
if (result) {
376
+
return { record: result, source: "pds" };
377
+
}
378
+
} catch (err) {
379
+
lastError = err as Error;
380
+
}
381
+
382
+
// All tiers failed - provide helpful error for banned/unreachable Bluesky PDSes
383
+
if (pdsEndpoint.includes('.bsky.network')) {
384
+
throw new Error(
385
+
`Record unavailable. The Bluesky PDS (${pdsEndpoint}) may be unreachable or the account may be banned.`
386
+
);
387
+
}
388
+
389
+
throw lastError ?? new Error("Failed to fetch record from all sources");
390
+
})();
391
+
392
+
return {
393
+
promise: fetchPromise,
394
+
abort: () => controller.abort(),
395
+
};
396
+
}
397
+
);
398
+
399
+
releaseRef.current = release;
400
+
401
+
promise
402
+
.then(({ record, source }) => {
403
+
if (!cancelled) {
404
+
dispatch({
405
+
type: "SET_SUCCESS",
406
+
record,
407
+
source,
408
+
});
409
+
}
410
+
})
411
+
.catch((err) => {
412
+
if (!cancelled) {
413
+
dispatch({
414
+
type: "SET_ERROR",
415
+
error: err instanceof Error ? err : new Error(String(err)),
416
+
});
417
+
}
418
+
});
419
+
420
+
return () => {
421
+
cancelled = true;
422
+
if (releaseRef.current) {
423
+
releaseRef.current();
424
+
releaseRef.current = undefined;
425
+
}
426
+
};
427
+
}, [
428
+
handleOrDid,
429
+
did,
430
+
collection,
431
+
rkey,
432
+
pdsEndpoint,
433
+
effectiveAppviewService,
434
+
skipAppview,
435
+
resolvingDid,
436
+
resolvingEndpoint,
437
+
didError,
438
+
endpointError,
439
+
recordCache,
440
+
resolver,
441
+
]);
442
+
443
+
return state;
444
+
}
445
+
446
+
/**
447
+
* Attempts to fetch a record from the Bluesky appview API.
448
+
* Different collections map to different endpoints with varying response structures.
449
+
*/
450
+
async function fetchFromAppview<T>(
451
+
did: string,
452
+
collection: string,
453
+
rkey: string,
454
+
appviewService: string,
455
+
): Promise<T | undefined> {
456
+
const { rpc } = await createAtprotoClient({ service: appviewService });
457
+
const endpoint = BLUESKY_COLLECTION_TO_ENDPOINT[collection];
458
+
459
+
if (!endpoint) {
460
+
throw new Error(`No appview endpoint mapped for collection ${collection}`);
461
+
}
462
+
463
+
const atUri = `at://${did}/${collection}/${rkey}`;
464
+
465
+
// Handle different appview endpoints
466
+
if (endpoint === "app.bsky.actor.getProfile") {
467
+
const res = await (rpc as unknown as { get: (nsid: string, opts: { params: Record<string, unknown> }) => Promise<{ ok: boolean; data: AppviewProfileResponse }> }).get(endpoint, {
468
+
params: { actor: did },
469
+
});
470
+
471
+
if (!res.ok) throw new Error(`Appview ${endpoint} request failed for ${did}`);
472
+
473
+
// The appview returns avatar/banner as CDN URLs like:
474
+
// https://cdn.bsky.app/img/avatar/plain/{did}/{cid}@jpeg
475
+
// We need to extract the CID and convert to ProfileRecord format
476
+
const profile = res.data;
477
+
const avatarCid = extractCidFromCdnUrl(profile.avatar);
478
+
const bannerCid = extractCidFromCdnUrl(profile.banner);
479
+
480
+
// Convert hydrated profile to ProfileRecord format
481
+
// Store the CDN URL directly so components can use it without re-fetching
482
+
const record: Record<string, unknown> = {
483
+
displayName: profile.displayName,
484
+
description: profile.description,
485
+
createdAt: profile.createdAt,
486
+
};
487
+
488
+
// Add pronouns and website if they exist
489
+
if (profile.pronouns) {
490
+
record.pronouns = profile.pronouns;
491
+
}
492
+
493
+
if (profile.website) {
494
+
record.website = profile.website;
495
+
}
496
+
497
+
if (profile.avatar && avatarCid) {
498
+
const avatarBlob: BlobWithCdn = {
499
+
$type: "blob",
500
+
ref: { $link: avatarCid },
501
+
mimeType: "image/jpeg",
502
+
size: 0,
503
+
cdnUrl: profile.avatar,
504
+
};
505
+
record.avatar = avatarBlob;
506
+
}
507
+
508
+
if (profile.banner && bannerCid) {
509
+
const bannerBlob: BlobWithCdn = {
510
+
$type: "blob",
511
+
ref: { $link: bannerCid },
512
+
mimeType: "image/jpeg",
513
+
size: 0,
514
+
cdnUrl: profile.banner,
515
+
};
516
+
record.banner = bannerBlob;
517
+
}
518
+
519
+
return record as T;
520
+
}
521
+
522
+
if (endpoint === "app.bsky.feed.getPostThread") {
523
+
const res = await (rpc as unknown as { get: (nsid: string, opts: { params: Record<string, unknown> }) => Promise<{ ok: boolean; data: AppviewPostThreadResponse<T> }> }).get(endpoint, {
524
+
params: { uri: atUri, depth: 0 },
525
+
});
526
+
527
+
if (!res.ok) throw new Error(`Appview ${endpoint} request failed for ${atUri}`);
528
+
529
+
const post = res.data.thread?.post;
530
+
if (!post?.record) return undefined;
531
+
532
+
const record = post.record as Record<string, unknown>;
533
+
const appviewEmbed = post.embed;
534
+
535
+
// If the appview includes embedded images with CDN URLs, inject them into the record
536
+
if (appviewEmbed && record.embed) {
537
+
const recordEmbed = record.embed as { $type?: string; images?: Array<Record<string, unknown>>; media?: Record<string, unknown> };
538
+
539
+
// Handle direct image embeds
540
+
if (appviewEmbed.$type === "app.bsky.embed.images#view" && appviewEmbed.images) {
541
+
if (recordEmbed.images && Array.isArray(recordEmbed.images)) {
542
+
recordEmbed.images = recordEmbed.images.map((img: Record<string, unknown>, idx: number) => {
543
+
const appviewImg = appviewEmbed.images?.[idx];
544
+
if (appviewImg?.fullsize) {
545
+
const cid = extractCidFromCdnUrl(appviewImg.fullsize);
546
+
const imageObj = img.image as { ref?: { $link?: string } } | undefined;
547
+
return {
548
+
...img,
549
+
image: {
550
+
...(img.image as Record<string, unknown> || {}),
551
+
cdnUrl: appviewImg.fullsize,
552
+
ref: { $link: cid || imageObj?.ref?.$link },
553
+
},
554
+
};
555
+
}
556
+
return img;
557
+
});
558
+
}
559
+
}
560
+
561
+
// Handle recordWithMedia embeds
562
+
if (appviewEmbed.$type === "app.bsky.embed.recordWithMedia#view" && appviewEmbed.media) {
563
+
const mediaImages = appviewEmbed.media.images;
564
+
const mediaEmbedImages = (recordEmbed.media as { images?: Array<Record<string, unknown>> } | undefined)?.images;
565
+
if (mediaImages && mediaEmbedImages && Array.isArray(mediaEmbedImages)) {
566
+
(recordEmbed.media as { images: Array<Record<string, unknown>> }).images = mediaEmbedImages.map((img: Record<string, unknown>, idx: number) => {
567
+
const appviewImg = mediaImages[idx];
568
+
if (appviewImg?.fullsize) {
569
+
const cid = extractCidFromCdnUrl(appviewImg.fullsize);
570
+
const imageObj = img.image as { ref?: { $link?: string } } | undefined;
571
+
return {
572
+
...img,
573
+
image: {
574
+
...(img.image as Record<string, unknown> || {}),
575
+
cdnUrl: appviewImg.fullsize,
576
+
ref: { $link: cid || imageObj?.ref?.$link },
577
+
},
578
+
};
579
+
}
580
+
return img;
581
+
});
582
+
}
583
+
}
584
+
}
585
+
586
+
return record as T;
587
+
}
588
+
589
+
// For other endpoints, we might not have a clean way to extract the specific record
590
+
// Fall through to let the caller try the next tier
591
+
throw new Error(`Appview endpoint ${endpoint} not fully implemented`);
592
+
}
593
+
594
+
/**
595
+
* Attempts to fetch a record from Slingshot's getRecord endpoint.
596
+
*/
597
+
async function fetchFromSlingshot<T>(
598
+
did: string,
599
+
collection: string,
600
+
rkey: string,
601
+
slingshotBaseUrl: string,
602
+
): Promise<T | undefined> {
603
+
const res = await callGetRecord<T>(slingshotBaseUrl, did, collection, rkey);
604
+
if (!res.ok) throw new Error(`Slingshot getRecord failed for ${did}/${collection}/${rkey}`);
605
+
return res.data.value;
606
+
}
607
+
608
+
/**
609
+
* Attempts to fetch a record directly from the actor's PDS.
610
+
*/
611
+
async function fetchFromPds<T>(
612
+
did: string,
613
+
collection: string,
614
+
rkey: string,
615
+
pdsEndpoint: string,
616
+
): Promise<T | undefined> {
617
+
const res = await callGetRecord<T>(pdsEndpoint, did, collection, rkey);
618
+
if (!res.ok) throw new Error(`PDS getRecord failed for ${did}/${collection}/${rkey} at ${pdsEndpoint}`);
619
+
return res.data.value;
620
+
}
621
+
622
+
/**
623
+
* Extracts and validates CID from Bluesky CDN URL.
624
+
* Format: https://cdn.bsky.app/img/{type}/plain/{did}/{cid}@{format}
625
+
*
626
+
* @throws Error if URL format is invalid or CID extraction fails
627
+
*/
628
+
function extractCidFromCdnUrl(url: string | undefined): string | undefined {
629
+
if (!url) return undefined;
630
+
631
+
try {
632
+
// Match pattern: /did:plc:xxxxx/CIDHERE@format or /did:web:xxxxx/CIDHERE@format
633
+
const match = url.match(/\/did:[^/]+\/([^@/]+)@/);
634
+
const cid = match?.[1];
635
+
636
+
if (!cid) {
637
+
console.warn(`Failed to extract CID from CDN URL: ${url}`);
638
+
return undefined;
639
+
}
640
+
641
+
// Basic CID validation - should start with common CID prefixes
642
+
if (!cid.startsWith("bafk") && !cid.startsWith("bafyb") && !cid.startsWith("Qm")) {
643
+
console.warn(`Extracted string does not appear to be a valid CID: ${cid} from URL: ${url}`);
644
+
return undefined;
645
+
}
646
+
647
+
return cid;
648
+
} catch (err) {
649
+
console.error(`Error extracting CID from CDN URL: ${url}`, err);
650
+
return undefined;
651
+
}
652
+
}
653
+
654
+
/**
655
+
* Shared RPC utility for making appview API calls with proper typing.
656
+
*/
657
+
export async function callAppviewRpc<TResponse>(
658
+
service: string,
659
+
nsid: string,
660
+
params: Record<string, unknown>,
661
+
): Promise<{ ok: boolean; data: TResponse }> {
662
+
const { rpc } = await createAtprotoClient({ service });
663
+
return await (rpc as unknown as {
664
+
get: (nsid: string, opts: { params: Record<string, unknown> }) => Promise<{ ok: boolean; data: TResponse }>;
665
+
}).get(nsid, { params });
666
+
}
667
+
668
+
/**
669
+
* Shared RPC utility for making getRecord calls (Slingshot or PDS).
670
+
*/
671
+
export async function callGetRecord<T>(
672
+
service: string,
673
+
did: string,
674
+
collection: string,
675
+
rkey: string,
676
+
): Promise<{ ok: boolean; data: { value: T } }> {
677
+
const { rpc } = await createAtprotoClient({ service });
678
+
return await (rpc as unknown as {
679
+
get: (nsid: string, opts: { params: Record<string, unknown> }) => Promise<{ ok: boolean; data: { value: T } }>;
680
+
}).get("com.atproto.repo.getRecord", {
681
+
params: { repo: did, collection, rkey },
682
+
});
683
+
}
684
+
685
+
/**
686
+
* Shared RPC utility for making listRecords calls.
687
+
*/
688
+
export async function callListRecords<T>(
689
+
service: string,
690
+
did: string,
691
+
collection: string,
692
+
limit: number,
693
+
cursor?: string,
694
+
): Promise<{
695
+
ok: boolean;
696
+
data: {
697
+
records: Array<{ uri: string; rkey?: string; value: T }>;
698
+
cursor?: string;
699
+
};
700
+
}> {
701
+
const { rpc } = await createAtprotoClient({ service });
702
+
703
+
const params: Record<string, unknown> = {
704
+
repo: did,
705
+
collection,
706
+
limit,
707
+
cursor,
708
+
reverse: false,
709
+
};
710
+
711
+
return await (rpc as unknown as {
712
+
get: (
713
+
nsid: string,
714
+
opts: { params: Record<string, unknown> },
715
+
) => Promise<{
716
+
ok: boolean;
717
+
data: {
718
+
records: Array<{ uri: string; rkey?: string; value: T }>;
719
+
cursor?: string;
720
+
};
721
+
}>;
722
+
}).get("com.atproto.repo.listRecords", {
723
+
params,
724
+
});
725
+
}
726
+
727
+
+30
-38
lib/hooks/useBlueskyProfile.ts
+30
-38
lib/hooks/useBlueskyProfile.ts
···
1
-
import { useEffect, useState } from "react";
2
-
import { usePdsEndpoint } from "./usePdsEndpoint";
3
-
import { createAtprotoClient } from "../utils/atproto-client";
1
+
import { useBlueskyAppview } from "./useBlueskyAppview";
2
+
import type { ProfileRecord } from "../types/bluesky";
3
+
import { extractCidFromBlob } from "../utils/blob";
4
4
5
5
/**
6
6
* Minimal profile fields returned by the Bluesky actor profile endpoint.
···
24
24
25
25
/**
26
26
* Fetches a Bluesky actor profile for a DID and exposes loading/error state.
27
+
*
28
+
* Uses a three-tier fallback strategy:
29
+
* 1. Try Bluesky appview API (app.bsky.actor.getProfile) - CIDs are extracted from CDN URLs
30
+
* 2. Fall back to Slingshot getRecord
31
+
* 3. Finally query the PDS directly
32
+
*
33
+
* When using the appview, avatar/banner CDN URLs (e.g., https://cdn.bsky.app/img/avatar/plain/did:plc:xxx/bafkreixxx@jpeg)
34
+
* are automatically parsed to extract CIDs and convert them to standard Blob format for compatibility.
27
35
*
28
36
* @param did - Actor DID whose profile should be retrieved.
29
37
* @returns {{ data: BlueskyProfileData | undefined; loading: boolean; error: Error | undefined }} Object exposing the profile payload, loading flag, and any error.
30
38
*/
31
39
export function useBlueskyProfile(did: string | undefined) {
32
-
const { endpoint } = usePdsEndpoint(did);
33
-
const [data, setData] = useState<BlueskyProfileData | undefined>();
34
-
const [loading, setLoading] = useState<boolean>(!!did);
35
-
const [error, setError] = useState<Error | undefined>();
40
+
const { record, loading, error } = useBlueskyAppview<ProfileRecord>({
41
+
did,
42
+
collection: "app.bsky.actor.profile",
43
+
rkey: "self",
44
+
});
36
45
37
-
useEffect(() => {
38
-
let cancelled = false;
39
-
async function run() {
40
-
if (!did || !endpoint) return;
41
-
setLoading(true);
42
-
try {
43
-
const { rpc } = await createAtprotoClient({
44
-
service: endpoint,
45
-
});
46
-
const client = rpc as unknown as {
47
-
get: (
48
-
nsid: string,
49
-
options: { params: { actor: string } },
50
-
) => Promise<{ ok: boolean; data: unknown }>;
51
-
};
52
-
const res = await client.get("app.bsky.actor.getProfile", {
53
-
params: { actor: did },
54
-
});
55
-
if (!res.ok) throw new Error("Profile request failed");
56
-
if (!cancelled) setData(res.data as BlueskyProfileData);
57
-
} catch (e) {
58
-
if (!cancelled) setError(e as Error);
59
-
} finally {
60
-
if (!cancelled) setLoading(false);
61
-
}
46
+
// Convert ProfileRecord to BlueskyProfileData
47
+
// Note: avatar and banner are Blob objects in the record (from all sources)
48
+
// The appview response is converted to ProfileRecord format by extracting CIDs from CDN URLs
49
+
const data: BlueskyProfileData | undefined = record
50
+
? {
51
+
did: did || "",
52
+
handle: "",
53
+
displayName: record.displayName,
54
+
description: record.description,
55
+
avatar: extractCidFromBlob(record.avatar),
56
+
banner: extractCidFromBlob(record.banner),
57
+
createdAt: record.createdAt,
62
58
}
63
-
run();
64
-
return () => {
65
-
cancelled = true;
66
-
};
67
-
}, [did, endpoint]);
59
+
: undefined;
68
60
69
61
return { data, loading, error };
70
-
}
62
+
}
-66
lib/hooks/useColorScheme.ts
-66
lib/hooks/useColorScheme.ts
···
1
-
import { useEffect, useState } from "react";
2
-
3
-
/**
4
-
* Possible user-facing color scheme preferences.
5
-
*/
6
-
export type ColorSchemePreference = "light" | "dark" | "system";
7
-
8
-
const MEDIA_QUERY = "(prefers-color-scheme: dark)";
9
-
10
-
/**
11
-
* Resolves a persisted preference into an explicit light/dark value.
12
-
*
13
-
* @param pref - Stored preference value (`light`, `dark`, or `system`).
14
-
* @returns Explicit light/dark scheme suitable for rendering.
15
-
*/
16
-
function resolveScheme(pref: ColorSchemePreference): "light" | "dark" {
17
-
if (pref === "light" || pref === "dark") return pref;
18
-
if (
19
-
typeof window === "undefined" ||
20
-
typeof window.matchMedia !== "function"
21
-
) {
22
-
return "light";
23
-
}
24
-
return window.matchMedia(MEDIA_QUERY).matches ? "dark" : "light";
25
-
}
26
-
27
-
/**
28
-
* React hook that returns the effective light/dark scheme, respecting system preferences.
29
-
*
30
-
* @param preference - User preference; defaults to following the OS setting.
31
-
* @returns {'light' | 'dark'} Explicit scheme that should be used for rendering.
32
-
*/
33
-
export function useColorScheme(
34
-
preference: ColorSchemePreference = "system",
35
-
): "light" | "dark" {
36
-
const [scheme, setScheme] = useState<"light" | "dark">(() =>
37
-
resolveScheme(preference),
38
-
);
39
-
40
-
useEffect(() => {
41
-
if (preference === "light" || preference === "dark") {
42
-
setScheme(preference);
43
-
return;
44
-
}
45
-
if (
46
-
typeof window === "undefined" ||
47
-
typeof window.matchMedia !== "function"
48
-
) {
49
-
setScheme("light");
50
-
return;
51
-
}
52
-
const media = window.matchMedia(MEDIA_QUERY);
53
-
const update = (event: MediaQueryListEvent | MediaQueryList) => {
54
-
setScheme(event.matches ? "dark" : "light");
55
-
};
56
-
update(media);
57
-
if (typeof media.addEventListener === "function") {
58
-
media.addEventListener("change", update);
59
-
return () => media.removeEventListener("change", update);
60
-
}
61
-
media.addListener(update);
62
-
return () => media.removeListener(update);
63
-
}, [preference]);
64
-
65
-
return scheme;
66
-
}
+5
-1
lib/hooks/useDidResolution.ts
+5
-1
lib/hooks/useDidResolution.ts
···
93
93
}
94
94
} catch (e) {
95
95
if (!cancelled) {
96
-
setError(e as Error);
96
+
const newError = e as Error;
97
+
// Only update error if message changed (stabilize reference)
98
+
setError(prevError =>
99
+
prevError?.message === newError.message ? prevError : newError
100
+
);
97
101
}
98
102
} finally {
99
103
if (!cancelled) setLoading(false);
+61
-33
lib/hooks/useLatestRecord.ts
+61
-33
lib/hooks/useLatestRecord.ts
···
1
1
import { useEffect, useState } from "react";
2
2
import { useDidResolution } from "./useDidResolution";
3
3
import { usePdsEndpoint } from "./usePdsEndpoint";
4
-
import { createAtprotoClient } from "../utils/atproto-client";
4
+
import { callListRecords } from "./useBlueskyAppview";
5
5
6
6
/**
7
7
* Shape of the state returned by {@link useLatestRecord}.
···
20
20
}
21
21
22
22
/**
23
-
* Fetches the most recent record from a collection using `listRecords(limit=1)`.
23
+
* Fetches the most recent record from a collection using `listRecords(limit=3)`.
24
+
*
25
+
* Note: Slingshot does not support listRecords, so this always queries the actor's PDS directly.
26
+
*
27
+
* Records with invalid timestamps (before 2023, when ATProto was created) are automatically
28
+
* skipped, and additional records are fetched to find a valid one.
24
29
*
25
30
* @param handleOrDid - Handle or DID that owns the collection.
26
31
* @param collection - NSID of the collection to query.
32
+
* @param refreshKey - Optional key that when changed, triggers a refetch. Use for auto-refresh scenarios.
27
33
* @returns {LatestRecordState<T>} Object reporting the latest record value, derived rkey, loading status, emptiness, and any error.
28
34
*/
29
35
export function useLatestRecord<T = unknown>(
30
36
handleOrDid: string | undefined,
31
37
collection: string,
38
+
refreshKey?: number,
32
39
): LatestRecordState<T> {
33
40
const {
34
41
did,
···
91
98
92
99
(async () => {
93
100
try {
94
-
const { rpc } = await createAtprotoClient({
95
-
service: endpoint,
96
-
});
97
-
const res = await (
98
-
rpc as unknown as {
99
-
get: (
100
-
nsid: string,
101
-
opts: {
102
-
params: Record<
103
-
string,
104
-
string | number | boolean
105
-
>;
106
-
},
107
-
) => Promise<{
108
-
ok: boolean;
109
-
data: {
110
-
records: Array<{
111
-
uri: string;
112
-
rkey?: string;
113
-
value: T;
114
-
}>;
115
-
};
116
-
}>;
117
-
}
118
-
).get("com.atproto.repo.listRecords", {
119
-
params: { repo: did, collection, limit: 1, reverse: false },
120
-
});
121
-
if (!res.ok) throw new Error("Failed to list records");
101
+
// Slingshot doesn't support listRecords, so we query PDS directly
102
+
const res = await callListRecords<T>(
103
+
endpoint,
104
+
did,
105
+
collection,
106
+
3, // Fetch 3 in case some have invalid timestamps
107
+
);
108
+
109
+
if (!res.ok) {
110
+
throw new Error("Failed to list records from PDS");
111
+
}
112
+
122
113
const list = res.data.records;
123
114
if (list.length === 0) {
124
115
assign({
···
129
120
});
130
121
return;
131
122
}
132
-
const first = list[0];
133
-
const derivedRkey = first.rkey ?? extractRkey(first.uri);
123
+
124
+
// Find the first valid record (skip records before 2023)
125
+
const validRecord = list.find((item) => isValidTimestamp(item.value));
126
+
127
+
if (!validRecord) {
128
+
console.warn("No valid records found (all had timestamps before 2023)");
129
+
assign({
130
+
loading: false,
131
+
empty: true,
132
+
record: undefined,
133
+
rkey: undefined,
134
+
});
135
+
return;
136
+
}
137
+
138
+
const derivedRkey = validRecord.rkey ?? extractRkey(validRecord.uri);
134
139
assign({
135
-
record: first.value,
140
+
record: validRecord.value,
136
141
rkey: derivedRkey,
137
142
loading: false,
138
143
empty: false,
···
154
159
resolvingEndpoint,
155
160
didError,
156
161
endpointError,
162
+
refreshKey,
157
163
]);
158
164
159
165
return state;
···
164
170
const parts = uri.split("/");
165
171
return parts[parts.length - 1];
166
172
}
173
+
174
+
/**
175
+
* Validates that a record has a reasonable timestamp (not before 2023).
176
+
* ATProto was created in 2023, so any timestamp before that is invalid.
177
+
*/
178
+
function isValidTimestamp(record: unknown): boolean {
179
+
if (typeof record !== "object" || record === null) return true;
180
+
181
+
const recordObj = record as { createdAt?: string; indexedAt?: string };
182
+
const timestamp = recordObj.createdAt || recordObj.indexedAt;
183
+
184
+
if (!timestamp || typeof timestamp !== "string") return true; // No timestamp to validate
185
+
186
+
try {
187
+
const date = new Date(timestamp);
188
+
// ATProto was created in 2023, reject anything before that
189
+
return date.getFullYear() >= 2023;
190
+
} catch {
191
+
// If we can't parse the date, consider it valid to avoid false negatives
192
+
return true;
193
+
}
194
+
}
+77
-83
lib/hooks/usePaginatedRecords.ts
+77
-83
lib/hooks/usePaginatedRecords.ts
···
1
1
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
2
import { useDidResolution } from "./useDidResolution";
3
3
import { usePdsEndpoint } from "./usePdsEndpoint";
4
-
import { createAtprotoClient } from "../utils/atproto-client";
4
+
import { callAppviewRpc, callListRecords } from "./useBlueskyAppview";
5
+
import { useAtProto } from "../providers/AtProtoProvider";
5
6
6
7
/**
7
8
* Record envelope returned by paginated AT Protocol queries.
···
70
71
pagesCount: number;
71
72
}
72
73
73
-
const DEFAULT_APPVIEW_SERVICE = "https://public.api.bsky.app";
74
+
74
75
75
76
export type AuthorFeedFilter =
76
77
| "posts_with_replies"
···
114
115
authorFeedService,
115
116
authorFeedActor,
116
117
}: UsePaginatedRecordsOptions): UsePaginatedRecordsResult<T> {
118
+
const { blueskyAppviewService } = useAtProto();
117
119
const {
118
120
did,
119
121
handle,
···
188
190
!!actorIdentifier;
189
191
if (shouldUseAuthorFeed) {
190
192
try {
191
-
const { rpc } = await createAtprotoClient({
192
-
service:
193
-
authorFeedService ?? DEFAULT_APPVIEW_SERVICE,
194
-
});
195
-
const res = await (
196
-
rpc as unknown as {
197
-
get: (
198
-
nsid: string,
199
-
opts: {
200
-
params: Record<
201
-
string,
202
-
| string
203
-
| number
204
-
| boolean
205
-
| undefined
206
-
>;
207
-
},
208
-
) => Promise<{
209
-
ok: boolean;
210
-
data: {
211
-
feed?: Array<{
212
-
post?: {
213
-
uri?: string;
214
-
record?: T;
215
-
reply?: {
216
-
parent?: {
217
-
uri?: string;
218
-
author?: {
219
-
handle?: string;
220
-
did?: string;
221
-
};
222
-
};
223
-
};
193
+
interface AuthorFeedResponse {
194
+
feed?: Array<{
195
+
post?: {
196
+
uri?: string;
197
+
record?: T;
198
+
reply?: {
199
+
parent?: {
200
+
uri?: string;
201
+
author?: {
202
+
handle?: string;
203
+
did?: string;
224
204
};
225
-
reason?: AuthorFeedReason;
226
-
}>;
227
-
cursor?: string;
205
+
};
228
206
};
229
-
}>;
230
-
}
231
-
).get("app.bsky.feed.getAuthorFeed", {
232
-
params: {
207
+
};
208
+
reason?: AuthorFeedReason;
209
+
}>;
210
+
cursor?: string;
211
+
}
212
+
213
+
const res = await callAppviewRpc<AuthorFeedResponse>(
214
+
authorFeedService ?? blueskyAppviewService,
215
+
"app.bsky.feed.getAuthorFeed",
216
+
{
233
217
actor: actorIdentifier,
234
218
limit,
235
219
cursor,
236
220
filter: authorFeedFilter,
237
221
includePins: authorFeedIncludePins,
238
222
},
239
-
});
223
+
);
240
224
if (!res.ok)
241
225
throw new Error("Failed to fetch author feed");
242
226
const { feed, cursor: feedCursor } = res.data;
···
249
233
!post.record
250
234
)
251
235
return acc;
236
+
// Skip records with invalid timestamps (before 2023)
237
+
if (!isValidTimestamp(post.record)) {
238
+
console.warn("Skipping record with invalid timestamp:", post.uri);
239
+
return acc;
240
+
}
252
241
acc.push({
253
242
uri: post.uri,
254
243
rkey: extractRkey(post.uri),
···
268
257
}
269
258
270
259
if (!mapped) {
271
-
const { rpc } = await createAtprotoClient({
272
-
service: endpoint,
273
-
});
274
-
const res = await (
275
-
rpc as unknown as {
276
-
get: (
277
-
nsid: string,
278
-
opts: {
279
-
params: Record<
280
-
string,
281
-
string | number | boolean | undefined
282
-
>;
283
-
},
284
-
) => Promise<{
285
-
ok: boolean;
286
-
data: {
287
-
records: Array<{
288
-
uri: string;
289
-
rkey?: string;
290
-
value: T;
291
-
}>;
292
-
cursor?: string;
293
-
};
294
-
}>;
295
-
}
296
-
).get("com.atproto.repo.listRecords", {
297
-
params: {
298
-
repo: did,
299
-
collection,
300
-
limit,
301
-
cursor,
302
-
reverse: false,
303
-
},
304
-
});
305
-
if (!res.ok) throw new Error("Failed to list records");
260
+
// Slingshot doesn't support listRecords, query PDS directly
261
+
const res = await callListRecords<T>(
262
+
endpoint,
263
+
did,
264
+
collection,
265
+
limit,
266
+
cursor,
267
+
);
268
+
269
+
if (!res.ok) throw new Error("Failed to list records from PDS");
306
270
const { records, cursor: repoCursor } = res.data;
307
-
mapped = records.map((item) => ({
308
-
uri: item.uri,
309
-
rkey: item.rkey ?? extractRkey(item.uri),
310
-
value: item.value,
311
-
}));
271
+
mapped = records
272
+
.filter((item) => {
273
+
if (!isValidTimestamp(item.value)) {
274
+
console.warn("Skipping record with invalid timestamp:", item.uri);
275
+
return false;
276
+
}
277
+
return true;
278
+
})
279
+
.map((item) => ({
280
+
uri: item.uri,
281
+
rkey: item.rkey ?? extractRkey(item.uri),
282
+
value: item.value,
283
+
}));
312
284
nextCursor = repoCursor;
313
285
}
314
286
···
475
447
const parts = uri.split("/");
476
448
return parts[parts.length - 1];
477
449
}
450
+
451
+
/**
452
+
* Validates that a record has a reasonable timestamp (not before 2023).
453
+
* ATProto was created in 2023, so any timestamp before that is invalid.
454
+
*/
455
+
function isValidTimestamp(record: unknown): boolean {
456
+
if (typeof record !== "object" || record === null) return true;
457
+
458
+
const recordObj = record as { createdAt?: string; indexedAt?: string };
459
+
const timestamp = recordObj.createdAt || recordObj.indexedAt;
460
+
461
+
if (!timestamp || typeof timestamp !== "string") return true; // No timestamp to validate
462
+
463
+
try {
464
+
const date = new Date(timestamp);
465
+
// ATProto was created in 2023, reject anything before that
466
+
return date.getFullYear() >= 2023;
467
+
} catch {
468
+
// If we can't parse the date, consider it valid to avoid false negatives
469
+
return true;
470
+
}
471
+
}
+5
-1
lib/hooks/usePdsEndpoint.ts
+5
-1
lib/hooks/usePdsEndpoint.ts
···
45
45
})
46
46
.catch((e) => {
47
47
if (cancelled) return;
48
-
setError(e as Error);
48
+
const newError = e as Error;
49
+
// Only update error if message changed (stabilize reference)
50
+
setError(prevError =>
51
+
prevError?.message === newError.message ? prevError : newError
52
+
);
49
53
})
50
54
.finally(() => {
51
55
if (!cancelled) setLoading(false);
+104
lib/hooks/useRepoLanguages.ts
+104
lib/hooks/useRepoLanguages.ts
···
1
+
import { useState, useEffect } from "react";
2
+
import type { RepoLanguagesResponse } from "../types/tangled";
3
+
4
+
export interface UseRepoLanguagesOptions {
5
+
/** The knot server URL (e.g., "knot.gaze.systems") */
6
+
knot?: string;
7
+
/** DID of the repository owner */
8
+
did?: string;
9
+
/** Repository name */
10
+
repoName?: string;
11
+
/** Branch to query (defaults to trying "main", then "master") */
12
+
branch?: string;
13
+
/** Whether to enable the query */
14
+
enabled?: boolean;
15
+
}
16
+
17
+
export interface UseRepoLanguagesResult {
18
+
/** Language data from the knot server */
19
+
data?: RepoLanguagesResponse;
20
+
/** Loading state */
21
+
loading: boolean;
22
+
/** Error state */
23
+
error?: Error;
24
+
}
25
+
26
+
/**
27
+
* Hook to fetch repository language information from a Tangled knot server.
28
+
* If no branch supplied, tries "main" first, then falls back to "master".
29
+
*/
30
+
export function useRepoLanguages({
31
+
knot,
32
+
did,
33
+
repoName,
34
+
branch,
35
+
enabled = true,
36
+
}: UseRepoLanguagesOptions): UseRepoLanguagesResult {
37
+
const [data, setData] = useState<RepoLanguagesResponse | undefined>();
38
+
const [loading, setLoading] = useState(false);
39
+
const [error, setError] = useState<Error | undefined>();
40
+
41
+
useEffect(() => {
42
+
if (!enabled || !knot || !did || !repoName) {
43
+
return;
44
+
}
45
+
46
+
let cancelled = false;
47
+
48
+
const fetchLanguages = async (ref: string): Promise<boolean> => {
49
+
try {
50
+
const url = `https://${knot}/xrpc/sh.tangled.repo.languages?repo=${encodeURIComponent(`${did}/${repoName}`)}&ref=${encodeURIComponent(ref)}`;
51
+
const response = await fetch(url);
52
+
53
+
if (!response.ok) {
54
+
return false;
55
+
}
56
+
57
+
const result = await response.json();
58
+
if (!cancelled) {
59
+
setData(result);
60
+
setError(undefined);
61
+
}
62
+
return true;
63
+
} catch (err) {
64
+
return false;
65
+
}
66
+
};
67
+
68
+
const fetchWithFallback = async () => {
69
+
setLoading(true);
70
+
setError(undefined);
71
+
72
+
if (branch) {
73
+
const success = await fetchLanguages(branch);
74
+
if (!cancelled) {
75
+
if (!success) {
76
+
setError(new Error(`Failed to fetch languages for branch: ${branch}`));
77
+
}
78
+
setLoading(false);
79
+
}
80
+
} else {
81
+
// Try "main" first, then "master"
82
+
let success = await fetchLanguages("main");
83
+
if (!success && !cancelled) {
84
+
success = await fetchLanguages("master");
85
+
}
86
+
87
+
if (!cancelled) {
88
+
if (!success) {
89
+
setError(new Error("Failed to fetch languages for main or master branch"));
90
+
}
91
+
setLoading(false);
92
+
}
93
+
}
94
+
};
95
+
96
+
fetchWithFallback();
97
+
98
+
return () => {
99
+
cancelled = true;
100
+
};
101
+
}, [knot, did, repoName, branch, enabled]);
102
+
103
+
return { data, loading, error };
104
+
}
+18
-2
lib/index.ts
+18
-2
lib/index.ts
···
1
1
// Master exporter for the AT React component library.
2
2
3
+
import "./styles.css";
4
+
3
5
// Providers & core primitives
4
6
export * from "./providers/AtProtoProvider";
5
7
export * from "./core/AtProtoRecord";
···
10
12
export * from "./components/BlueskyPostList";
11
13
export * from "./components/BlueskyProfile";
12
14
export * from "./components/BlueskyQuotePost";
13
-
export * from "./components/ColorSchemeToggle";
15
+
export * from "./components/GrainGallery";
14
16
export * from "./components/LeafletDocument";
17
+
export * from "./components/TangledRepo";
15
18
export * from "./components/TangledString";
19
+
export * from "./components/CurrentlyPlaying";
20
+
export * from "./components/LastPlayed";
21
+
export * from "./components/SongHistoryList";
16
22
17
23
// Hooks
18
24
export * from "./hooks/useAtProtoRecord";
25
+
export * from "./hooks/useBacklinks";
19
26
export * from "./hooks/useBlob";
27
+
export * from "./hooks/useBlueskyAppview";
20
28
export * from "./hooks/useBlueskyProfile";
21
-
export * from "./hooks/useColorScheme";
22
29
export * from "./hooks/useDidResolution";
23
30
export * from "./hooks/useLatestRecord";
24
31
export * from "./hooks/usePaginatedRecords";
25
32
export * from "./hooks/usePdsEndpoint";
33
+
export * from "./hooks/useRepoLanguages";
26
34
27
35
// Renderers
28
36
export * from "./renderers/BlueskyPostRenderer";
29
37
export * from "./renderers/BlueskyProfileRenderer";
38
+
export * from "./renderers/GrainGalleryRenderer";
30
39
export * from "./renderers/LeafletDocumentRenderer";
40
+
export * from "./renderers/TangledRepoRenderer";
31
41
export * from "./renderers/TangledStringRenderer";
42
+
export * from "./renderers/CurrentlyPlayingRenderer";
32
43
33
44
// Types
34
45
export * from "./types/bluesky";
46
+
export * from "./types/grain";
35
47
export * from "./types/leaflet";
48
+
export * from "./types/tangled";
49
+
export * from "./types/teal";
50
+
export * from "./types/theme";
36
51
37
52
// Utilities
38
53
export * from "./utils/at-uri";
39
54
export * from "./utils/atproto-client";
55
+
export * from "./utils/blob";
40
56
export * from "./utils/profile";
+174
-7
lib/providers/AtProtoProvider.tsx
+174
-7
lib/providers/AtProtoProvider.tsx
···
1
1
/* eslint-disable react-refresh/only-export-components */
2
-
import React, { createContext, useContext, useMemo, useRef } from "react";
3
-
import { ServiceResolver, normalizeBaseUrl } from "../utils/atproto-client";
4
-
import { BlobCache, DidCache } from "../utils/cache";
2
+
import React, {
3
+
createContext,
4
+
useContext,
5
+
useMemo,
6
+
useRef,
7
+
} from "react";
8
+
import { ServiceResolver, normalizeBaseUrl, DEFAULT_CONFIG } from "../utils/atproto-client";
9
+
import { BlobCache, DidCache, RecordCache } from "../utils/cache";
5
10
11
+
/**
12
+
* Props for the AT Protocol context provider.
13
+
*/
6
14
export interface AtProtoProviderProps {
15
+
/** Child components that will have access to the AT Protocol context. */
7
16
children: React.ReactNode;
17
+
/** Optional custom PLC directory URL. Defaults to https://plc.directory */
8
18
plcDirectory?: string;
19
+
/** Optional custom identity service URL. Defaults to https://public.api.bsky.app */
20
+
identityService?: string;
21
+
/** Optional custom Slingshot service URL. Defaults to https://slingshot.microcosm.blue */
22
+
slingshotBaseUrl?: string;
23
+
/** Optional custom Bluesky appview service URL. Defaults to https://public.api.bsky.app */
24
+
blueskyAppviewService?: string;
25
+
/** Optional custom Bluesky app base URL for links. Defaults to https://bsky.app */
26
+
blueskyAppBaseUrl?: string;
27
+
/** Optional custom Tangled base URL for links. Defaults to https://tangled.org */
28
+
tangledBaseUrl?: string;
29
+
/** Optional custom Constellation API URL for backlinks. Defaults to https://constellation.microcosm.blue */
30
+
constellationBaseUrl?: string;
9
31
}
10
32
33
+
/**
34
+
* Internal context value shared across all AT Protocol hooks.
35
+
*/
11
36
interface AtProtoContextValue {
37
+
/** Service resolver for DID resolution and PDS endpoint discovery. */
12
38
resolver: ServiceResolver;
39
+
/** Normalized PLC directory base URL. */
13
40
plcDirectory: string;
41
+
/** Normalized Bluesky appview service URL. */
42
+
blueskyAppviewService: string;
43
+
/** Normalized Bluesky app base URL for links. */
44
+
blueskyAppBaseUrl: string;
45
+
/** Normalized Tangled base URL for links. */
46
+
tangledBaseUrl: string;
47
+
/** Normalized Constellation API base URL for backlinks. */
48
+
constellationBaseUrl: string;
49
+
/** Cache for DID documents and handle mappings. */
14
50
didCache: DidCache;
51
+
/** Cache for fetched blob data. */
15
52
blobCache: BlobCache;
53
+
/** Cache for fetched AT Protocol records. */
54
+
recordCache: RecordCache;
16
55
}
17
56
18
57
const AtProtoContext = createContext<AtProtoContextValue | undefined>(
19
58
undefined,
20
59
);
21
60
61
+
/**
62
+
* Context provider that supplies AT Protocol infrastructure to all child components.
63
+
*
64
+
* This provider initializes and shares:
65
+
* - Service resolver for DID and PDS endpoint resolution
66
+
* - DID cache for identity resolution
67
+
* - Blob cache for efficient media handling
68
+
*
69
+
* All AT Protocol components (`BlueskyPost`, `LeafletDocument`, etc.) must be wrapped
70
+
* in this provider to function correctly.
71
+
*
72
+
* @example
73
+
* ```tsx
74
+
* import { AtProtoProvider, BlueskyPost } from 'atproto-ui';
75
+
*
76
+
* function App() {
77
+
* return (
78
+
* <AtProtoProvider>
79
+
* <BlueskyPost did="did:plc:example" rkey="3k2aexample" />
80
+
* </AtProtoProvider>
81
+
* );
82
+
* }
83
+
* ```
84
+
*
85
+
* @example
86
+
* ```tsx
87
+
* // Using a custom PLC directory
88
+
* <AtProtoProvider plcDirectory="https://custom-plc.example.com">
89
+
* <YourComponents />
90
+
* </AtProtoProvider>
91
+
* ```
92
+
*
93
+
* @param children - Child components to render within the provider.
94
+
* @param plcDirectory - Optional PLC directory override (defaults to https://plc.directory).
95
+
* @returns Provider component that enables AT Protocol functionality.
96
+
*/
22
97
export function AtProtoProvider({
23
98
children,
24
99
plcDirectory,
100
+
identityService,
101
+
slingshotBaseUrl,
102
+
blueskyAppviewService,
103
+
blueskyAppBaseUrl,
104
+
tangledBaseUrl,
105
+
constellationBaseUrl,
25
106
}: AtProtoProviderProps) {
26
107
const normalizedPlc = useMemo(
27
108
() =>
28
109
normalizeBaseUrl(
29
110
plcDirectory && plcDirectory.trim()
30
111
? plcDirectory
31
-
: "https://plc.directory",
112
+
: DEFAULT_CONFIG.plcDirectory,
32
113
),
33
114
[plcDirectory],
34
115
);
116
+
const normalizedIdentity = useMemo(
117
+
() =>
118
+
normalizeBaseUrl(
119
+
identityService && identityService.trim()
120
+
? identityService
121
+
: DEFAULT_CONFIG.identityService,
122
+
),
123
+
[identityService],
124
+
);
125
+
const normalizedSlingshot = useMemo(
126
+
() =>
127
+
normalizeBaseUrl(
128
+
slingshotBaseUrl && slingshotBaseUrl.trim()
129
+
? slingshotBaseUrl
130
+
: DEFAULT_CONFIG.slingshotBaseUrl,
131
+
),
132
+
[slingshotBaseUrl],
133
+
);
134
+
const normalizedAppview = useMemo(
135
+
() =>
136
+
normalizeBaseUrl(
137
+
blueskyAppviewService && blueskyAppviewService.trim()
138
+
? blueskyAppviewService
139
+
: DEFAULT_CONFIG.blueskyAppviewService,
140
+
),
141
+
[blueskyAppviewService],
142
+
);
143
+
const normalizedBlueskyApp = useMemo(
144
+
() =>
145
+
normalizeBaseUrl(
146
+
blueskyAppBaseUrl && blueskyAppBaseUrl.trim()
147
+
? blueskyAppBaseUrl
148
+
: DEFAULT_CONFIG.blueskyAppBaseUrl,
149
+
),
150
+
[blueskyAppBaseUrl],
151
+
);
152
+
const normalizedTangled = useMemo(
153
+
() =>
154
+
normalizeBaseUrl(
155
+
tangledBaseUrl && tangledBaseUrl.trim()
156
+
? tangledBaseUrl
157
+
: DEFAULT_CONFIG.tangledBaseUrl,
158
+
),
159
+
[tangledBaseUrl],
160
+
);
161
+
const normalizedConstellation = useMemo(
162
+
() =>
163
+
normalizeBaseUrl(
164
+
constellationBaseUrl && constellationBaseUrl.trim()
165
+
? constellationBaseUrl
166
+
: DEFAULT_CONFIG.constellationBaseUrl,
167
+
),
168
+
[constellationBaseUrl],
169
+
);
35
170
const resolver = useMemo(
36
-
() => new ServiceResolver({ plcDirectory: normalizedPlc }),
37
-
[normalizedPlc],
171
+
() => new ServiceResolver({
172
+
plcDirectory: normalizedPlc,
173
+
identityService: normalizedIdentity,
174
+
slingshotBaseUrl: normalizedSlingshot,
175
+
}),
176
+
[normalizedPlc, normalizedIdentity, normalizedSlingshot],
38
177
);
39
178
const cachesRef = useRef<{
40
179
didCache: DidCache;
41
180
blobCache: BlobCache;
181
+
recordCache: RecordCache;
42
182
} | null>(null);
43
183
if (!cachesRef.current) {
44
184
cachesRef.current = {
45
185
didCache: new DidCache(),
46
186
blobCache: new BlobCache(),
187
+
recordCache: new RecordCache(),
47
188
};
48
189
}
190
+
49
191
const value = useMemo<AtProtoContextValue>(
50
192
() => ({
51
193
resolver,
52
194
plcDirectory: normalizedPlc,
195
+
blueskyAppviewService: normalizedAppview,
196
+
blueskyAppBaseUrl: normalizedBlueskyApp,
197
+
tangledBaseUrl: normalizedTangled,
198
+
constellationBaseUrl: normalizedConstellation,
53
199
didCache: cachesRef.current!.didCache,
54
200
blobCache: cachesRef.current!.blobCache,
201
+
recordCache: cachesRef.current!.recordCache,
55
202
}),
56
-
[resolver, normalizedPlc],
203
+
[resolver, normalizedPlc, normalizedAppview, normalizedBlueskyApp, normalizedTangled, normalizedConstellation],
57
204
);
205
+
58
206
return (
59
207
<AtProtoContext.Provider value={value}>
60
208
{children}
···
62
210
);
63
211
}
64
212
213
+
/**
214
+
* Hook that accesses the AT Protocol context provided by `AtProtoProvider`.
215
+
*
216
+
* This hook exposes the service resolver, DID cache, blob cache, and record cache
217
+
* for building custom AT Protocol functionality.
218
+
*
219
+
* @throws {Error} When called outside of an `AtProtoProvider`.
220
+
* @returns {AtProtoContextValue} Object containing resolver, caches, and PLC directory URL.
221
+
*
222
+
* @example
223
+
* ```tsx
224
+
* import { useAtProto } from 'atproto-ui';
225
+
*
226
+
* function MyCustomComponent() {
227
+
* const { resolver, didCache, blobCache, recordCache } = useAtProto();
228
+
* // Use the resolver and caches for custom AT Protocol operations
229
+
* }
230
+
* ```
231
+
*/
65
232
export function useAtProto() {
66
233
const ctx = useContext(AtProtoContext);
67
234
if (!ctx) throw new Error("useAtProto must be used within AtProtoProvider");
+322
-269
lib/renderers/BlueskyPostRenderer.tsx
+322
-269
lib/renderers/BlueskyPostRenderer.tsx
···
1
1
import React from "react";
2
2
import type { FeedPostRecord } from "../types/bluesky";
3
3
import {
4
-
useColorScheme,
5
-
type ColorSchemePreference,
6
-
} from "../hooks/useColorScheme";
7
-
import {
8
4
parseAtUri,
9
5
toBlueskyPostUrl,
10
6
formatDidForLabel,
···
13
9
import { useDidResolution } from "../hooks/useDidResolution";
14
10
import { useBlob } from "../hooks/useBlob";
15
11
import { BlueskyIcon } from "../components/BlueskyIcon";
12
+
import { isBlobWithCdn, extractCidFromBlob } from "../utils/blob";
13
+
import { RichText } from "../components/RichText";
16
14
17
15
export interface BlueskyPostRendererProps {
18
16
record: FeedPostRecord;
19
17
loading: boolean;
20
18
error?: Error;
21
-
// Optionally pass in actor display info if pre-fetched
22
19
authorHandle?: string;
23
20
authorDisplayName?: string;
24
21
avatarUrl?: string;
25
-
colorScheme?: ColorSchemePreference;
26
22
authorDid?: string;
27
23
embed?: React.ReactNode;
28
24
iconPlacement?: "cardBottomRight" | "timestamp" | "linkInline";
29
25
showIcon?: boolean;
30
26
atUri?: string;
27
+
isInThread?: boolean;
28
+
threadDepth?: number;
29
+
isQuotePost?: boolean;
30
+
showThreadBorder?: boolean;
31
31
}
32
32
33
33
export const BlueskyPostRenderer: React.FC<BlueskyPostRendererProps> = ({
···
37
37
authorDisplayName,
38
38
authorHandle,
39
39
avatarUrl,
40
-
colorScheme = "system",
41
40
authorDid,
42
41
embed,
43
42
iconPlacement = "timestamp",
44
43
showIcon = true,
45
44
atUri,
45
+
isInThread = false,
46
+
threadDepth = 0,
47
+
isQuotePost = false,
48
+
showThreadBorder = false
46
49
}) => {
47
-
const scheme = useColorScheme(colorScheme);
50
+
void threadDepth;
51
+
48
52
const replyParentUri = record.reply?.parent?.uri;
49
53
const replyTarget = replyParentUri ? parseAtUri(replyParentUri) : undefined;
50
54
const { handle: parentHandle, loading: parentHandleLoading } =
51
55
useDidResolution(replyTarget?.did);
52
56
53
-
if (error)
57
+
if (error) {
54
58
return (
55
-
<div style={{ padding: 8, color: "crimson" }}>
59
+
<div role="alert" style={{ padding: 8, color: "crimson" }}>
56
60
Failed to load post.
57
61
</div>
58
62
);
59
-
if (loading && !record) return <div style={{ padding: 8 }}>Loadingโฆ</div>;
60
-
61
-
const palette = scheme === "dark" ? themeStyles.dark : themeStyles.light;
63
+
}
64
+
if (loading && !record) return <div role="status" aria-live="polite" style={{ padding: 8 }}>Loadingโฆ</div>;
62
65
63
66
const text = record.text;
64
67
const createdDate = new Date(record.createdAt);
···
73
76
: undefined;
74
77
75
78
const makeIcon = () => (showIcon ? <BlueskyIcon size={16} /> : null);
76
-
const resolvedEmbed = embed ?? createAutoEmbed(record, authorDid, scheme);
79
+
const resolvedEmbed = embed ?? createAutoEmbed(record, authorDid);
77
80
const parsedSelf = atUri ? parseAtUri(atUri) : undefined;
78
81
const postUrl = parsedSelf ? toBlueskyPostUrl(parsedSelf) : undefined;
79
82
const cardPadding =
80
83
typeof baseStyles.card.padding === "number"
81
84
? baseStyles.card.padding
82
85
: 12;
86
+
83
87
const cardStyle: React.CSSProperties = {
84
88
...baseStyles.card,
85
-
...palette.card,
86
-
...(iconPlacement === "cardBottomRight" && showIcon
89
+
border: (isInThread && !isQuotePost && !showThreadBorder) ? "none" : `1px solid var(--atproto-color-border)`,
90
+
background: `var(--atproto-color-bg)`,
91
+
color: `var(--atproto-color-text)`,
92
+
borderRadius: (isInThread && !isQuotePost && !showThreadBorder) ? "0" : "12px",
93
+
...(iconPlacement === "cardBottomRight" && showIcon && !isInThread
87
94
? { paddingBottom: cardPadding + 16 }
88
95
: {}),
89
96
};
90
97
91
98
return (
92
99
<article style={cardStyle} aria-busy={loading}>
93
-
<header style={baseStyles.header}>
94
-
{avatarUrl ? (
95
-
<img
96
-
src={avatarUrl}
97
-
alt="avatar"
98
-
style={baseStyles.avatarImg}
99
-
/>
100
-
) : (
101
-
<div
102
-
style={{
103
-
...baseStyles.avatarPlaceholder,
104
-
...palette.avatarPlaceholder,
105
-
}}
106
-
aria-hidden
107
-
/>
108
-
)}
109
-
<div style={{ display: "flex", flexDirection: "column" }}>
110
-
<strong style={{ fontSize: 14 }}>{primaryName}</strong>
111
-
{authorDisplayName && authorHandle && (
112
-
<span
113
-
style={{ ...baseStyles.handle, ...palette.handle }}
114
-
>
115
-
@{authorHandle}
116
-
</span>
117
-
)}
118
-
</div>
119
-
{iconPlacement === "timestamp" && showIcon && (
120
-
<div style={baseStyles.headerIcon}>{makeIcon()}</div>
121
-
)}
122
-
</header>
123
-
{replyHref && replyLabel && (
124
-
<div style={{ ...baseStyles.replyLine, ...palette.replyLine }}>
125
-
Replying to{" "}
100
+
{isInThread ? (
101
+
<ThreadLayout
102
+
avatarUrl={avatarUrl}
103
+
primaryName={primaryName}
104
+
authorDisplayName={authorDisplayName}
105
+
authorHandle={authorHandle}
106
+
iconPlacement={iconPlacement}
107
+
showIcon={showIcon}
108
+
makeIcon={makeIcon}
109
+
replyHref={replyHref}
110
+
replyLabel={replyLabel}
111
+
text={text}
112
+
record={record}
113
+
created={created}
114
+
postUrl={postUrl}
115
+
resolvedEmbed={resolvedEmbed}
116
+
/>
117
+
) : (
118
+
<DefaultLayout
119
+
avatarUrl={avatarUrl}
120
+
primaryName={primaryName}
121
+
authorDisplayName={authorDisplayName}
122
+
authorHandle={authorHandle}
123
+
iconPlacement={iconPlacement}
124
+
showIcon={showIcon}
125
+
makeIcon={makeIcon}
126
+
replyHref={replyHref}
127
+
replyLabel={replyLabel}
128
+
text={text}
129
+
record={record}
130
+
created={created}
131
+
postUrl={postUrl}
132
+
resolvedEmbed={resolvedEmbed}
133
+
/>
134
+
)}
135
+
</article>
136
+
);
137
+
};
138
+
139
+
interface LayoutProps {
140
+
avatarUrl?: string;
141
+
primaryName: string;
142
+
authorDisplayName?: string;
143
+
authorHandle?: string;
144
+
iconPlacement: "cardBottomRight" | "timestamp" | "linkInline";
145
+
showIcon: boolean;
146
+
makeIcon: () => React.ReactNode;
147
+
replyHref?: string;
148
+
replyLabel?: string;
149
+
text: string;
150
+
record: FeedPostRecord;
151
+
created: string;
152
+
postUrl?: string;
153
+
resolvedEmbed: React.ReactNode;
154
+
}
155
+
156
+
const AuthorInfo: React.FC<{
157
+
primaryName: string;
158
+
authorDisplayName?: string;
159
+
authorHandle?: string;
160
+
inline?: boolean;
161
+
}> = ({ primaryName, authorDisplayName, authorHandle, inline = false }) => (
162
+
<div
163
+
style={{
164
+
display: "flex",
165
+
flexDirection: inline ? "row" : "column",
166
+
alignItems: inline ? "center" : "flex-start",
167
+
gap: inline ? 8 : 0,
168
+
}}
169
+
>
170
+
<strong style={{ fontSize: 14 }}>{authorDisplayName || primaryName}</strong>
171
+
{authorHandle && (
172
+
<span
173
+
style={{
174
+
...baseStyles.handle,
175
+
color: `var(--atproto-color-text-secondary)`,
176
+
}}
177
+
>
178
+
@{authorHandle}
179
+
</span>
180
+
)}
181
+
</div>
182
+
);
183
+
184
+
const Avatar: React.FC<{ avatarUrl?: string; name?: string }> = ({ avatarUrl, name }) =>
185
+
avatarUrl ? (
186
+
<img src={avatarUrl} alt={`${name || 'User'}'s profile picture`} style={baseStyles.avatarImg} />
187
+
) : (
188
+
<div style={baseStyles.avatarPlaceholder} aria-hidden="true" />
189
+
);
190
+
191
+
const ReplyInfo: React.FC<{
192
+
replyHref?: string;
193
+
replyLabel?: string;
194
+
marginBottom?: number;
195
+
}> = ({ replyHref, replyLabel, marginBottom = 0 }) =>
196
+
replyHref && replyLabel ? (
197
+
<div
198
+
style={{
199
+
...baseStyles.replyLine,
200
+
color: `var(--atproto-color-text-secondary)`,
201
+
marginBottom,
202
+
}}
203
+
>
204
+
Replying to{" "}
205
+
<a
206
+
href={replyHref}
207
+
target="_blank"
208
+
rel="noopener noreferrer"
209
+
style={{
210
+
...baseStyles.replyLink,
211
+
color: `var(--atproto-color-link)`,
212
+
}}
213
+
>
214
+
{replyLabel}
215
+
</a>
216
+
</div>
217
+
) : null;
218
+
219
+
const PostContent: React.FC<{
220
+
text: string;
221
+
record: FeedPostRecord;
222
+
created: string;
223
+
postUrl?: string;
224
+
iconPlacement: "cardBottomRight" | "timestamp" | "linkInline";
225
+
showIcon: boolean;
226
+
makeIcon: () => React.ReactNode;
227
+
resolvedEmbed: React.ReactNode;
228
+
}> = ({
229
+
text,
230
+
record,
231
+
created,
232
+
postUrl,
233
+
iconPlacement,
234
+
showIcon,
235
+
makeIcon,
236
+
resolvedEmbed,
237
+
}) => (
238
+
<div style={baseStyles.body}>
239
+
<p style={{ ...baseStyles.text, color: `var(--atproto-color-text)` }}>
240
+
<RichText text={text} facets={record.facets} />
241
+
</p>
242
+
{resolvedEmbed && (
243
+
<div style={baseStyles.embedContainer}>{resolvedEmbed}</div>
244
+
)}
245
+
<div style={baseStyles.timestampRow}>
246
+
<time
247
+
style={{
248
+
...baseStyles.time,
249
+
color: `var(--atproto-color-text-muted)`,
250
+
}}
251
+
dateTime={record.createdAt}
252
+
>
253
+
{created}
254
+
</time>
255
+
{postUrl && (
256
+
<span style={baseStyles.linkWithIcon}>
126
257
<a
127
-
href={replyHref}
258
+
href={postUrl}
128
259
target="_blank"
129
260
rel="noopener noreferrer"
130
261
style={{
131
-
...baseStyles.replyLink,
132
-
...palette.replyLink,
262
+
...baseStyles.postLink,
263
+
color: `var(--atproto-color-link)`,
133
264
}}
134
265
>
135
-
{replyLabel}
266
+
View on Bluesky
136
267
</a>
137
-
</div>
138
-
)}
139
-
<div style={baseStyles.body}>
140
-
<p style={{ ...baseStyles.text, ...palette.text }}>{text}</p>
141
-
{record.facets && record.facets.length > 0 && (
142
-
<div style={baseStyles.facets}>
143
-
{record.facets.map((_, idx) => (
144
-
<span
145
-
key={idx}
146
-
style={{
147
-
...baseStyles.facetTag,
148
-
...palette.facetTag,
149
-
}}
150
-
>
151
-
facet
152
-
</span>
153
-
))}
154
-
</div>
155
-
)}
156
-
<div style={baseStyles.timestampRow}>
157
-
<time
158
-
style={{ ...baseStyles.time, ...palette.time }}
159
-
dateTime={record.createdAt}
160
-
>
161
-
{created}
162
-
</time>
163
-
{postUrl && (
164
-
<span style={baseStyles.linkWithIcon}>
165
-
<a
166
-
href={postUrl}
167
-
target="_blank"
168
-
rel="noopener noreferrer"
169
-
style={{
170
-
...baseStyles.postLink,
171
-
...palette.postLink,
172
-
}}
173
-
>
174
-
View on Bluesky
175
-
</a>
176
-
{iconPlacement === "linkInline" && showIcon && (
177
-
<span style={baseStyles.inlineIcon} aria-hidden>
178
-
{makeIcon()}
179
-
</span>
180
-
)}
268
+
{iconPlacement === "linkInline" && showIcon && (
269
+
<span style={baseStyles.inlineIcon} aria-hidden>
270
+
{makeIcon()}
181
271
</span>
182
272
)}
183
-
</div>
184
-
{resolvedEmbed && (
185
-
<div
186
-
style={{
187
-
...baseStyles.embedContainer,
188
-
...palette.embedContainer,
189
-
}}
190
-
>
191
-
{resolvedEmbed}
192
-
</div>
273
+
</span>
274
+
)}
275
+
</div>
276
+
</div>
277
+
);
278
+
279
+
const ThreadLayout: React.FC<LayoutProps> = (props) => (
280
+
<div style={{ display: "flex", gap: 8, alignItems: "flex-start" }}>
281
+
<Avatar avatarUrl={props.avatarUrl} name={props.authorDisplayName || props.authorHandle} />
282
+
<div style={{ flex: 1, minWidth: 0 }}>
283
+
<div
284
+
style={{
285
+
display: "flex",
286
+
alignItems: "center",
287
+
gap: 8,
288
+
marginBottom: 4,
289
+
}}
290
+
>
291
+
<AuthorInfo
292
+
primaryName={props.primaryName}
293
+
authorDisplayName={props.authorDisplayName}
294
+
authorHandle={props.authorHandle}
295
+
inline
296
+
/>
297
+
{props.iconPlacement === "timestamp" && props.showIcon && (
298
+
<div style={{ marginLeft: "auto" }}>{props.makeIcon()}</div>
193
299
)}
194
300
</div>
195
-
{iconPlacement === "cardBottomRight" && showIcon && (
196
-
<div style={baseStyles.iconCorner} aria-hidden>
197
-
{makeIcon()}
301
+
<ReplyInfo
302
+
replyHref={props.replyHref}
303
+
replyLabel={props.replyLabel}
304
+
marginBottom={4}
305
+
/>
306
+
<PostContent {...props} />
307
+
{props.iconPlacement === "cardBottomRight" && props.showIcon && (
308
+
<div
309
+
style={{
310
+
position: "relative",
311
+
right: 0,
312
+
bottom: 0,
313
+
justifyContent: "flex-start",
314
+
marginTop: 8,
315
+
display: "flex",
316
+
}}
317
+
aria-hidden
318
+
>
319
+
{props.makeIcon()}
198
320
</div>
199
321
)}
200
-
</article>
201
-
);
202
-
};
322
+
</div>
323
+
</div>
324
+
);
325
+
326
+
const DefaultLayout: React.FC<LayoutProps> = (props) => (
327
+
<>
328
+
<header style={baseStyles.header}>
329
+
<Avatar avatarUrl={props.avatarUrl} name={props.authorDisplayName || props.authorHandle} />
330
+
<AuthorInfo
331
+
primaryName={props.primaryName}
332
+
authorDisplayName={props.authorDisplayName}
333
+
authorHandle={props.authorHandle}
334
+
/>
335
+
{props.iconPlacement === "timestamp" && props.showIcon && (
336
+
<div style={baseStyles.headerIcon}>{props.makeIcon()}</div>
337
+
)}
338
+
</header>
339
+
<ReplyInfo replyHref={props.replyHref} replyLabel={props.replyLabel} />
340
+
<PostContent {...props} />
341
+
{props.iconPlacement === "cardBottomRight" && props.showIcon && (
342
+
<div style={baseStyles.iconCorner} aria-hidden>
343
+
{props.makeIcon()}
344
+
</div>
345
+
)}
346
+
</>
347
+
);
203
348
204
349
const baseStyles: Record<string, React.CSSProperties> = {
205
350
card: {
···
241
386
time: {
242
387
fontSize: 11,
243
388
},
244
-
timestampIcon: {
245
-
display: "flex",
246
-
alignItems: "center",
247
-
justifyContent: "center",
248
-
},
249
389
body: {
250
390
fontSize: 14,
251
391
lineHeight: 1.4,
···
255
395
whiteSpace: "pre-wrap",
256
396
overflowWrap: "anywhere",
257
397
},
258
-
facets: {
259
-
marginTop: 8,
260
-
display: "flex",
261
-
gap: 4,
262
-
},
263
398
embedContainer: {
264
399
marginTop: 12,
265
400
padding: 8,
266
401
borderRadius: 12,
402
+
border: `1px solid var(--atproto-color-border)`,
403
+
background: `var(--atproto-color-bg-elevated)`,
267
404
display: "flex",
268
405
flexDirection: "column",
269
406
gap: 8,
···
290
427
display: "inline-flex",
291
428
alignItems: "center",
292
429
},
293
-
facetTag: {
294
-
padding: "2px 6px",
295
-
borderRadius: 4,
296
-
fontSize: 11,
297
-
},
298
430
replyLine: {
299
431
fontSize: 12,
300
432
},
···
312
444
},
313
445
};
314
446
315
-
const themeStyles = {
316
-
light: {
317
-
card: {
318
-
border: "1px solid #e2e8f0",
319
-
background: "#ffffff",
320
-
color: "#0f172a",
321
-
},
322
-
avatarPlaceholder: {
323
-
background: "#cbd5e1",
324
-
},
325
-
handle: {
326
-
color: "#64748b",
327
-
},
328
-
time: {
329
-
color: "#94a3b8",
330
-
},
331
-
text: {
332
-
color: "#0f172a",
333
-
},
334
-
facetTag: {
335
-
background: "#f1f5f9",
336
-
color: "#475569",
337
-
},
338
-
replyLine: {
339
-
color: "#475569",
340
-
},
341
-
replyLink: {
342
-
color: "#2563eb",
343
-
},
344
-
embedContainer: {
345
-
border: "1px solid #e2e8f0",
346
-
borderRadius: 12,
347
-
background: "#f8fafc",
348
-
},
349
-
postLink: {
350
-
color: "#2563eb",
351
-
},
352
-
},
353
-
dark: {
354
-
card: {
355
-
border: "1px solid #1e293b",
356
-
background: "#0f172a",
357
-
color: "#e2e8f0",
358
-
},
359
-
avatarPlaceholder: {
360
-
background: "#1e293b",
361
-
},
362
-
handle: {
363
-
color: "#cbd5f5",
364
-
},
365
-
time: {
366
-
color: "#94a3ff",
367
-
},
368
-
text: {
369
-
color: "#e2e8f0",
370
-
},
371
-
facetTag: {
372
-
background: "#1e293b",
373
-
color: "#e0f2fe",
374
-
},
375
-
replyLine: {
376
-
color: "#cbd5f5",
377
-
},
378
-
replyLink: {
379
-
color: "#38bdf8",
380
-
},
381
-
embedContainer: {
382
-
border: "1px solid #1e293b",
383
-
borderRadius: 12,
384
-
background: "#0b1120",
385
-
},
386
-
postLink: {
387
-
color: "#38bdf8",
388
-
},
389
-
},
390
-
} satisfies Record<"light" | "dark", Record<string, React.CSSProperties>>;
391
-
392
447
function formatReplyLabel(
393
448
target: ParsedAtUri,
394
449
resolvedHandle?: string,
···
402
457
function createAutoEmbed(
403
458
record: FeedPostRecord,
404
459
authorDid: string | undefined,
405
-
scheme: "light" | "dark",
406
460
): React.ReactNode {
407
461
const embed = record.embed as { $type?: string } | undefined;
408
462
if (!embed) return null;
409
463
if (embed.$type === "app.bsky.embed.images") {
410
-
return (
411
-
<ImagesEmbed
412
-
embed={embed as ImagesEmbedType}
413
-
did={authorDid}
414
-
scheme={scheme}
415
-
/>
416
-
);
464
+
return <ImagesEmbed embed={embed as ImagesEmbedType} did={authorDid} />;
417
465
}
418
466
if (embed.$type === "app.bsky.embed.recordWithMedia") {
419
467
const media = (embed as RecordWithMediaEmbed).media;
420
468
if (media?.$type === "app.bsky.embed.images") {
421
469
return (
422
-
<ImagesEmbed
423
-
embed={media as ImagesEmbedType}
424
-
did={authorDid}
425
-
scheme={scheme}
426
-
/>
470
+
<ImagesEmbed embed={media as ImagesEmbedType} did={authorDid} />
427
471
);
428
472
}
429
473
}
···
457
501
interface ImagesEmbedProps {
458
502
embed: ImagesEmbedType;
459
503
did?: string;
460
-
scheme: "light" | "dark";
461
504
}
462
505
463
-
const ImagesEmbed: React.FC<ImagesEmbedProps> = ({ embed, did, scheme }) => {
506
+
const ImagesEmbed: React.FC<ImagesEmbedProps> = ({ embed, did }) => {
464
507
if (!embed.images || embed.images.length === 0) return null;
465
-
const palette =
466
-
scheme === "dark" ? imagesPalette.dark : imagesPalette.light;
508
+
467
509
const columns =
468
510
embed.images.length > 1
469
511
? "repeat(auto-fit, minmax(160px, 1fr))"
···
472
514
<div
473
515
style={{
474
516
...imagesBase.container,
475
-
...palette.container,
517
+
background: `var(--atproto-color-bg-elevated)`,
476
518
gridTemplateColumns: columns,
477
519
}}
478
520
>
479
-
{embed.images.map((image, idx) => (
480
-
<PostImage key={idx} image={image} did={did} scheme={scheme} />
521
+
{embed.images.map((img, idx) => (
522
+
<PostImage key={idx} image={img} did={did} />
481
523
))}
482
524
</div>
483
525
);
···
486
528
interface PostImageProps {
487
529
image: ImagesEmbedType["images"][number];
488
530
did?: string;
489
-
scheme: "light" | "dark";
490
531
}
491
532
492
-
const PostImage: React.FC<PostImageProps> = ({ image, did, scheme }) => {
493
-
const cid = image.image?.ref?.$link ?? image.image?.cid;
494
-
const { url, loading, error } = useBlob(did, cid);
533
+
const PostImage: React.FC<PostImageProps> = ({ image, did }) => {
534
+
const [showAltText, setShowAltText] = React.useState(false);
535
+
const imageBlob = image.image;
536
+
const cdnUrl = isBlobWithCdn(imageBlob) ? imageBlob.cdnUrl : undefined;
537
+
const cid = cdnUrl ? undefined : extractCidFromBlob(imageBlob);
538
+
const { url: urlFromBlob, loading, error } = useBlob(did, cid);
539
+
const url = cdnUrl || urlFromBlob;
495
540
const alt = image.alt?.trim() || "Bluesky attachment";
496
-
const palette =
497
-
scheme === "dark" ? imagesPalette.dark : imagesPalette.light;
541
+
const hasAlt = image.alt && image.alt.trim().length > 0;
542
+
498
543
const aspect =
499
544
image.aspectRatio && image.aspectRatio.height > 0
500
545
? `${image.aspectRatio.width} / ${image.aspectRatio.height}`
501
546
: undefined;
502
547
503
548
return (
504
-
<figure style={{ ...imagesBase.item, ...palette.item }}>
549
+
<figure
550
+
style={{
551
+
...imagesBase.item,
552
+
background: `var(--atproto-color-bg-elevated)`,
553
+
}}
554
+
>
505
555
<div
506
556
style={{
507
557
...imagesBase.media,
508
-
...palette.media,
558
+
background: `var(--atproto-color-image-bg)`,
509
559
aspectRatio: aspect,
510
560
}}
511
561
>
···
513
563
<img src={url} alt={alt} style={imagesBase.img} />
514
564
) : (
515
565
<div
566
+
role={error ? "alert" : "status"}
516
567
style={{
517
568
...imagesBase.placeholder,
518
-
...palette.placeholder,
569
+
color: `var(--atproto-color-text-muted)`,
519
570
}}
520
571
>
521
572
{loading
···
524
575
? "Image failed to load"
525
576
: "Image unavailable"}
526
577
</div>
578
+
)}
579
+
{hasAlt && (
580
+
<button
581
+
onClick={() => setShowAltText(!showAltText)}
582
+
style={{
583
+
...imagesBase.altBadge,
584
+
background: showAltText
585
+
? `var(--atproto-color-text)`
586
+
: `var(--atproto-color-bg-secondary)`,
587
+
color: showAltText
588
+
? `var(--atproto-color-bg)`
589
+
: `var(--atproto-color-text)`,
590
+
}}
591
+
title="Toggle alt text"
592
+
aria-label="Toggle alt text"
593
+
>
594
+
ALT
595
+
</button>
527
596
)}
528
597
</div>
529
-
{image.alt && image.alt.trim().length > 0 && (
598
+
{hasAlt && showAltText && (
530
599
<figcaption
531
-
style={{ ...imagesBase.caption, ...palette.caption }}
600
+
style={{
601
+
...imagesBase.caption,
602
+
color: `var(--atproto-color-text-secondary)`,
603
+
}}
532
604
>
533
605
{image.alt}
534
606
</figcaption>
···
571
643
fontSize: 12,
572
644
lineHeight: 1.3,
573
645
} satisfies React.CSSProperties,
646
+
altBadge: {
647
+
position: "absolute",
648
+
bottom: 8,
649
+
right: 8,
650
+
padding: "4px 8px",
651
+
fontSize: 10,
652
+
fontWeight: 600,
653
+
letterSpacing: "0.5px",
654
+
border: "none",
655
+
borderRadius: 4,
656
+
cursor: "pointer",
657
+
transition: "background 150ms ease, color 150ms ease",
658
+
fontFamily: "system-ui, sans-serif",
659
+
} satisfies React.CSSProperties,
574
660
};
575
-
576
-
const imagesPalette = {
577
-
light: {
578
-
container: {
579
-
padding: 0,
580
-
} satisfies React.CSSProperties,
581
-
item: {},
582
-
media: {
583
-
background: "#e2e8f0",
584
-
} satisfies React.CSSProperties,
585
-
placeholder: {
586
-
color: "#475569",
587
-
} satisfies React.CSSProperties,
588
-
caption: {
589
-
color: "#475569",
590
-
} satisfies React.CSSProperties,
591
-
},
592
-
dark: {
593
-
container: {
594
-
padding: 0,
595
-
} satisfies React.CSSProperties,
596
-
item: {},
597
-
media: {
598
-
background: "#1e293b",
599
-
} satisfies React.CSSProperties,
600
-
placeholder: {
601
-
color: "#cbd5f5",
602
-
} satisfies React.CSSProperties,
603
-
caption: {
604
-
color: "#94a3b8",
605
-
} satisfies React.CSSProperties,
606
-
},
607
-
} as const;
608
661
609
662
export default BlueskyPostRenderer;
+54
-112
lib/renderers/BlueskyProfileRenderer.tsx
+54
-112
lib/renderers/BlueskyProfileRenderer.tsx
···
1
1
import React from "react";
2
2
import type { ProfileRecord } from "../types/bluesky";
3
-
import {
4
-
useColorScheme,
5
-
type ColorSchemePreference,
6
-
} from "../hooks/useColorScheme";
7
3
import { BlueskyIcon } from "../components/BlueskyIcon";
4
+
import { useAtProto } from "../providers/AtProtoProvider";
8
5
9
6
export interface BlueskyProfileRendererProps {
10
7
record: ProfileRecord;
···
13
10
did: string;
14
11
handle?: string;
15
12
avatarUrl?: string;
16
-
colorScheme?: ColorSchemePreference;
17
13
}
18
14
19
15
export const BlueskyProfileRenderer: React.FC<BlueskyProfileRendererProps> = ({
···
23
19
did,
24
20
handle,
25
21
avatarUrl,
26
-
colorScheme = "system",
27
22
}) => {
28
-
const scheme = useColorScheme(colorScheme);
23
+
const { blueskyAppBaseUrl } = useAtProto();
29
24
30
25
if (error)
31
26
return (
32
-
<div style={{ padding: 8, color: "crimson" }}>
27
+
<div role="alert" style={{ padding: 8, color: "crimson" }}>
33
28
Failed to load profile.
34
29
</div>
35
30
);
36
-
if (loading && !record) return <div style={{ padding: 8 }}>Loadingโฆ</div>;
31
+
if (loading && !record) return <div role="status" aria-live="polite" style={{ padding: 8 }}>Loadingโฆ</div>;
37
32
38
-
const palette = scheme === "dark" ? theme.dark : theme.light;
39
-
const profileUrl = `https://bsky.app/profile/${encodeURIComponent(did)}`;
33
+
const profileUrl = `${blueskyAppBaseUrl}/profile/${did}`;
40
34
const rawWebsite = record.website?.trim();
41
35
const websiteHref = rawWebsite
42
36
? rawWebsite.match(/^https?:\/\//i)
···
48
42
: undefined;
49
43
50
44
return (
51
-
<div style={{ ...base.card, ...palette.card }}>
45
+
<div style={{ ...base.card, background: `var(--atproto-color-bg)`, borderColor: `var(--atproto-color-border)`, color: `var(--atproto-color-text)` }}>
52
46
<div style={base.header}>
53
47
{avatarUrl ? (
54
-
<img src={avatarUrl} alt="avatar" style={base.avatarImg} />
48
+
<img src={avatarUrl} alt={`${record.displayName || handle || did}'s profile picture`} style={base.avatarImg} />
55
49
) : (
56
50
<div
57
-
style={{ ...base.avatar, ...palette.avatar }}
58
-
aria-label="avatar"
51
+
style={{ ...base.avatar, background: `var(--atproto-color-bg-elevated)` }}
52
+
aria-hidden="true"
59
53
/>
60
54
)}
61
55
<div style={{ flex: 1 }}>
62
-
<div style={{ ...base.display, ...palette.display }}>
56
+
<div style={{ ...base.display, color: `var(--atproto-color-text)` }}>
63
57
{record.displayName ?? handle ?? did}
64
58
</div>
65
-
<div style={{ ...base.handleLine, ...palette.handleLine }}>
59
+
<div style={{ ...base.handleLine, color: `var(--atproto-color-text-secondary)` }}>
66
60
@{handle ?? did}
67
61
</div>
68
62
{record.pronouns && (
69
-
<div style={{ ...base.pronouns, ...palette.pronouns }}>
63
+
<div style={{ ...base.pronouns, background: `var(--atproto-color-bg-elevated)`, color: `var(--atproto-color-text-secondary)` }}>
70
64
{record.pronouns}
71
65
</div>
72
66
)}
73
67
</div>
74
68
</div>
75
69
{record.description && (
76
-
<p style={{ ...base.desc, ...palette.desc }}>
70
+
<p style={{ ...base.desc, color: `var(--atproto-color-text)` }}>
77
71
{record.description}
78
72
</p>
79
73
)}
80
-
{record.createdAt && (
81
-
<div style={{ ...base.meta, ...palette.meta }}>
82
-
Joined {new Date(record.createdAt).toLocaleDateString()}
83
-
</div>
84
-
)}
85
-
<div style={base.links}>
86
-
{websiteHref && websiteLabel && (
74
+
<div style={base.bottomRow}>
75
+
<div style={base.bottomLeft}>
76
+
{record.createdAt && (
77
+
<div style={{ ...base.meta, color: `var(--atproto-color-text-secondary)` }}>
78
+
Joined {new Date(record.createdAt).toLocaleDateString()}
79
+
</div>
80
+
)}
81
+
{websiteHref && websiteLabel && (
82
+
<a
83
+
href={websiteHref}
84
+
target="_blank"
85
+
rel="noopener noreferrer"
86
+
style={{ ...base.link, color: `var(--atproto-color-link)` }}
87
+
>
88
+
{websiteLabel}
89
+
</a>
90
+
)}
87
91
<a
88
-
href={websiteHref}
92
+
href={profileUrl}
89
93
target="_blank"
90
94
rel="noopener noreferrer"
91
-
style={{ ...base.link, ...palette.link }}
95
+
style={{ ...base.link, color: `var(--atproto-color-link)` }}
92
96
>
93
-
{websiteLabel}
97
+
View on Bluesky
94
98
</a>
95
-
)}
96
-
<a
97
-
href={profileUrl}
98
-
target="_blank"
99
-
rel="noopener noreferrer"
100
-
style={{ ...base.link, ...palette.link }}
101
-
>
102
-
View on Bluesky
103
-
</a>
104
-
</div>
105
-
<div style={base.iconCorner} aria-hidden>
106
-
<BlueskyIcon size={18} />
99
+
</div>
100
+
<div aria-hidden>
101
+
<BlueskyIcon size={18} />
102
+
</div>
107
103
</div>
108
104
</div>
109
105
);
···
111
107
112
108
const base: Record<string, React.CSSProperties> = {
113
109
card: {
110
+
display: "flex",
111
+
flexDirection: "column",
112
+
height: "100%",
114
113
borderRadius: 12,
115
114
padding: 16,
116
115
fontFamily: "system-ui, sans-serif",
···
148
147
lineHeight: 1.4,
149
148
},
150
149
meta: {
151
-
marginTop: 12,
150
+
marginTop: 0,
152
151
fontSize: 12,
153
152
},
154
153
pronouns: {
···
161
160
padding: "2px 8px",
162
161
marginTop: 6,
163
162
},
164
-
links: {
165
-
display: "flex",
166
-
flexDirection: "column",
167
-
gap: 8,
168
-
marginTop: 12,
169
-
},
170
163
link: {
171
164
display: "inline-flex",
172
165
alignItems: "center",
···
175
168
fontWeight: 600,
176
169
textDecoration: "none",
177
170
},
171
+
bottomRow: {
172
+
display: "flex",
173
+
alignItems: "flex-end",
174
+
justifyContent: "space-between",
175
+
marginTop: "auto",
176
+
paddingTop: 12,
177
+
},
178
+
bottomLeft: {
179
+
display: "flex",
180
+
flexDirection: "column",
181
+
gap: 8,
182
+
},
178
183
iconCorner: {
179
-
position: "absolute",
180
-
right: 12,
181
-
bottom: 12,
184
+
// Removed absolute positioning, now in flex layout
182
185
},
183
186
};
184
-
185
-
const theme = {
186
-
light: {
187
-
card: {
188
-
border: "1px solid #e2e8f0",
189
-
background: "#ffffff",
190
-
color: "#0f172a",
191
-
},
192
-
avatar: {
193
-
background: "#cbd5e1",
194
-
},
195
-
display: {
196
-
color: "#0f172a",
197
-
},
198
-
handleLine: {
199
-
color: "#64748b",
200
-
},
201
-
desc: {
202
-
color: "#0f172a",
203
-
},
204
-
meta: {
205
-
color: "#94a3b8",
206
-
},
207
-
pronouns: {
208
-
background: "#e2e8f0",
209
-
color: "#1e293b",
210
-
},
211
-
link: {
212
-
color: "#2563eb",
213
-
},
214
-
},
215
-
dark: {
216
-
card: {
217
-
border: "1px solid #1e293b",
218
-
background: "#0b1120",
219
-
color: "#e2e8f0",
220
-
},
221
-
avatar: {
222
-
background: "#1e293b",
223
-
},
224
-
display: {
225
-
color: "#e2e8f0",
226
-
},
227
-
handleLine: {
228
-
color: "#cbd5f5",
229
-
},
230
-
desc: {
231
-
color: "#e2e8f0",
232
-
},
233
-
meta: {
234
-
color: "#a5b4fc",
235
-
},
236
-
pronouns: {
237
-
background: "#1e293b",
238
-
color: "#e2e8f0",
239
-
},
240
-
link: {
241
-
color: "#38bdf8",
242
-
},
243
-
},
244
-
} satisfies Record<"light" | "dark", Record<string, React.CSSProperties>>;
245
187
246
188
export default BlueskyProfileRenderer;
+749
lib/renderers/CurrentlyPlayingRenderer.tsx
+749
lib/renderers/CurrentlyPlayingRenderer.tsx
···
1
+
import React, { useState, useEffect, useRef } from "react";
2
+
import type { TealActorStatusRecord } from "../types/teal";
3
+
4
+
export interface CurrentlyPlayingRendererProps {
5
+
record: TealActorStatusRecord;
6
+
error?: Error;
7
+
loading: boolean;
8
+
did: string;
9
+
rkey: string;
10
+
colorScheme?: "light" | "dark" | "system";
11
+
/** Label to display (e.g., "CURRENTLY PLAYING", "LAST PLAYED"). Defaults to "CURRENTLY PLAYING". */
12
+
label?: string;
13
+
/** Handle to display in not listening state */
14
+
handle?: string;
15
+
}
16
+
17
+
interface SonglinkPlatform {
18
+
url: string;
19
+
entityUniqueId: string;
20
+
nativeAppUriMobile?: string;
21
+
nativeAppUriDesktop?: string;
22
+
}
23
+
24
+
interface SonglinkResponse {
25
+
linksByPlatform: {
26
+
[platform: string]: SonglinkPlatform;
27
+
};
28
+
entitiesByUniqueId: {
29
+
[id: string]: {
30
+
thumbnailUrl?: string;
31
+
title?: string;
32
+
artistName?: string;
33
+
};
34
+
};
35
+
}
36
+
37
+
export const CurrentlyPlayingRenderer: React.FC<CurrentlyPlayingRendererProps> = ({
38
+
record,
39
+
error,
40
+
loading,
41
+
label = "CURRENTLY PLAYING",
42
+
handle,
43
+
}) => {
44
+
const [albumArt, setAlbumArt] = useState<string | undefined>(undefined);
45
+
const [artworkLoading, setArtworkLoading] = useState(true);
46
+
const [songlinkData, setSonglinkData] = useState<SonglinkResponse | undefined>(undefined);
47
+
const [showPlatformModal, setShowPlatformModal] = useState(false);
48
+
const previousTrackIdentityRef = useRef<string>("");
49
+
50
+
// Auto-refresh interval removed - handled by AtProtoRecord
51
+
52
+
useEffect(() => {
53
+
if (!record) return;
54
+
55
+
const { item } = record;
56
+
const artistName = item.artists[0]?.artistName;
57
+
const trackName = item.trackName;
58
+
59
+
if (!artistName || !trackName) {
60
+
setArtworkLoading(false);
61
+
return;
62
+
}
63
+
64
+
// Create a unique identity for this track
65
+
const trackIdentity = `${trackName}::${artistName}`;
66
+
67
+
// Check if the track has actually changed
68
+
const trackHasChanged = trackIdentity !== previousTrackIdentityRef.current;
69
+
70
+
// Update tracked identity
71
+
previousTrackIdentityRef.current = trackIdentity;
72
+
73
+
// Only reset loading state and clear data when track actually changes
74
+
// This prevents the loading flicker when auto-refreshing the same track
75
+
if (trackHasChanged) {
76
+
console.log(`[teal.fm] ๐ต Track changed: "${trackName}" by ${artistName}`);
77
+
setArtworkLoading(true);
78
+
setAlbumArt(undefined);
79
+
setSonglinkData(undefined);
80
+
} else {
81
+
console.log(`[teal.fm] ๐ Auto-refresh: same track still playing ("${trackName}" by ${artistName})`);
82
+
}
83
+
84
+
let cancelled = false;
85
+
86
+
const fetchMusicData = async () => {
87
+
try {
88
+
// Step 1: Check if we have an ISRC - Songlink supports this directly
89
+
if (item.isrc) {
90
+
console.log(`[teal.fm] Attempting ISRC lookup for ${trackName} by ${artistName}`, { isrc: item.isrc });
91
+
const response = await fetch(
92
+
`https://api.song.link/v1-alpha.1/links?platform=isrc&type=song&id=${encodeURIComponent(item.isrc)}&songIfSingle=true`
93
+
);
94
+
if (cancelled) return;
95
+
if (response.ok) {
96
+
const data = await response.json();
97
+
setSonglinkData(data);
98
+
99
+
// Extract album art from Songlink data
100
+
const entityId = data.entityUniqueId;
101
+
const entity = data.entitiesByUniqueId?.[entityId];
102
+
103
+
// Debug: Log the entity structure to see what fields are available
104
+
console.log(`[teal.fm] ISRC entity data:`, { entityId, entity });
105
+
106
+
if (entity?.thumbnailUrl) {
107
+
console.log(`[teal.fm] โ Found album art via ISRC lookup`);
108
+
setAlbumArt(entity.thumbnailUrl);
109
+
} else {
110
+
console.warn(`[teal.fm] ISRC lookup succeeded but no thumbnail found`, {
111
+
entityId,
112
+
entityKeys: entity ? Object.keys(entity) : 'no entity',
113
+
entity
114
+
});
115
+
}
116
+
setArtworkLoading(false);
117
+
return;
118
+
} else {
119
+
console.warn(`[teal.fm] ISRC lookup failed with status ${response.status}`);
120
+
}
121
+
}
122
+
123
+
// Step 2: Search iTunes Search API to find the track (single request for both artwork and links)
124
+
console.log(`[teal.fm] Attempting iTunes search for: "${trackName}" by "${artistName}"`);
125
+
const iTunesSearchUrl = `https://itunes.apple.com/search?term=${encodeURIComponent(
126
+
`${trackName} ${artistName}`
127
+
)}&media=music&entity=song&limit=1`;
128
+
129
+
const iTunesResponse = await fetch(iTunesSearchUrl);
130
+
131
+
if (cancelled) return;
132
+
133
+
if (iTunesResponse.ok) {
134
+
const iTunesData = await iTunesResponse.json();
135
+
136
+
if (iTunesData.results && iTunesData.results.length > 0) {
137
+
const match = iTunesData.results[0];
138
+
const iTunesId = match.trackId;
139
+
140
+
// Set album artwork immediately (600x600 for high quality)
141
+
const artworkUrl = match.artworkUrl100?.replace('100x100', '600x600') || match.artworkUrl100;
142
+
if (artworkUrl) {
143
+
console.log(`[teal.fm] โ Found album art via iTunes search`, { url: artworkUrl });
144
+
setAlbumArt(artworkUrl);
145
+
} else {
146
+
console.warn(`[teal.fm] iTunes match found but no artwork URL`);
147
+
}
148
+
setArtworkLoading(false);
149
+
150
+
// Step 3: Use iTunes ID with Songlink to get all platform links
151
+
console.log(`[teal.fm] Fetching platform links via Songlink (iTunes ID: ${iTunesId})`);
152
+
const songlinkResponse = await fetch(
153
+
`https://api.song.link/v1-alpha.1/links?platform=itunes&type=song&id=${iTunesId}&songIfSingle=true`
154
+
);
155
+
156
+
if (cancelled) return;
157
+
158
+
if (songlinkResponse.ok) {
159
+
const songlinkData = await songlinkResponse.json();
160
+
console.log(`[teal.fm] โ Got platform links from Songlink`);
161
+
setSonglinkData(songlinkData);
162
+
return;
163
+
} else {
164
+
console.warn(`[teal.fm] Songlink request failed with status ${songlinkResponse.status}`);
165
+
}
166
+
} else {
167
+
console.warn(`[teal.fm] No iTunes results found for "${trackName}" by "${artistName}"`);
168
+
setArtworkLoading(false);
169
+
}
170
+
} else {
171
+
console.warn(`[teal.fm] iTunes search failed with status ${iTunesResponse.status}`);
172
+
}
173
+
174
+
// Step 4: Fallback - if originUrl is from a supported platform, try it directly
175
+
if (item.originUrl && (
176
+
item.originUrl.includes('spotify.com') ||
177
+
item.originUrl.includes('apple.com') ||
178
+
item.originUrl.includes('youtube.com') ||
179
+
item.originUrl.includes('tidal.com')
180
+
)) {
181
+
console.log(`[teal.fm] Attempting Songlink lookup via originUrl`, { url: item.originUrl });
182
+
const songlinkResponse = await fetch(
183
+
`https://api.song.link/v1-alpha.1/links?url=${encodeURIComponent(item.originUrl)}&songIfSingle=true`
184
+
);
185
+
186
+
if (cancelled) return;
187
+
188
+
if (songlinkResponse.ok) {
189
+
const data = await songlinkResponse.json();
190
+
console.log(`[teal.fm] โ Got data from Songlink via originUrl`);
191
+
setSonglinkData(data);
192
+
193
+
// Try to get artwork from Songlink if we don't have it yet
194
+
if (!albumArt) {
195
+
const entityId = data.entityUniqueId;
196
+
const entity = data.entitiesByUniqueId?.[entityId];
197
+
198
+
// Debug: Log the entity structure to see what fields are available
199
+
console.log(`[teal.fm] Songlink originUrl entity data:`, { entityId, entity });
200
+
201
+
if (entity?.thumbnailUrl) {
202
+
console.log(`[teal.fm] โ Found album art via Songlink originUrl lookup`);
203
+
setAlbumArt(entity.thumbnailUrl);
204
+
} else {
205
+
console.warn(`[teal.fm] Songlink lookup succeeded but no thumbnail found`, {
206
+
entityId,
207
+
entityKeys: entity ? Object.keys(entity) : 'no entity',
208
+
entity
209
+
});
210
+
}
211
+
}
212
+
} else {
213
+
console.warn(`[teal.fm] Songlink originUrl lookup failed with status ${songlinkResponse.status}`);
214
+
}
215
+
}
216
+
217
+
if (!albumArt) {
218
+
console.warn(`[teal.fm] โ All album art fetch methods failed for "${trackName}" by "${artistName}"`);
219
+
}
220
+
221
+
setArtworkLoading(false);
222
+
} catch (err) {
223
+
console.error(`[teal.fm] โ Error fetching music data for "${trackName}" by "${artistName}":`, err);
224
+
setArtworkLoading(false);
225
+
}
226
+
};
227
+
228
+
fetchMusicData();
229
+
230
+
return () => {
231
+
cancelled = true;
232
+
};
233
+
}, [record]); // Runs on record change
234
+
235
+
if (error)
236
+
return (
237
+
<div role="alert" style={{ padding: 8, color: "var(--atproto-color-error)" }}>
238
+
Failed to load status.
239
+
</div>
240
+
);
241
+
if (loading && !record)
242
+
return (
243
+
<div role="status" aria-live="polite" style={{ padding: 8, color: "var(--atproto-color-text-secondary)" }}>
244
+
Loadingโฆ
245
+
</div>
246
+
);
247
+
248
+
const { item } = record;
249
+
250
+
// Check if user is not listening to anything
251
+
const isNotListening = !item.trackName || item.artists.length === 0;
252
+
253
+
// Show "not listening" state
254
+
if (isNotListening) {
255
+
const displayHandle = handle || "User";
256
+
return (
257
+
<div style={styles.notListeningContainer}>
258
+
<div style={styles.notListeningIcon}>
259
+
<svg
260
+
width="80"
261
+
height="80"
262
+
viewBox="0 0 24 24"
263
+
fill="none"
264
+
stroke="currentColor"
265
+
strokeWidth="1.5"
266
+
strokeLinecap="round"
267
+
strokeLinejoin="round"
268
+
>
269
+
<path d="M9 18V5l12-2v13" />
270
+
<circle cx="6" cy="18" r="3" />
271
+
<circle cx="18" cy="16" r="3" />
272
+
</svg>
273
+
</div>
274
+
<div style={styles.notListeningTitle}>
275
+
{displayHandle} isn't listening to anything
276
+
</div>
277
+
<div style={styles.notListeningSubtitle}>Check back soon</div>
278
+
</div>
279
+
);
280
+
}
281
+
282
+
const artistNames = item.artists.map((a) => a.artistName).join(", ");
283
+
284
+
const platformConfig: Record<string, { name: string; svg: string; color: string }> = {
285
+
spotify: {
286
+
name: "Spotify",
287
+
svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="#1ed760" d="M248 8C111.1 8 0 119.1 0 256s111.1 248 248 248 248-111.1 248-248S384.9 8 248 8Z"/><path d="M406.6 231.1c-5.2 0-8.4-1.3-12.9-3.9-71.2-42.5-198.5-52.7-280.9-29.7-3.6 1-8.1 2.6-12.9 2.6-13.2 0-23.3-10.3-23.3-23.6 0-13.6 8.4-21.3 17.4-23.9 35.2-10.3 74.6-15.2 117.5-15.2 73 0 149.5 15.2 205.4 47.8 7.8 4.5 12.9 10.7 12.9 22.6 0 13.6-11 23.3-23.2 23.3zm-31 76.2c-5.2 0-8.7-2.3-12.3-4.2-62.5-37-155.7-51.9-238.6-29.4-4.8 1.3-7.4 2.6-11.9 2.6-10.7 0-19.4-8.7-19.4-19.4s5.2-17.8 15.5-20.7c27.8-7.8 56.2-13.6 97.8-13.6 64.9 0 127.6 16.1 177 45.5 8.1 4.8 11.3 11 11.3 19.7-.1 10.8-8.5 19.5-19.4 19.5zm-26.9 65.6c-4.2 0-6.8-1.3-10.7-3.6-62.4-37.6-135-39.2-206.7-24.5-3.9 1-9 2.6-11.9 2.6-9.7 0-15.8-7.7-15.8-15.8 0-10.3 6.1-15.2 13.6-16.8 81.9-18.1 165.6-16.5 237 26.2 6.1 3.9 9.7 7.4 9.7 16.5s-7.1 15.4-15.2 15.4z"/></svg>',
288
+
color: "#1DB954"
289
+
},
290
+
appleMusic: {
291
+
name: "Apple Music",
292
+
svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 361 361"><defs><linearGradient id="apple-grad" x1="180" y1="358.6" x2="180" y2="7.76" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#FA233B"/><stop offset="1" style="stop-color:#FB5C74"/></linearGradient></defs><path fill="url(#apple-grad)" d="M360 112.61V247.39c0 4.3 0 8.6-.02 12.9-.02 3.62-.06 7.24-.16 10.86-.21 7.89-.68 15.84-2.08 23.64-1.42 7.92-3.75 15.29-7.41 22.49-3.6 7.07-8.3 13.53-13.91 19.14-5.61 5.61-12.08 10.31-19.15 13.91-7.19 3.66-14.56 5.98-22.47 7.41-7.8 1.4-15.76 1.87-23.65 2.08-3.62.1-7.24.14-10.86.16-4.3.03-8.6.02-12.9.02H112.61c-4.3 0-8.6 0-12.9-.02-3.62-.02-7.24-.06-10.86-.16-7.89-.21-15.85-.68-23.65-2.08-7.92-1.42-15.28-3.75-22.47-7.41-7.07-3.6-13.54-8.3-19.15-13.91-5.61-5.61-10.31-12.07-13.91-19.14-3.66-7.2-5.99-14.57-7.41-22.49-1.4-7.8-1.87-15.76-2.08-23.64-.1-3.62-.14-7.24-.16-10.86C0 255.99 0 251.69 0 247.39V112.61c0-4.3 0-8.6.02-12.9.02-3.62.06-7.24.16-10.86.21-7.89.68-15.84 2.08-23.64 1.42-7.92 3.75-15.29 7.41-22.49 3.6-7.07 8.3-13.53 13.91-19.14 5.61-5.61 12.08-10.31 19.15-13.91 7.19-3.66 14.56-5.98 22.47-7.41 7.8-1.4 15.76-1.87 23.65-2.08 3.62-.1 7.24-.14 10.86-.16C104.01 0 108.31 0 112.61 0h134.77c4.3 0 8.6 0 12.9.02 3.62.02 7.24.06 10.86.16 7.89.21 15.85.68 23.65 2.08 7.92 1.42 15.28 3.75 22.47 7.41 7.07 3.6 13.54 8.3 19.15 13.91 5.61 5.61 10.31 12.07 13.91 19.14 3.66 7.2 5.99 14.57 7.41 22.49 1.4 7.8 1.87 15.76 2.08 23.64.1 3.62.14 7.24.16 10.86.03 4.3.02 8.6.02 12.9z"/><path fill="#FFF" d="M254.5 55c-.87.08-8.6 1.45-9.53 1.64l-107 21.59-.04.01c-2.79.59-4.98 1.58-6.67 3-2.04 1.71-3.17 4.13-3.6 6.95-.09.6-.24 1.82-.24 3.62v133.92c0 3.13-.25 6.17-2.37 8.76-2.12 2.59-4.74 3.37-7.81 3.99-2.33.47-4.66.94-6.99 1.41-8.84 1.78-14.59 2.99-19.8 5.01-4.98 1.93-8.71 4.39-11.68 7.51-5.89 6.17-8.28 14.54-7.46 22.38.7 6.69 3.71 13.09 8.88 17.82 3.49 3.2 7.85 5.63 12.99 6.66 5.33 1.07 11.01.7 19.31-.98 4.42-.89 8.56-2.28 12.5-4.61 3.9-2.3 7.24-5.37 9.85-9.11 2.62-3.75 4.31-7.92 5.24-12.35.96-4.57 1.19-8.7 1.19-13.26V128.82c0-6.22 1.76-7.86 6.78-9.08l93.09-18.75c5.79-1.11 8.52.54 8.52 6.61v79.29c0 3.14-.03 6.32-2.17 8.92-2.12 2.59-4.74 3.37-7.81 3.99-2.33.47-4.66.94-6.99 1.41-8.84 1.78-14.59 2.99-19.8 5.01-4.98 1.93-8.71 4.39-11.68 7.51-5.89 6.17-8.49 14.54-7.67 22.38.7 6.69 3.92 13.09 9.09 17.82 3.49 3.2 7.85 5.56 12.99 6.6 5.33 1.07 11.01.69 19.31-.98 4.42-.89 8.56-2.22 12.5-4.55 3.9-2.3 7.24-5.37 9.85-9.11 2.62-3.75 4.31-7.92 5.24-12.35.96-4.57 1-8.7 1-13.26V64.46c0-6.16-3.25-9.96-9.04-9.46z"/></svg>',
293
+
color: "#FA243C"
294
+
},
295
+
youtube: {
296
+
name: "YouTube",
297
+
svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300"><g transform="scale(.75)"><path fill="red" d="M199.917 105.63s-84.292 0-105.448 5.497c-11.328 3.165-20.655 12.493-23.82 23.987-5.498 21.156-5.498 64.969-5.498 64.969s0 43.979 5.497 64.802c3.165 11.494 12.326 20.655 23.82 23.82 21.323 5.664 105.448 5.664 105.448 5.664s84.459 0 105.615-5.497c11.494-3.165 20.655-12.16 23.654-23.82 5.664-20.99 5.664-64.803 5.664-64.803s.166-43.98-5.664-65.135c-2.999-11.494-12.16-20.655-23.654-23.654-21.156-5.83-105.615-5.83-105.615-5.83zm-26.82 53.974 70.133 40.479-70.133 40.312v-80.79z"/><path fill="#fff" d="m173.097 159.604 70.133 40.479-70.133 40.312v-80.79z"/></g></svg>',
298
+
color: "#FF0000"
299
+
},
300
+
youtubeMusic: {
301
+
name: "YouTube Music",
302
+
svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 176 176"><circle fill="#FF0000" cx="88" cy="88" r="88"/><path fill="#FFF" d="M88 46c23.1 0 42 18.8 42 42s-18.8 42-42 42-42-18.8-42-42 18.8-42 42-42m0-4c-25.4 0-46 20.6-46 46s20.6 46 46 46 46-20.6 46-46-20.6-46-46-46z"/><path fill="#FFF" d="m72 111 39-24-39-22z"/></svg>',
303
+
color: "#FF0000"
304
+
},
305
+
tidal: {
306
+
name: "Tidal",
307
+
svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M256 0c141.385 0 256 114.615 256 256S397.385 512 256 512 0 397.385 0 256 114.615 0 256 0zm50.384 219.459-50.372 50.383 50.379 50.391-50.382 50.393-50.395-50.393 50.393-50.389-50.393-50.39 50.395-50.372 50.38 50.369 50.389-50.375 50.382 50.382-50.382 50.392-50.394-50.391zm-100.767-.001-50.392 50.392-50.385-50.392 50.385-50.382 50.392 50.382z"/></svg>',
308
+
color: "#000000"
309
+
},
310
+
bandcamp: {
311
+
name: "Bandcamp",
312
+
svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#1DA0C3" d="M0 156v200h172l84-200z"/></svg>',
313
+
color: "#1DA0C3"
314
+
},
315
+
};
316
+
317
+
const availablePlatforms = songlinkData
318
+
? Object.keys(platformConfig).filter((platform) =>
319
+
songlinkData.linksByPlatform[platform]
320
+
)
321
+
: [];
322
+
323
+
return (
324
+
<>
325
+
<div style={styles.container}>
326
+
{/* Album Artwork */}
327
+
<div style={styles.artworkContainer}>
328
+
{artworkLoading ? (
329
+
<div style={styles.artworkPlaceholder}>
330
+
<div style={styles.loadingSpinner} />
331
+
</div>
332
+
) : albumArt ? (
333
+
<img
334
+
src={albumArt}
335
+
alt={`${item.releaseName || "Album"} cover`}
336
+
style={styles.artwork}
337
+
onError={(e) => {
338
+
console.error("Failed to load album art:", {
339
+
url: albumArt,
340
+
track: item.trackName,
341
+
artist: item.artists[0]?.artistName,
342
+
error: "Image load error"
343
+
});
344
+
e.currentTarget.style.display = "none";
345
+
}}
346
+
/>
347
+
) : (
348
+
<div style={styles.artworkPlaceholder}>
349
+
<svg
350
+
width="64"
351
+
height="64"
352
+
viewBox="0 0 24 24"
353
+
fill="none"
354
+
stroke="currentColor"
355
+
strokeWidth="1.5"
356
+
>
357
+
<circle cx="12" cy="12" r="10" />
358
+
<circle cx="12" cy="12" r="3" />
359
+
<path d="M12 2v3M12 19v3M2 12h3M19 12h3" />
360
+
</svg>
361
+
</div>
362
+
)}
363
+
</div>
364
+
365
+
{/* Content */}
366
+
<div style={styles.content}>
367
+
<div style={styles.label}>{label}</div>
368
+
<h2 style={styles.trackName}>{item.trackName}</h2>
369
+
<div style={styles.artistName}>{artistNames}</div>
370
+
{item.releaseName && (
371
+
<div style={styles.releaseName}>from {item.releaseName}</div>
372
+
)}
373
+
374
+
{/* Listen Button */}
375
+
{availablePlatforms.length > 0 ? (
376
+
<button
377
+
onClick={() => setShowPlatformModal(true)}
378
+
style={styles.listenButton}
379
+
data-teal-listen-button="true"
380
+
>
381
+
<span>Listen with your Streaming Client</span>
382
+
<svg
383
+
width="16"
384
+
height="16"
385
+
viewBox="0 0 24 24"
386
+
fill="none"
387
+
stroke="currentColor"
388
+
strokeWidth="2"
389
+
strokeLinecap="round"
390
+
strokeLinejoin="round"
391
+
>
392
+
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />
393
+
<polyline points="15 3 21 3 21 9" />
394
+
<line x1="10" y1="14" x2="21" y2="3" />
395
+
</svg>
396
+
</button>
397
+
) : item.originUrl ? (
398
+
<a
399
+
href={item.originUrl}
400
+
target="_blank"
401
+
rel="noopener noreferrer"
402
+
style={styles.listenButton}
403
+
data-teal-listen-button="true"
404
+
>
405
+
<span>Listen on Last.fm</span>
406
+
<svg
407
+
width="16"
408
+
height="16"
409
+
viewBox="0 0 24 24"
410
+
fill="none"
411
+
stroke="currentColor"
412
+
strokeWidth="2"
413
+
strokeLinecap="round"
414
+
strokeLinejoin="round"
415
+
>
416
+
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />
417
+
<polyline points="15 3 21 3 21 9" />
418
+
<line x1="10" y1="14" x2="21" y2="3" />
419
+
</svg>
420
+
</a>
421
+
) : null}
422
+
</div>
423
+
</div>
424
+
425
+
{/* Platform Selection Modal */}
426
+
{showPlatformModal && songlinkData && (
427
+
<div style={styles.modalOverlay} onClick={() => setShowPlatformModal(false)}>
428
+
<div
429
+
role="dialog"
430
+
aria-modal="true"
431
+
aria-labelledby="platform-modal-title"
432
+
style={styles.modalContent}
433
+
onClick={(e) => e.stopPropagation()}
434
+
>
435
+
<div style={styles.modalHeader}>
436
+
<h3 id="platform-modal-title" style={styles.modalTitle}>Choose your streaming service</h3>
437
+
<button
438
+
style={styles.closeButton}
439
+
onClick={() => setShowPlatformModal(false)}
440
+
data-teal-close="true"
441
+
>
442
+
ร
443
+
</button>
444
+
</div>
445
+
<div style={styles.platformList}>
446
+
{availablePlatforms.map((platform) => {
447
+
const config = platformConfig[platform];
448
+
const link = songlinkData.linksByPlatform[platform];
449
+
return (
450
+
<a
451
+
key={platform}
452
+
href={link.url}
453
+
target="_blank"
454
+
rel="noopener noreferrer"
455
+
style={{
456
+
...styles.platformItem,
457
+
borderLeft: `4px solid ${config.color}`,
458
+
}}
459
+
onClick={() => setShowPlatformModal(false)}
460
+
data-teal-platform="true"
461
+
>
462
+
<span
463
+
style={styles.platformIcon}
464
+
dangerouslySetInnerHTML={{ __html: config.svg }}
465
+
/>
466
+
<span style={styles.platformName}>{config.name}</span>
467
+
<svg
468
+
width="20"
469
+
height="20"
470
+
viewBox="0 0 24 24"
471
+
fill="none"
472
+
stroke="currentColor"
473
+
strokeWidth="2"
474
+
style={styles.platformArrow}
475
+
>
476
+
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />
477
+
<polyline points="15 3 21 3 21 9" />
478
+
<line x1="10" y1="14" x2="21" y2="3" />
479
+
</svg>
480
+
</a>
481
+
);
482
+
})}
483
+
</div>
484
+
</div>
485
+
</div>
486
+
)}
487
+
</>
488
+
);
489
+
};
490
+
491
+
const styles: Record<string, React.CSSProperties> = {
492
+
container: {
493
+
fontFamily: "system-ui, -apple-system, sans-serif",
494
+
display: "flex",
495
+
flexDirection: "column",
496
+
background: "var(--atproto-color-bg)",
497
+
borderRadius: 16,
498
+
overflow: "hidden",
499
+
maxWidth: 420,
500
+
color: "var(--atproto-color-text)",
501
+
boxShadow: "0 8px 24px rgba(0, 0, 0, 0.4)",
502
+
border: "1px solid var(--atproto-color-border)",
503
+
},
504
+
artworkContainer: {
505
+
width: "100%",
506
+
aspectRatio: "1 / 1",
507
+
position: "relative",
508
+
overflow: "hidden",
509
+
},
510
+
artwork: {
511
+
width: "100%",
512
+
height: "100%",
513
+
objectFit: "cover",
514
+
display: "block",
515
+
},
516
+
artworkPlaceholder: {
517
+
width: "100%",
518
+
height: "100%",
519
+
display: "flex",
520
+
alignItems: "center",
521
+
justifyContent: "center",
522
+
background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
523
+
color: "rgba(255, 255, 255, 0.5)",
524
+
},
525
+
loadingSpinner: {
526
+
width: 40,
527
+
height: 40,
528
+
border: "3px solid var(--atproto-color-border)",
529
+
borderTop: "3px solid var(--atproto-color-primary)",
530
+
borderRadius: "50%",
531
+
animation: "spin 1s linear infinite",
532
+
},
533
+
content: {
534
+
padding: "24px",
535
+
display: "flex",
536
+
flexDirection: "column",
537
+
gap: "8px",
538
+
},
539
+
label: {
540
+
fontSize: 11,
541
+
fontWeight: 600,
542
+
letterSpacing: "0.1em",
543
+
textTransform: "uppercase",
544
+
color: "var(--atproto-color-text-secondary)",
545
+
marginBottom: "4px",
546
+
},
547
+
trackName: {
548
+
fontSize: 28,
549
+
fontWeight: 700,
550
+
margin: 0,
551
+
lineHeight: 1.2,
552
+
color: "var(--atproto-color-text)",
553
+
},
554
+
artistName: {
555
+
fontSize: 16,
556
+
color: "var(--atproto-color-text-secondary)",
557
+
marginTop: "4px",
558
+
},
559
+
releaseName: {
560
+
fontSize: 14,
561
+
color: "var(--atproto-color-text-secondary)",
562
+
marginTop: "2px",
563
+
},
564
+
listenButton: {
565
+
display: "inline-flex",
566
+
alignItems: "center",
567
+
gap: "8px",
568
+
marginTop: "16px",
569
+
padding: "12px 20px",
570
+
background: "var(--atproto-color-bg-elevated)",
571
+
border: "1px solid var(--atproto-color-border)",
572
+
borderRadius: 24,
573
+
color: "var(--atproto-color-text)",
574
+
fontSize: 14,
575
+
fontWeight: 600,
576
+
textDecoration: "none",
577
+
cursor: "pointer",
578
+
transition: "all 0.2s ease",
579
+
alignSelf: "flex-start",
580
+
},
581
+
modalOverlay: {
582
+
position: "fixed",
583
+
top: 0,
584
+
left: 0,
585
+
right: 0,
586
+
bottom: 0,
587
+
backgroundColor: "rgba(0, 0, 0, 0.85)",
588
+
display: "flex",
589
+
alignItems: "center",
590
+
justifyContent: "center",
591
+
zIndex: 9999,
592
+
backdropFilter: "blur(4px)",
593
+
},
594
+
modalContent: {
595
+
background: "var(--atproto-color-bg)",
596
+
borderRadius: 16,
597
+
padding: 0,
598
+
maxWidth: 450,
599
+
width: "90%",
600
+
maxHeight: "80vh",
601
+
overflow: "auto",
602
+
boxShadow: "0 20px 60px rgba(0, 0, 0, 0.8)",
603
+
border: "1px solid var(--atproto-color-border)",
604
+
},
605
+
modalHeader: {
606
+
display: "flex",
607
+
justifyContent: "space-between",
608
+
alignItems: "center",
609
+
padding: "24px 24px 16px 24px",
610
+
borderBottom: "1px solid var(--atproto-color-border)",
611
+
},
612
+
modalTitle: {
613
+
margin: 0,
614
+
fontSize: 20,
615
+
fontWeight: 700,
616
+
color: "var(--atproto-color-text)",
617
+
},
618
+
closeButton: {
619
+
background: "transparent",
620
+
border: "none",
621
+
color: "var(--atproto-color-text-secondary)",
622
+
fontSize: 32,
623
+
cursor: "pointer",
624
+
padding: 0,
625
+
width: 32,
626
+
height: 32,
627
+
display: "flex",
628
+
alignItems: "center",
629
+
justifyContent: "center",
630
+
borderRadius: "50%",
631
+
transition: "all 0.2s ease",
632
+
lineHeight: 1,
633
+
},
634
+
platformList: {
635
+
padding: "16px",
636
+
display: "flex",
637
+
flexDirection: "column",
638
+
gap: "8px",
639
+
},
640
+
platformItem: {
641
+
display: "flex",
642
+
alignItems: "center",
643
+
gap: "16px",
644
+
padding: "16px",
645
+
background: "var(--atproto-color-bg-hover)",
646
+
borderRadius: 12,
647
+
textDecoration: "none",
648
+
color: "var(--atproto-color-text)",
649
+
transition: "all 0.2s ease",
650
+
cursor: "pointer",
651
+
border: "1px solid var(--atproto-color-border)",
652
+
},
653
+
platformIcon: {
654
+
fontSize: 24,
655
+
width: 32,
656
+
height: 32,
657
+
display: "flex",
658
+
alignItems: "center",
659
+
justifyContent: "center",
660
+
},
661
+
platformName: {
662
+
flex: 1,
663
+
fontSize: 16,
664
+
fontWeight: 600,
665
+
},
666
+
platformArrow: {
667
+
opacity: 0.5,
668
+
transition: "opacity 0.2s ease",
669
+
},
670
+
notListeningContainer: {
671
+
fontFamily: "system-ui, -apple-system, sans-serif",
672
+
display: "flex",
673
+
flexDirection: "column",
674
+
alignItems: "center",
675
+
justifyContent: "center",
676
+
background: "var(--atproto-color-bg)",
677
+
borderRadius: 16,
678
+
padding: "80px 40px",
679
+
maxWidth: 420,
680
+
color: "var(--atproto-color-text-secondary)",
681
+
border: "1px solid var(--atproto-color-border)",
682
+
textAlign: "center",
683
+
},
684
+
notListeningIcon: {
685
+
width: 120,
686
+
height: 120,
687
+
borderRadius: "50%",
688
+
background: "var(--atproto-color-bg-elevated)",
689
+
display: "flex",
690
+
alignItems: "center",
691
+
justifyContent: "center",
692
+
marginBottom: 24,
693
+
color: "var(--atproto-color-text-muted)",
694
+
},
695
+
notListeningTitle: {
696
+
fontSize: 18,
697
+
fontWeight: 600,
698
+
color: "var(--atproto-color-text)",
699
+
marginBottom: 8,
700
+
},
701
+
notListeningSubtitle: {
702
+
fontSize: 14,
703
+
color: "var(--atproto-color-text-secondary)",
704
+
},
705
+
};
706
+
707
+
// Add keyframes and hover styles
708
+
if (typeof document !== "undefined") {
709
+
const styleId = "teal-status-styles";
710
+
if (!document.getElementById(styleId)) {
711
+
const styleElement = document.createElement("style");
712
+
styleElement.id = styleId;
713
+
styleElement.textContent = `
714
+
@keyframes spin {
715
+
0% { transform: rotate(0deg); }
716
+
100% { transform: rotate(360deg); }
717
+
}
718
+
719
+
button[data-teal-listen-button]:hover:not(:disabled),
720
+
a[data-teal-listen-button]:hover {
721
+
background: var(--atproto-color-bg-pressed) !important;
722
+
border-color: var(--atproto-color-border-hover) !important;
723
+
transform: translateY(-2px);
724
+
}
725
+
726
+
button[data-teal-listen-button]:disabled {
727
+
opacity: 0.5;
728
+
cursor: not-allowed;
729
+
}
730
+
731
+
button[data-teal-close]:hover {
732
+
background: var(--atproto-color-bg-hover) !important;
733
+
color: var(--atproto-color-text) !important;
734
+
}
735
+
736
+
a[data-teal-platform]:hover {
737
+
background: var(--atproto-color-bg-pressed) !important;
738
+
transform: translateX(4px);
739
+
}
740
+
741
+
a[data-teal-platform]:hover svg {
742
+
opacity: 1 !important;
743
+
}
744
+
`;
745
+
document.head.appendChild(styleElement);
746
+
}
747
+
}
748
+
749
+
export default CurrentlyPlayingRenderer;
+971
lib/renderers/GrainGalleryRenderer.tsx
+971
lib/renderers/GrainGalleryRenderer.tsx
···
1
+
import React from "react";
2
+
import type { GrainGalleryRecord, GrainPhotoRecord } from "../types/grain";
3
+
import { useBlob } from "../hooks/useBlob";
4
+
import { isBlobWithCdn, extractCidFromBlob } from "../utils/blob";
5
+
6
+
export interface GrainGalleryPhoto {
7
+
record: GrainPhotoRecord;
8
+
did: string;
9
+
rkey: string;
10
+
position?: number;
11
+
}
12
+
13
+
export interface GrainGalleryRendererProps {
14
+
gallery: GrainGalleryRecord;
15
+
photos: GrainGalleryPhoto[];
16
+
loading: boolean;
17
+
error?: Error;
18
+
authorHandle?: string;
19
+
authorDisplayName?: string;
20
+
avatarUrl?: string;
21
+
}
22
+
23
+
export const GrainGalleryRenderer: React.FC<GrainGalleryRendererProps> = ({
24
+
gallery,
25
+
photos,
26
+
loading,
27
+
error,
28
+
authorDisplayName,
29
+
authorHandle,
30
+
avatarUrl,
31
+
}) => {
32
+
const [currentPage, setCurrentPage] = React.useState(0);
33
+
const [lightboxOpen, setLightboxOpen] = React.useState(false);
34
+
const [lightboxPhotoIndex, setLightboxPhotoIndex] = React.useState(0);
35
+
36
+
const createdDate = new Date(gallery.createdAt);
37
+
const created = createdDate.toLocaleString(undefined, {
38
+
dateStyle: "medium",
39
+
timeStyle: "short",
40
+
});
41
+
42
+
const primaryName = authorDisplayName || authorHandle || "โฆ";
43
+
44
+
// Memoize sorted photos to prevent re-sorting on every render
45
+
const sortedPhotos = React.useMemo(
46
+
() => [...photos].sort((a, b) => (a.position ?? 0) - (b.position ?? 0)),
47
+
[photos]
48
+
);
49
+
50
+
// Open lightbox
51
+
const openLightbox = React.useCallback((photoIndex: number) => {
52
+
setLightboxPhotoIndex(photoIndex);
53
+
setLightboxOpen(true);
54
+
}, []);
55
+
56
+
// Close lightbox
57
+
const closeLightbox = React.useCallback(() => {
58
+
setLightboxOpen(false);
59
+
}, []);
60
+
61
+
// Navigate lightbox
62
+
const goToNextPhoto = React.useCallback(() => {
63
+
setLightboxPhotoIndex((prev) => (prev + 1) % sortedPhotos.length);
64
+
}, [sortedPhotos.length]);
65
+
66
+
const goToPrevPhoto = React.useCallback(() => {
67
+
setLightboxPhotoIndex((prev) => (prev - 1 + sortedPhotos.length) % sortedPhotos.length);
68
+
}, [sortedPhotos.length]);
69
+
70
+
// Keyboard navigation
71
+
React.useEffect(() => {
72
+
if (!lightboxOpen) return;
73
+
74
+
const handleKeyDown = (e: KeyboardEvent) => {
75
+
if (e.key === "Escape") closeLightbox();
76
+
if (e.key === "ArrowLeft") goToPrevPhoto();
77
+
if (e.key === "ArrowRight") goToNextPhoto();
78
+
};
79
+
80
+
window.addEventListener("keydown", handleKeyDown);
81
+
return () => window.removeEventListener("keydown", handleKeyDown);
82
+
}, [lightboxOpen, closeLightbox, goToPrevPhoto, goToNextPhoto]);
83
+
84
+
const isSinglePhoto = sortedPhotos.length === 1;
85
+
86
+
// Preload all photos to avoid loading states when paginating
87
+
usePreloadAllPhotos(sortedPhotos);
88
+
89
+
// Reset to first page when photos change
90
+
React.useEffect(() => {
91
+
setCurrentPage(0);
92
+
}, [sortedPhotos.length]);
93
+
94
+
// Memoize pagination calculations with intelligent photo count per page
95
+
const paginationData = React.useMemo(() => {
96
+
const pages = calculatePages(sortedPhotos);
97
+
const totalPages = pages.length;
98
+
const visiblePhotos = pages[currentPage] || [];
99
+
const hasMultiplePages = totalPages > 1;
100
+
const layoutPhotos = calculateLayout(visiblePhotos);
101
+
102
+
return {
103
+
pages,
104
+
totalPages,
105
+
visiblePhotos,
106
+
hasMultiplePages,
107
+
layoutPhotos,
108
+
};
109
+
}, [sortedPhotos, currentPage]);
110
+
111
+
const { totalPages, hasMultiplePages, layoutPhotos } = paginationData;
112
+
113
+
// Memoize navigation handlers to prevent re-creation
114
+
const goToNextPage = React.useCallback(() => {
115
+
setCurrentPage((prev) => (prev + 1) % totalPages);
116
+
}, [totalPages]);
117
+
118
+
const goToPrevPage = React.useCallback(() => {
119
+
setCurrentPage((prev) => (prev - 1 + totalPages) % totalPages);
120
+
}, [totalPages]);
121
+
122
+
if (error) {
123
+
return (
124
+
<div role="alert" style={{ padding: 8, color: "crimson" }}>
125
+
Failed to load gallery.
126
+
</div>
127
+
);
128
+
}
129
+
130
+
if (loading && photos.length === 0) {
131
+
return <div role="status" aria-live="polite" style={{ padding: 8 }}>Loading galleryโฆ</div>;
132
+
}
133
+
134
+
return (
135
+
<>
136
+
{/* Hidden preload elements for all photos */}
137
+
<div style={{ display: "none" }} aria-hidden>
138
+
{sortedPhotos.map((photo) => (
139
+
<PreloadPhoto key={`${photo.did}-${photo.rkey}-preload`} photo={photo} />
140
+
))}
141
+
</div>
142
+
143
+
{/* Lightbox */}
144
+
{lightboxOpen && (
145
+
<Lightbox
146
+
photo={sortedPhotos[lightboxPhotoIndex]}
147
+
photoIndex={lightboxPhotoIndex}
148
+
totalPhotos={sortedPhotos.length}
149
+
onClose={closeLightbox}
150
+
onNext={goToNextPhoto}
151
+
onPrev={goToPrevPhoto}
152
+
/>
153
+
)}
154
+
155
+
<article style={styles.card}>
156
+
<header style={styles.header}>
157
+
{avatarUrl ? (
158
+
<img src={avatarUrl} alt={`${authorDisplayName || authorHandle || 'User'}'s profile picture`} style={styles.avatarImg} />
159
+
) : (
160
+
<div style={styles.avatarPlaceholder} aria-hidden />
161
+
)}
162
+
<div style={styles.authorInfo}>
163
+
<strong style={styles.displayName}>{primaryName}</strong>
164
+
{authorHandle && (
165
+
<span
166
+
style={{
167
+
...styles.handle,
168
+
color: `var(--atproto-color-text-secondary)`,
169
+
}}
170
+
>
171
+
@{authorHandle}
172
+
</span>
173
+
)}
174
+
</div>
175
+
</header>
176
+
177
+
<div style={styles.galleryInfo}>
178
+
<h2
179
+
style={{
180
+
...styles.title,
181
+
color: `var(--atproto-color-text)`,
182
+
}}
183
+
>
184
+
{gallery.title}
185
+
</h2>
186
+
{gallery.description && (
187
+
<p
188
+
style={{
189
+
...styles.description,
190
+
color: `var(--atproto-color-text-secondary)`,
191
+
}}
192
+
>
193
+
{gallery.description}
194
+
</p>
195
+
)}
196
+
</div>
197
+
198
+
{isSinglePhoto ? (
199
+
<div style={styles.singlePhotoContainer}>
200
+
<GalleryPhotoItem
201
+
key={`${sortedPhotos[0].did}-${sortedPhotos[0].rkey}`}
202
+
photo={sortedPhotos[0]}
203
+
isSingle={true}
204
+
onClick={() => openLightbox(0)}
205
+
/>
206
+
</div>
207
+
) : (
208
+
<div style={styles.carouselContainer}>
209
+
{hasMultiplePages && currentPage > 0 && (
210
+
<button
211
+
onClick={goToPrevPage}
212
+
onMouseEnter={(e) => (e.currentTarget.style.opacity = "1")}
213
+
onMouseLeave={(e) => (e.currentTarget.style.opacity = "0.7")}
214
+
style={{
215
+
...styles.navButton,
216
+
...styles.navButtonLeft,
217
+
color: "white",
218
+
background: "rgba(0, 0, 0, 0.5)",
219
+
boxShadow: "0 2px 4px rgba(0, 0, 0, 0.1)",
220
+
}}
221
+
aria-label="Previous photos"
222
+
>
223
+
โน
224
+
</button>
225
+
)}
226
+
<div style={styles.photosGrid}>
227
+
{layoutPhotos.map((item) => {
228
+
const photoIndex = sortedPhotos.findIndex(p => p.did === item.did && p.rkey === item.rkey);
229
+
return (
230
+
<GalleryPhotoItem
231
+
key={`${item.did}-${item.rkey}`}
232
+
photo={item}
233
+
isSingle={false}
234
+
span={item.span}
235
+
onClick={() => openLightbox(photoIndex)}
236
+
/>
237
+
);
238
+
})}
239
+
</div>
240
+
{hasMultiplePages && currentPage < totalPages - 1 && (
241
+
<button
242
+
onClick={goToNextPage}
243
+
onMouseEnter={(e) => (e.currentTarget.style.opacity = "1")}
244
+
onMouseLeave={(e) => (e.currentTarget.style.opacity = "0.7")}
245
+
style={{
246
+
...styles.navButton,
247
+
...styles.navButtonRight,
248
+
color: "white",
249
+
background: "rgba(0, 0, 0, 0.5)",
250
+
boxShadow: "0 2px 4px rgba(0, 0, 0, 0.1)",
251
+
}}
252
+
aria-label="Next photos"
253
+
>
254
+
โบ
255
+
</button>
256
+
)}
257
+
</div>
258
+
)}
259
+
260
+
<footer style={styles.footer}>
261
+
<time
262
+
style={{
263
+
...styles.time,
264
+
color: `var(--atproto-color-text-muted)`,
265
+
}}
266
+
dateTime={gallery.createdAt}
267
+
>
268
+
{created}
269
+
</time>
270
+
{hasMultiplePages && !isSinglePhoto && (
271
+
<div style={styles.paginationDots}>
272
+
{Array.from({ length: totalPages }, (_, i) => (
273
+
<button
274
+
key={i}
275
+
onClick={() => setCurrentPage(i)}
276
+
style={{
277
+
...styles.paginationDot,
278
+
background: i === currentPage
279
+
? `var(--atproto-color-text)`
280
+
: `var(--atproto-color-border)`,
281
+
}}
282
+
aria-label={`Go to page ${i + 1}`}
283
+
aria-current={i === currentPage ? "page" : undefined}
284
+
/>
285
+
))}
286
+
</div>
287
+
)}
288
+
</footer>
289
+
</article>
290
+
</>
291
+
);
292
+
};
293
+
294
+
// Component to preload a single photo's blob
295
+
const PreloadPhoto: React.FC<{ photo: GrainGalleryPhoto }> = ({ photo }) => {
296
+
const photoBlob = photo.record.photo;
297
+
const cdnUrl = isBlobWithCdn(photoBlob) ? photoBlob.cdnUrl : undefined;
298
+
const cid = cdnUrl ? undefined : extractCidFromBlob(photoBlob);
299
+
300
+
// Trigger blob loading via the hook
301
+
useBlob(photo.did, cid);
302
+
303
+
// Preload CDN images via Image element
304
+
React.useEffect(() => {
305
+
if (cdnUrl) {
306
+
const img = new Image();
307
+
img.src = cdnUrl;
308
+
}
309
+
}, [cdnUrl]);
310
+
311
+
return null;
312
+
};
313
+
314
+
// Hook to preload all photos (CDN-based)
315
+
const usePreloadAllPhotos = (photos: GrainGalleryPhoto[]) => {
316
+
React.useEffect(() => {
317
+
// Preload CDN images
318
+
photos.forEach((photo) => {
319
+
const photoBlob = photo.record.photo;
320
+
const cdnUrl = isBlobWithCdn(photoBlob) ? photoBlob.cdnUrl : undefined;
321
+
322
+
if (cdnUrl) {
323
+
const img = new Image();
324
+
img.src = cdnUrl;
325
+
}
326
+
});
327
+
}, [photos]);
328
+
};
329
+
330
+
// Calculate pages with intelligent photo count (1, 2, or 3)
331
+
// Only includes multiple photos when they fit well together
332
+
const calculatePages = (photos: GrainGalleryPhoto[]): GrainGalleryPhoto[][] => {
333
+
if (photos.length === 0) return [];
334
+
if (photos.length === 1) return [[photos[0]]];
335
+
336
+
const pages: GrainGalleryPhoto[][] = [];
337
+
let i = 0;
338
+
339
+
while (i < photos.length) {
340
+
const remaining = photos.length - i;
341
+
342
+
// Only one photo left - use it
343
+
if (remaining === 1) {
344
+
pages.push([photos[i]]);
345
+
break;
346
+
}
347
+
348
+
// Check if next 3 photos can fit well together
349
+
if (remaining >= 3) {
350
+
const nextThree = photos.slice(i, i + 3);
351
+
if (canFitThreePhotos(nextThree)) {
352
+
pages.push(nextThree);
353
+
i += 3;
354
+
continue;
355
+
}
356
+
}
357
+
358
+
// Check if next 2 photos can fit well together
359
+
if (remaining >= 2) {
360
+
const nextTwo = photos.slice(i, i + 2);
361
+
if (canFitTwoPhotos(nextTwo)) {
362
+
pages.push(nextTwo);
363
+
i += 2;
364
+
continue;
365
+
}
366
+
}
367
+
368
+
// Photos don't fit well together, use 1 per page
369
+
pages.push([photos[i]]);
370
+
i += 1;
371
+
}
372
+
373
+
return pages;
374
+
};
375
+
376
+
// Helper functions for aspect ratio classification
377
+
const isPortrait = (ratio: number) => ratio < 0.8;
378
+
const isLandscape = (ratio: number) => ratio > 1.2;
379
+
const isSquarish = (ratio: number) => ratio >= 0.8 && ratio <= 1.2;
380
+
381
+
// Determine if 2 photos can fit well together side by side
382
+
const canFitTwoPhotos = (photos: GrainGalleryPhoto[]): boolean => {
383
+
if (photos.length !== 2) return false;
384
+
385
+
const ratios = photos.map((p) => {
386
+
const ar = p.record.aspectRatio;
387
+
return ar ? ar.width / ar.height : 1;
388
+
});
389
+
390
+
const [r1, r2] = ratios;
391
+
392
+
// Two portraits side by side don't work well (too narrow)
393
+
if (isPortrait(r1) && isPortrait(r2)) return false;
394
+
395
+
// Portrait + landscape/square creates awkward layout
396
+
if (isPortrait(r1) && !isPortrait(r2)) return false;
397
+
if (!isPortrait(r1) && isPortrait(r2)) return false;
398
+
399
+
// Two landscape or two squarish photos work well
400
+
if ((isLandscape(r1) || isSquarish(r1)) && (isLandscape(r2) || isSquarish(r2))) {
401
+
return true;
402
+
}
403
+
404
+
// Default to not fitting
405
+
return false;
406
+
};
407
+
408
+
// Determine if 3 photos can fit well together in a layout
409
+
const canFitThreePhotos = (photos: GrainGalleryPhoto[]): boolean => {
410
+
if (photos.length !== 3) return false;
411
+
412
+
const ratios = photos.map((p) => {
413
+
const ar = p.record.aspectRatio;
414
+
return ar ? ar.width / ar.height : 1;
415
+
});
416
+
417
+
const [r1, r2, r3] = ratios;
418
+
419
+
// Good pattern: one portrait, two landscape/square
420
+
if (isPortrait(r1) && !isPortrait(r2) && !isPortrait(r3)) return true;
421
+
if (isPortrait(r3) && !isPortrait(r1) && !isPortrait(r2)) return true;
422
+
423
+
// Good pattern: all similar aspect ratios (all landscape or all squarish)
424
+
const allLandscape = ratios.every(isLandscape);
425
+
const allSquarish = ratios.every(isSquarish);
426
+
if (allLandscape || allSquarish) return true;
427
+
428
+
// Three portraits in a row can work
429
+
const allPortrait = ratios.every(isPortrait);
430
+
if (allPortrait) return true;
431
+
432
+
// Otherwise don't fit 3 together
433
+
return false;
434
+
};
435
+
436
+
// Layout calculator for intelligent photo grid arrangement
437
+
const calculateLayout = (photos: GrainGalleryPhoto[]) => {
438
+
if (photos.length === 0) return [];
439
+
if (photos.length === 1) {
440
+
return [{ ...photos[0], span: { row: 2, col: 2 } }];
441
+
}
442
+
443
+
const photosWithRatios = photos.map((photo) => {
444
+
const ratio = photo.record.aspectRatio
445
+
? photo.record.aspectRatio.width / photo.record.aspectRatio.height
446
+
: 1;
447
+
return {
448
+
...photo,
449
+
ratio,
450
+
isPortrait: isPortrait(ratio),
451
+
isLandscape: isLandscape(ratio)
452
+
};
453
+
});
454
+
455
+
// For 2 photos: side by side
456
+
if (photos.length === 2) {
457
+
return photosWithRatios.map((p) => ({ ...p, span: { row: 2, col: 1 } }));
458
+
}
459
+
460
+
// For 3 photos: try to create a balanced layout
461
+
if (photos.length === 3) {
462
+
const [p1, p2, p3] = photosWithRatios;
463
+
464
+
// Pattern 1: One tall on left, two stacked on right
465
+
if (p1.isPortrait && !p2.isPortrait && !p3.isPortrait) {
466
+
return [
467
+
{ ...p1, span: { row: 2, col: 1 } },
468
+
{ ...p2, span: { row: 1, col: 1 } },
469
+
{ ...p3, span: { row: 1, col: 1 } },
470
+
];
471
+
}
472
+
473
+
// Pattern 2: Two stacked on left, one tall on right
474
+
if (!p1.isPortrait && !p2.isPortrait && p3.isPortrait) {
475
+
return [
476
+
{ ...p1, span: { row: 1, col: 1 } },
477
+
{ ...p2, span: { row: 1, col: 1 } },
478
+
{ ...p3, span: { row: 2, col: 1 } },
479
+
];
480
+
}
481
+
482
+
// Pattern 3: All in a row
483
+
const allPortrait = photosWithRatios.every((p) => p.isPortrait);
484
+
if (allPortrait) {
485
+
// All portraits: display in a row with smaller cells
486
+
return photosWithRatios.map((p) => ({ ...p, span: { row: 1, col: 1 } }));
487
+
}
488
+
489
+
// Default: All three in a row
490
+
return photosWithRatios.map((p) => ({ ...p, span: { row: 1, col: 1 } }));
491
+
}
492
+
493
+
return photosWithRatios.map((p) => ({ ...p, span: { row: 1, col: 1 } }));
494
+
};
495
+
496
+
// Lightbox component for fullscreen image viewing
497
+
const Lightbox: React.FC<{
498
+
photo: GrainGalleryPhoto;
499
+
photoIndex: number;
500
+
totalPhotos: number;
501
+
onClose: () => void;
502
+
onNext: () => void;
503
+
onPrev: () => void;
504
+
}> = ({ photo, photoIndex, totalPhotos, onClose, onNext, onPrev }) => {
505
+
const photoBlob = photo.record.photo;
506
+
const cdnUrl = isBlobWithCdn(photoBlob) ? photoBlob.cdnUrl : undefined;
507
+
const cid = cdnUrl ? undefined : extractCidFromBlob(photoBlob);
508
+
const { url: urlFromBlob, loading: photoLoading, error: photoError } = useBlob(photo.did, cid);
509
+
const url = cdnUrl || urlFromBlob;
510
+
const alt = photo.record.alt?.trim() || "grain.social photo";
511
+
512
+
return (
513
+
<div
514
+
role="dialog"
515
+
aria-modal="true"
516
+
aria-label={`Photo ${photoIndex + 1} of ${totalPhotos}`}
517
+
style={{
518
+
position: "fixed",
519
+
top: 0,
520
+
left: 0,
521
+
right: 0,
522
+
bottom: 0,
523
+
background: "rgba(0, 0, 0, 0.95)",
524
+
zIndex: 9999,
525
+
display: "flex",
526
+
alignItems: "center",
527
+
justifyContent: "center",
528
+
padding: 20,
529
+
}}
530
+
onClick={onClose}
531
+
>
532
+
{/* Close button */}
533
+
<button
534
+
onClick={onClose}
535
+
style={{
536
+
position: "absolute",
537
+
top: 20,
538
+
right: 20,
539
+
width: 40,
540
+
height: 40,
541
+
border: "none",
542
+
borderRadius: "50%",
543
+
background: "rgba(255, 255, 255, 0.1)",
544
+
color: "white",
545
+
fontSize: 24,
546
+
cursor: "pointer",
547
+
display: "flex",
548
+
alignItems: "center",
549
+
justifyContent: "center",
550
+
transition: "background 200ms ease",
551
+
}}
552
+
onMouseEnter={(e) => (e.currentTarget.style.background = "rgba(255, 255, 255, 0.2)")}
553
+
onMouseLeave={(e) => (e.currentTarget.style.background = "rgba(255, 255, 255, 0.1)")}
554
+
aria-label="Close lightbox"
555
+
>
556
+
ร
557
+
</button>
558
+
559
+
{/* Previous button */}
560
+
{totalPhotos > 1 && (
561
+
<button
562
+
onClick={(e) => {
563
+
e.stopPropagation();
564
+
onPrev();
565
+
}}
566
+
style={{
567
+
position: "absolute",
568
+
left: 20,
569
+
top: "50%",
570
+
transform: "translateY(-50%)",
571
+
width: 50,
572
+
height: 50,
573
+
border: "none",
574
+
borderRadius: "50%",
575
+
background: "rgba(255, 255, 255, 0.1)",
576
+
color: "white",
577
+
fontSize: 24,
578
+
cursor: "pointer",
579
+
display: "flex",
580
+
alignItems: "center",
581
+
justifyContent: "center",
582
+
transition: "background 200ms ease",
583
+
}}
584
+
onMouseEnter={(e) => (e.currentTarget.style.background = "rgba(255, 255, 255, 0.2)")}
585
+
onMouseLeave={(e) => (e.currentTarget.style.background = "rgba(255, 255, 255, 0.1)")}
586
+
aria-label={`Previous photo (${photoIndex} of ${totalPhotos})`}
587
+
>
588
+
โน
589
+
</button>
590
+
)}
591
+
592
+
{/* Next button */}
593
+
{totalPhotos > 1 && (
594
+
<button
595
+
onClick={(e) => {
596
+
e.stopPropagation();
597
+
onNext();
598
+
}}
599
+
style={{
600
+
position: "absolute",
601
+
right: 20,
602
+
top: "50%",
603
+
transform: "translateY(-50%)",
604
+
width: 50,
605
+
height: 50,
606
+
border: "none",
607
+
borderRadius: "50%",
608
+
background: "rgba(255, 255, 255, 0.1)",
609
+
color: "white",
610
+
fontSize: 24,
611
+
cursor: "pointer",
612
+
display: "flex",
613
+
alignItems: "center",
614
+
justifyContent: "center",
615
+
transition: "background 200ms ease",
616
+
}}
617
+
onMouseEnter={(e) => (e.currentTarget.style.background = "rgba(255, 255, 255, 0.2)")}
618
+
onMouseLeave={(e) => (e.currentTarget.style.background = "rgba(255, 255, 255, 0.1)")}
619
+
aria-label={`Next photo (${photoIndex + 2} of ${totalPhotos})`}
620
+
>
621
+
โบ
622
+
</button>
623
+
)}
624
+
625
+
{/* Image */}
626
+
<div
627
+
style={{
628
+
maxWidth: "90vw",
629
+
maxHeight: "90vh",
630
+
display: "flex",
631
+
alignItems: "center",
632
+
justifyContent: "center",
633
+
}}
634
+
onClick={(e) => e.stopPropagation()}
635
+
>
636
+
{url ? (
637
+
<img
638
+
src={url}
639
+
alt={alt}
640
+
style={{
641
+
maxWidth: "100%",
642
+
maxHeight: "100%",
643
+
objectFit: "contain",
644
+
borderRadius: 8,
645
+
}}
646
+
/>
647
+
) : (
648
+
<div
649
+
style={{
650
+
color: "white",
651
+
fontSize: 16,
652
+
textAlign: "center",
653
+
}}
654
+
>
655
+
{photoLoading ? "Loadingโฆ" : photoError ? "Failed to load" : "Unavailable"}
656
+
</div>
657
+
)}
658
+
</div>
659
+
660
+
{/* Photo counter */}
661
+
{totalPhotos > 1 && (
662
+
<div
663
+
style={{
664
+
position: "absolute",
665
+
bottom: 20,
666
+
left: "50%",
667
+
transform: "translateX(-50%)",
668
+
color: "white",
669
+
fontSize: 14,
670
+
background: "rgba(0, 0, 0, 0.5)",
671
+
padding: "8px 16px",
672
+
borderRadius: 20,
673
+
}}
674
+
>
675
+
{photoIndex + 1} / {totalPhotos}
676
+
</div>
677
+
)}
678
+
</div>
679
+
);
680
+
};
681
+
682
+
const GalleryPhotoItem: React.FC<{
683
+
photo: GrainGalleryPhoto;
684
+
isSingle: boolean;
685
+
span?: { row: number; col: number };
686
+
onClick?: () => void;
687
+
}> = ({ photo, isSingle, span, onClick }) => {
688
+
const [showAltText, setShowAltText] = React.useState(false);
689
+
const photoBlob = photo.record.photo;
690
+
const cdnUrl = isBlobWithCdn(photoBlob) ? photoBlob.cdnUrl : undefined;
691
+
const cid = cdnUrl ? undefined : extractCidFromBlob(photoBlob);
692
+
const { url: urlFromBlob, loading: photoLoading, error: photoError } = useBlob(photo.did, cid);
693
+
const url = cdnUrl || urlFromBlob;
694
+
const alt = photo.record.alt?.trim() || "grain.social photo";
695
+
const hasAlt = photo.record.alt && photo.record.alt.trim().length > 0;
696
+
697
+
const aspect =
698
+
photo.record.aspectRatio && photo.record.aspectRatio.height > 0
699
+
? `${photo.record.aspectRatio.width} / ${photo.record.aspectRatio.height}`
700
+
: undefined;
701
+
702
+
const gridItemStyle = span
703
+
? {
704
+
gridRow: `span ${span.row}`,
705
+
gridColumn: `span ${span.col}`,
706
+
}
707
+
: {};
708
+
709
+
return (
710
+
<figure style={{ ...(isSingle ? styles.singlePhotoItem : styles.photoItem), ...gridItemStyle }}>
711
+
<button
712
+
onClick={onClick}
713
+
aria-label={hasAlt ? `View photo: ${alt}` : "View photo"}
714
+
style={{
715
+
...(isSingle ? styles.singlePhotoMedia : styles.photoContainer),
716
+
background: `var(--atproto-color-image-bg)`,
717
+
// Only apply aspect ratio for single photos; grid photos fill their cells
718
+
...(isSingle && aspect ? { aspectRatio: aspect } : {}),
719
+
cursor: onClick ? "pointer" : "default",
720
+
border: "none",
721
+
padding: 0,
722
+
display: "block",
723
+
width: "100%",
724
+
}}
725
+
>
726
+
{url ? (
727
+
<img src={url} alt={alt} style={isSingle ? styles.photo : styles.photoGrid} />
728
+
) : (
729
+
<div
730
+
style={{
731
+
...styles.placeholder,
732
+
color: `var(--atproto-color-text-muted)`,
733
+
}}
734
+
>
735
+
{photoLoading
736
+
? "Loadingโฆ"
737
+
: photoError
738
+
? "Failed to load"
739
+
: "Unavailable"}
740
+
</div>
741
+
)}
742
+
{hasAlt && (
743
+
<button
744
+
onClick={(e) => {
745
+
e.stopPropagation();
746
+
setShowAltText(!showAltText);
747
+
}}
748
+
style={{
749
+
...styles.altBadge,
750
+
background: showAltText
751
+
? `var(--atproto-color-text)`
752
+
: `var(--atproto-color-bg-secondary)`,
753
+
color: showAltText
754
+
? `var(--atproto-color-bg)`
755
+
: `var(--atproto-color-text)`,
756
+
}}
757
+
title="Toggle alt text"
758
+
aria-label="Toggle alt text"
759
+
aria-pressed={showAltText}
760
+
>
761
+
ALT
762
+
</button>
763
+
)}
764
+
</button>
765
+
{hasAlt && showAltText && (
766
+
<figcaption
767
+
style={{
768
+
...styles.caption,
769
+
color: `var(--atproto-color-text-secondary)`,
770
+
}}
771
+
>
772
+
{photo.record.alt}
773
+
</figcaption>
774
+
)}
775
+
</figure>
776
+
);
777
+
};
778
+
779
+
const styles: Record<string, React.CSSProperties> = {
780
+
card: {
781
+
borderRadius: 12,
782
+
border: `1px solid var(--atproto-color-border)`,
783
+
background: `var(--atproto-color-bg)`,
784
+
color: `var(--atproto-color-text)`,
785
+
fontFamily: "system-ui, sans-serif",
786
+
display: "flex",
787
+
flexDirection: "column",
788
+
maxWidth: 600,
789
+
transition:
790
+
"background-color 180ms ease, border-color 180ms ease, color 180ms ease",
791
+
overflow: "hidden",
792
+
},
793
+
header: {
794
+
display: "flex",
795
+
alignItems: "center",
796
+
gap: 12,
797
+
padding: 12,
798
+
paddingBottom: 0,
799
+
},
800
+
avatarPlaceholder: {
801
+
width: 32,
802
+
height: 32,
803
+
borderRadius: "50%",
804
+
background: `var(--atproto-color-border)`,
805
+
},
806
+
avatarImg: {
807
+
width: 32,
808
+
height: 32,
809
+
borderRadius: "50%",
810
+
objectFit: "cover",
811
+
},
812
+
authorInfo: {
813
+
display: "flex",
814
+
flexDirection: "column",
815
+
gap: 2,
816
+
},
817
+
displayName: {
818
+
fontSize: 14,
819
+
fontWeight: 600,
820
+
},
821
+
handle: {
822
+
fontSize: 12,
823
+
},
824
+
galleryInfo: {
825
+
padding: 12,
826
+
paddingBottom: 8,
827
+
},
828
+
title: {
829
+
margin: 0,
830
+
fontSize: 18,
831
+
fontWeight: 600,
832
+
marginBottom: 4,
833
+
},
834
+
description: {
835
+
margin: 0,
836
+
fontSize: 14,
837
+
lineHeight: 1.4,
838
+
whiteSpace: "pre-wrap",
839
+
},
840
+
singlePhotoContainer: {
841
+
padding: 0,
842
+
},
843
+
carouselContainer: {
844
+
position: "relative",
845
+
padding: 4,
846
+
},
847
+
photosGrid: {
848
+
display: "grid",
849
+
gridTemplateColumns: "repeat(2, 1fr)",
850
+
gridTemplateRows: "repeat(2, 1fr)",
851
+
gap: 4,
852
+
minHeight: 400,
853
+
},
854
+
navButton: {
855
+
position: "absolute",
856
+
top: "50%",
857
+
transform: "translateY(-50%)",
858
+
width: 28,
859
+
height: 28,
860
+
border: "none",
861
+
borderRadius: "50%",
862
+
fontSize: 18,
863
+
fontWeight: "600",
864
+
cursor: "pointer",
865
+
display: "flex",
866
+
alignItems: "center",
867
+
justifyContent: "center",
868
+
zIndex: 10,
869
+
transition: "opacity 150ms ease",
870
+
userSelect: "none",
871
+
opacity: 0.7,
872
+
},
873
+
navButtonLeft: {
874
+
left: 8,
875
+
},
876
+
navButtonRight: {
877
+
right: 8,
878
+
},
879
+
photoItem: {
880
+
margin: 0,
881
+
display: "flex",
882
+
flexDirection: "column",
883
+
gap: 4,
884
+
},
885
+
singlePhotoItem: {
886
+
margin: 0,
887
+
display: "flex",
888
+
flexDirection: "column",
889
+
gap: 8,
890
+
},
891
+
photoContainer: {
892
+
position: "relative",
893
+
width: "100%",
894
+
height: "100%",
895
+
overflow: "hidden",
896
+
borderRadius: 4,
897
+
},
898
+
singlePhotoMedia: {
899
+
position: "relative",
900
+
width: "100%",
901
+
overflow: "hidden",
902
+
borderRadius: 0,
903
+
},
904
+
photo: {
905
+
width: "100%",
906
+
height: "100%",
907
+
objectFit: "cover",
908
+
display: "block",
909
+
},
910
+
photoGrid: {
911
+
width: "100%",
912
+
height: "100%",
913
+
objectFit: "cover",
914
+
display: "block",
915
+
},
916
+
placeholder: {
917
+
display: "flex",
918
+
alignItems: "center",
919
+
justifyContent: "center",
920
+
width: "100%",
921
+
height: "100%",
922
+
minHeight: 100,
923
+
fontSize: 12,
924
+
},
925
+
caption: {
926
+
fontSize: 12,
927
+
lineHeight: 1.3,
928
+
padding: "0 12px 8px",
929
+
},
930
+
altBadge: {
931
+
position: "absolute",
932
+
bottom: 8,
933
+
right: 8,
934
+
padding: "4px 8px",
935
+
fontSize: 10,
936
+
fontWeight: 600,
937
+
letterSpacing: "0.5px",
938
+
border: "none",
939
+
borderRadius: 4,
940
+
cursor: "pointer",
941
+
transition: "background 150ms ease, color 150ms ease",
942
+
fontFamily: "system-ui, sans-serif",
943
+
},
944
+
footer: {
945
+
padding: 12,
946
+
paddingTop: 8,
947
+
display: "flex",
948
+
justifyContent: "space-between",
949
+
alignItems: "center",
950
+
},
951
+
time: {
952
+
fontSize: 11,
953
+
},
954
+
paginationDots: {
955
+
display: "flex",
956
+
gap: 6,
957
+
alignItems: "center",
958
+
},
959
+
paginationDot: {
960
+
width: 6,
961
+
height: 6,
962
+
borderRadius: "50%",
963
+
border: "none",
964
+
padding: 0,
965
+
cursor: "pointer",
966
+
transition: "background 200ms ease, transform 150ms ease",
967
+
flexShrink: 0,
968
+
},
969
+
};
970
+
971
+
export default GrainGalleryRenderer;
+80
-336
lib/renderers/LeafletDocumentRenderer.tsx
+80
-336
lib/renderers/LeafletDocumentRenderer.tsx
···
1
1
import React, { useMemo, useRef } from "react";
2
-
import {
3
-
useColorScheme,
4
-
type ColorSchemePreference,
5
-
} from "../hooks/useColorScheme";
6
2
import { useDidResolution } from "../hooks/useDidResolution";
7
3
import { useBlob } from "../hooks/useBlob";
4
+
import { useAtProto } from "../providers/AtProtoProvider";
8
5
import {
9
6
parseAtUri,
10
7
formatDidForLabel,
···
39
36
record: LeafletDocumentRecord;
40
37
loading: boolean;
41
38
error?: Error;
42
-
colorScheme?: ColorSchemePreference;
43
39
did: string;
44
40
rkey: string;
45
41
canonicalUrl?: string;
···
53
49
record,
54
50
loading,
55
51
error,
56
-
colorScheme = "system",
57
52
did,
58
53
rkey,
59
54
canonicalUrl,
60
55
publicationBaseUrl,
61
56
publicationRecord,
62
57
}) => {
63
-
const scheme = useColorScheme(colorScheme);
64
-
const palette = scheme === "dark" ? theme.dark : theme.light;
58
+
const { blueskyAppBaseUrl } = useAtProto();
65
59
const authorDid = record.author?.startsWith("did:")
66
60
? record.author
67
61
: undefined;
···
86
80
: undefined);
87
81
const authorLabel = resolvedPublicationLabel ?? fallbackAuthorLabel;
88
82
const authorHref = publicationUri
89
-
? `https://bsky.app/profile/${publicationUri.did}`
83
+
? `${blueskyAppBaseUrl}/profile/${publicationUri.did}`
90
84
: undefined;
91
85
92
86
if (error)
···
113
107
timeStyle: "short",
114
108
})
115
109
: undefined;
116
-
const fallbackLeafletUrl = `https://bsky.app/leaflet/${encodeURIComponent(did)}/${encodeURIComponent(rkey)}`;
110
+
const fallbackLeafletUrl = `${blueskyAppBaseUrl}/leaflet/${encodeURIComponent(did)}/${encodeURIComponent(rkey)}`;
117
111
const publicationRoot =
118
112
publicationBaseUrl ?? publicationRecord?.base_path ?? undefined;
119
113
const resolvedPublicationRoot = publicationRoot
···
125
119
publicationLeafletUrl ??
126
120
postUrl ??
127
121
(publicationUri
128
-
? `https://bsky.app/profile/${publicationUri.did}`
122
+
? `${blueskyAppBaseUrl}/profile/${publicationUri.did}`
129
123
: undefined) ??
130
124
fallbackLeafletUrl;
131
125
···
136
130
href={authorHref}
137
131
target="_blank"
138
132
rel="noopener noreferrer"
139
-
style={palette.metaLink}
133
+
style={{ color: `var(--atproto-color-link)`, textDecoration: "none" }}
140
134
>
141
135
{authorLabel}
142
136
</a>
···
155
149
href={resolvedPublicationRoot}
156
150
target="_blank"
157
151
rel="noopener noreferrer"
158
-
style={palette.metaLink}
152
+
style={{ color: `var(--atproto-color-link)`, textDecoration: "none" }}
159
153
>
160
154
{resolvedPublicationRoot.replace(/^https?:\/\//, "")}
161
155
</a>,
···
167
161
href={viewUrl}
168
162
target="_blank"
169
163
rel="noopener noreferrer"
170
-
style={palette.metaLink}
164
+
style={{ color: `var(--atproto-color-link)`, textDecoration: "none" }}
171
165
>
172
166
View source
173
167
</a>,
···
175
169
}
176
170
177
171
return (
178
-
<article style={{ ...base.container, ...palette.container }}>
179
-
<header style={{ ...base.header, ...palette.header }}>
172
+
<article style={{ ...base.container, background: `var(--atproto-color-bg)`, borderWidth: "1px", borderStyle: "solid", borderColor: `var(--atproto-color-border)`, color: `var(--atproto-color-text)` }}>
173
+
<header style={{ ...base.header }}>
180
174
<div style={base.headerContent}>
181
-
<h1 style={{ ...base.title, ...palette.title }}>
175
+
<h1 style={{ ...base.title, color: `var(--atproto-color-text)` }}>
182
176
{record.title}
183
177
</h1>
184
178
{record.description && (
185
-
<p style={{ ...base.subtitle, ...palette.subtitle }}>
179
+
<p style={{ ...base.subtitle, color: `var(--atproto-color-text-secondary)` }}>
186
180
{record.description}
187
181
</p>
188
182
)}
189
183
</div>
190
-
<div style={{ ...base.meta, ...palette.meta }}>
184
+
<div style={{ ...base.meta, color: `var(--atproto-color-text-secondary)` }}>
191
185
{metaItems.map((item, idx) => (
192
186
<React.Fragment key={`meta-${idx}`}>
193
187
{idx > 0 && (
194
-
<span style={palette.metaSeparator}>โข</span>
188
+
<span style={{ margin: "0 4px" }}>โข</span>
195
189
)}
196
190
{item}
197
191
</React.Fragment>
···
204
198
key={`page-${pageIndex}`}
205
199
page={page}
206
200
documentDid={did}
207
-
colorScheme={scheme}
208
201
/>
209
202
))}
210
203
</div>
···
215
208
const LeafletPageRenderer: React.FC<{
216
209
page: LeafletLinearDocumentPage;
217
210
documentDid: string;
218
-
colorScheme: "light" | "dark";
219
-
}> = ({ page, documentDid, colorScheme }) => {
211
+
}> = ({ page, documentDid }) => {
220
212
if (!page.blocks?.length) return null;
221
213
return (
222
214
<div style={base.page}>
···
225
217
key={`block-${idx}`}
226
218
wrapper={blockWrapper}
227
219
documentDid={documentDid}
228
-
colorScheme={colorScheme}
229
220
isFirst={idx === 0}
230
221
/>
231
222
))}
···
236
227
interface LeafletBlockRendererProps {
237
228
wrapper: LeafletLinearDocumentBlock;
238
229
documentDid: string;
239
-
colorScheme: "light" | "dark";
240
230
isFirst?: boolean;
241
231
}
242
232
243
233
const LeafletBlockRenderer: React.FC<LeafletBlockRendererProps> = ({
244
234
wrapper,
245
235
documentDid,
246
-
colorScheme,
247
236
isFirst,
248
237
}) => {
249
238
const block = wrapper.block;
···
258
247
<LeafletHeaderBlockView
259
248
block={block}
260
249
alignment={alignment}
261
-
colorScheme={colorScheme}
262
250
isFirst={isFirst}
263
251
/>
264
252
);
···
267
255
<LeafletBlockquoteBlockView
268
256
block={block}
269
257
alignment={alignment}
270
-
colorScheme={colorScheme}
271
258
isFirst={isFirst}
272
259
/>
273
260
);
···
277
264
block={block}
278
265
alignment={alignment}
279
266
documentDid={documentDid}
280
-
colorScheme={colorScheme}
281
267
/>
282
268
);
283
269
case "pub.leaflet.blocks.unorderedList":
···
286
272
block={block}
287
273
alignment={alignment}
288
274
documentDid={documentDid}
289
-
colorScheme={colorScheme}
290
275
/>
291
276
);
292
277
case "pub.leaflet.blocks.website":
···
295
280
block={block}
296
281
alignment={alignment}
297
282
documentDid={documentDid}
298
-
colorScheme={colorScheme}
299
283
/>
300
284
);
301
285
case "pub.leaflet.blocks.iframe":
···
307
291
<LeafletMathBlockView
308
292
block={block}
309
293
alignment={alignment}
310
-
colorScheme={colorScheme}
311
294
/>
312
295
);
313
296
case "pub.leaflet.blocks.code":
···
315
298
<LeafletCodeBlockView
316
299
block={block}
317
300
alignment={alignment}
318
-
colorScheme={colorScheme}
319
301
/>
320
302
);
321
303
case "pub.leaflet.blocks.horizontalRule":
322
304
return (
323
305
<LeafletHorizontalRuleBlockView
324
306
alignment={alignment}
325
-
colorScheme={colorScheme}
326
307
/>
327
308
);
328
309
case "pub.leaflet.blocks.bskyPost":
329
310
return (
330
311
<LeafletBskyPostBlockView
331
312
block={block}
332
-
colorScheme={colorScheme}
333
313
/>
334
314
);
335
315
case "pub.leaflet.blocks.text":
···
338
318
<LeafletTextBlockView
339
319
block={block as LeafletTextBlock}
340
320
alignment={alignment}
341
-
colorScheme={colorScheme}
342
321
isFirst={isFirst}
343
322
/>
344
323
);
···
348
327
const LeafletTextBlockView: React.FC<{
349
328
block: LeafletTextBlock;
350
329
alignment?: React.CSSProperties["textAlign"];
351
-
colorScheme: "light" | "dark";
352
330
isFirst?: boolean;
353
-
}> = ({ block, alignment, colorScheme, isFirst }) => {
331
+
}> = ({ block, alignment, isFirst }) => {
354
332
const segments = useMemo(
355
333
() => createFacetedSegments(block.plaintext, block.facets),
356
334
[block.plaintext, block.facets],
···
359
337
if (!textContent.trim() && segments.length === 0) {
360
338
return null;
361
339
}
362
-
const palette = colorScheme === "dark" ? theme.dark : theme.light;
363
340
const style: React.CSSProperties = {
364
341
...base.paragraph,
365
-
...palette.paragraph,
342
+
color: `var(--atproto-color-text)`,
366
343
...(alignment ? { textAlign: alignment } : undefined),
367
344
...(isFirst ? { marginTop: 0 } : undefined),
368
345
};
···
370
347
<p style={style}>
371
348
{segments.map((segment, idx) => (
372
349
<React.Fragment key={`text-${idx}`}>
373
-
{renderSegment(segment, colorScheme)}
350
+
{renderSegment(segment)}
374
351
</React.Fragment>
375
352
))}
376
353
</p>
···
380
357
const LeafletHeaderBlockView: React.FC<{
381
358
block: LeafletHeaderBlock;
382
359
alignment?: React.CSSProperties["textAlign"];
383
-
colorScheme: "light" | "dark";
384
360
isFirst?: boolean;
385
-
}> = ({ block, alignment, colorScheme, isFirst }) => {
386
-
const palette = colorScheme === "dark" ? theme.dark : theme.light;
361
+
}> = ({ block, alignment, isFirst }) => {
387
362
const level =
388
363
block.level && block.level >= 1 && block.level <= 6 ? block.level : 2;
389
364
const segments = useMemo(
···
400
375
const headingTag = (["h1", "h2", "h3", "h4", "h5", "h6"] as const)[
401
376
normalizedLevel - 1
402
377
];
403
-
const headingStyles = palette.heading[normalizedLevel];
404
378
const style: React.CSSProperties = {
405
379
...base.heading,
406
-
...headingStyles,
380
+
color: `var(--atproto-color-text)`,
381
+
fontSize: normalizedLevel === 1 ? 30 : normalizedLevel === 2 ? 28 : normalizedLevel === 3 ? 24 : normalizedLevel === 4 ? 20 : normalizedLevel === 5 ? 18 : 16,
407
382
...(alignment ? { textAlign: alignment } : undefined),
408
383
...(isFirst ? { marginTop: 0 } : undefined),
409
384
};
···
413
388
{ style },
414
389
segments.map((segment, idx) => (
415
390
<React.Fragment key={`header-${idx}`}>
416
-
{renderSegment(segment, colorScheme)}
391
+
{renderSegment(segment)}
417
392
</React.Fragment>
418
393
)),
419
394
);
···
422
397
const LeafletBlockquoteBlockView: React.FC<{
423
398
block: LeafletBlockquoteBlock;
424
399
alignment?: React.CSSProperties["textAlign"];
425
-
colorScheme: "light" | "dark";
426
400
isFirst?: boolean;
427
-
}> = ({ block, alignment, colorScheme, isFirst }) => {
401
+
}> = ({ block, alignment, isFirst }) => {
428
402
const segments = useMemo(
429
403
() => createFacetedSegments(block.plaintext, block.facets),
430
404
[block.plaintext, block.facets],
···
433
407
if (!textContent.trim() && segments.length === 0) {
434
408
return null;
435
409
}
436
-
const palette = colorScheme === "dark" ? theme.dark : theme.light;
437
410
return (
438
411
<blockquote
439
412
style={{
440
413
...base.blockquote,
441
-
...palette.blockquote,
414
+
background: `var(--atproto-color-bg-elevated)`,
415
+
borderLeftWidth: "4px",
416
+
borderLeftStyle: "solid",
417
+
borderColor: `var(--atproto-color-border)`,
418
+
color: `var(--atproto-color-text)`,
442
419
...(alignment ? { textAlign: alignment } : undefined),
443
420
...(isFirst ? { marginTop: 0 } : undefined),
444
421
}}
445
422
>
446
423
{segments.map((segment, idx) => (
447
424
<React.Fragment key={`quote-${idx}`}>
448
-
{renderSegment(segment, colorScheme)}
425
+
{renderSegment(segment)}
449
426
</React.Fragment>
450
427
))}
451
428
</blockquote>
···
456
433
block: LeafletImageBlock;
457
434
alignment?: React.CSSProperties["textAlign"];
458
435
documentDid: string;
459
-
colorScheme: "light" | "dark";
460
-
}> = ({ block, alignment, documentDid, colorScheme }) => {
461
-
const palette = colorScheme === "dark" ? theme.dark : theme.light;
436
+
}> = ({ block, alignment, documentDid }) => {
462
437
const cid = block.image?.ref?.$link ?? block.image?.cid;
463
438
const { url, loading, error } = useBlob(documentDid, cid);
464
439
const aspectRatio =
···
470
445
<figure
471
446
style={{
472
447
...base.figure,
473
-
...palette.figure,
474
448
...(alignment ? { textAlign: alignment } : undefined),
475
449
}}
476
450
>
477
451
<div
478
452
style={{
479
453
...base.imageWrapper,
480
-
...palette.imageWrapper,
454
+
background: `var(--atproto-color-bg-elevated)`,
481
455
...(aspectRatio ? { aspectRatio } : {}),
482
456
}}
483
457
>
···
485
459
<img
486
460
src={url}
487
461
alt={block.alt ?? ""}
488
-
style={{ ...base.image, ...palette.image }}
462
+
style={{ ...base.image }}
489
463
/>
490
464
) : (
491
465
<div
492
466
style={{
493
467
...base.imagePlaceholder,
494
-
...palette.imagePlaceholder,
468
+
color: `var(--atproto-color-text-secondary)`,
495
469
}}
496
470
>
497
471
{loading
···
503
477
)}
504
478
</div>
505
479
{block.alt && block.alt.trim().length > 0 && (
506
-
<figcaption style={{ ...base.caption, ...palette.caption }}>
480
+
<figcaption style={{ ...base.caption, color: `var(--atproto-color-text-secondary)` }}>
507
481
{block.alt}
508
482
</figcaption>
509
483
)}
···
515
489
block: LeafletUnorderedListBlock;
516
490
alignment?: React.CSSProperties["textAlign"];
517
491
documentDid: string;
518
-
colorScheme: "light" | "dark";
519
-
}> = ({ block, alignment, documentDid, colorScheme }) => {
520
-
const palette = colorScheme === "dark" ? theme.dark : theme.light;
492
+
}> = ({ block, alignment, documentDid }) => {
521
493
return (
522
494
<ul
523
495
style={{
524
496
...base.list,
525
-
...palette.list,
497
+
color: `var(--atproto-color-text)`,
526
498
...(alignment ? { textAlign: alignment } : undefined),
527
499
}}
528
500
>
···
531
503
key={`list-item-${idx}`}
532
504
item={child}
533
505
documentDid={documentDid}
534
-
colorScheme={colorScheme}
535
506
alignment={alignment}
536
507
/>
537
508
))}
···
542
513
const LeafletListItemRenderer: React.FC<{
543
514
item: LeafletListItem;
544
515
documentDid: string;
545
-
colorScheme: "light" | "dark";
546
516
alignment?: React.CSSProperties["textAlign"];
547
-
}> = ({ item, documentDid, colorScheme, alignment }) => {
517
+
}> = ({ item, documentDid, alignment }) => {
548
518
return (
549
519
<li
550
520
style={{
···
555
525
<div>
556
526
<LeafletInlineBlock
557
527
block={item.content}
558
-
colorScheme={colorScheme}
559
528
documentDid={documentDid}
560
529
alignment={alignment}
561
530
/>
···
572
541
key={`nested-${idx}`}
573
542
item={child}
574
543
documentDid={documentDid}
575
-
colorScheme={colorScheme}
576
544
alignment={alignment}
577
545
/>
578
546
))}
···
584
552
585
553
const LeafletInlineBlock: React.FC<{
586
554
block: LeafletBlock;
587
-
colorScheme: "light" | "dark";
588
555
documentDid: string;
589
556
alignment?: React.CSSProperties["textAlign"];
590
-
}> = ({ block, colorScheme, documentDid, alignment }) => {
557
+
}> = ({ block, documentDid, alignment }) => {
591
558
switch (block.$type) {
592
559
case "pub.leaflet.blocks.header":
593
560
return (
594
561
<LeafletHeaderBlockView
595
562
block={block as LeafletHeaderBlock}
596
-
colorScheme={colorScheme}
597
563
alignment={alignment}
598
564
/>
599
565
);
···
601
567
return (
602
568
<LeafletBlockquoteBlockView
603
569
block={block as LeafletBlockquoteBlock}
604
-
colorScheme={colorScheme}
605
570
alignment={alignment}
606
571
/>
607
572
);
···
610
575
<LeafletImageBlockView
611
576
block={block as LeafletImageBlock}
612
577
documentDid={documentDid}
613
-
colorScheme={colorScheme}
614
578
alignment={alignment}
615
579
/>
616
580
);
···
618
582
return (
619
583
<LeafletTextBlockView
620
584
block={block as LeafletTextBlock}
621
-
colorScheme={colorScheme}
622
585
alignment={alignment}
623
586
/>
624
587
);
···
629
592
block: LeafletWebsiteBlock;
630
593
alignment?: React.CSSProperties["textAlign"];
631
594
documentDid: string;
632
-
colorScheme: "light" | "dark";
633
-
}> = ({ block, alignment, documentDid, colorScheme }) => {
634
-
const palette = colorScheme === "dark" ? theme.dark : theme.light;
595
+
}> = ({ block, alignment, documentDid }) => {
635
596
const previewCid =
636
597
block.previewImage?.ref?.$link ?? block.previewImage?.cid;
637
598
const { url, loading, error } = useBlob(documentDid, previewCid);
···
643
604
rel="noopener noreferrer"
644
605
style={{
645
606
...base.linkCard,
646
-
...palette.linkCard,
607
+
borderWidth: "1px",
608
+
borderStyle: "solid",
609
+
borderColor: `var(--atproto-color-border)`,
610
+
background: `var(--atproto-color-bg-elevated)`,
611
+
color: `var(--atproto-color-text)`,
647
612
...(alignment ? { textAlign: alignment } : undefined),
648
613
}}
649
614
>
···
651
616
<img
652
617
src={url}
653
618
alt={block.title ?? "Website preview"}
654
-
style={{ ...base.linkPreview, ...palette.linkPreview }}
619
+
style={{ ...base.linkPreview }}
655
620
/>
656
621
) : (
657
622
<div
658
623
style={{
659
624
...base.linkPreviewPlaceholder,
660
-
...palette.linkPreviewPlaceholder,
625
+
background: `var(--atproto-color-bg-elevated)`,
626
+
color: `var(--atproto-color-text-secondary)`,
661
627
}}
662
628
>
663
629
{loading ? "Loading previewโฆ" : "Open link"}
···
665
631
)}
666
632
<div style={base.linkContent}>
667
633
{block.title && (
668
-
<strong style={palette.linkTitle}>{block.title}</strong>
634
+
<strong style={{ fontSize: 16, color: `var(--atproto-color-text)` }}>{block.title}</strong>
669
635
)}
670
636
{block.description && (
671
-
<p style={palette.linkDescription}>{block.description}</p>
637
+
<p style={{ margin: 0, fontSize: 14, color: `var(--atproto-color-text-secondary)`, lineHeight: 1.5 }}>{block.description}</p>
672
638
)}
673
-
<span style={palette.linkUrl}>{block.src}</span>
639
+
<span style={{ fontSize: 13, color: `var(--atproto-color-link)`, wordBreak: "break-all" }}>{block.src}</span>
674
640
</div>
675
641
</a>
676
642
);
···
701
667
const LeafletMathBlockView: React.FC<{
702
668
block: LeafletMathBlock;
703
669
alignment?: React.CSSProperties["textAlign"];
704
-
colorScheme: "light" | "dark";
705
-
}> = ({ block, alignment, colorScheme }) => {
706
-
const palette = colorScheme === "dark" ? theme.dark : theme.light;
670
+
}> = ({ block, alignment }) => {
707
671
return (
708
672
<pre
709
673
style={{
710
674
...base.math,
711
-
...palette.math,
675
+
background: `var(--atproto-color-bg-elevated)`,
676
+
color: `var(--atproto-color-text)`,
677
+
border: `1px solid var(--atproto-color-border)`,
712
678
...(alignment ? { textAlign: alignment } : undefined),
713
679
}}
714
680
>
···
720
686
const LeafletCodeBlockView: React.FC<{
721
687
block: LeafletCodeBlock;
722
688
alignment?: React.CSSProperties["textAlign"];
723
-
colorScheme: "light" | "dark";
724
-
}> = ({ block, alignment, colorScheme }) => {
725
-
const palette = colorScheme === "dark" ? theme.dark : theme.light;
689
+
}> = ({ block, alignment }) => {
726
690
const codeRef = useRef<HTMLElement | null>(null);
727
691
const langClass = block.language
728
692
? `language-${block.language.toLowerCase()}`
···
731
695
<pre
732
696
style={{
733
697
...base.code,
734
-
...palette.code,
698
+
background: `var(--atproto-color-bg)`,
699
+
color: `var(--atproto-color-text)`,
735
700
...(alignment ? { textAlign: alignment } : undefined),
736
701
}}
737
702
>
···
744
709
745
710
const LeafletHorizontalRuleBlockView: React.FC<{
746
711
alignment?: React.CSSProperties["textAlign"];
747
-
colorScheme: "light" | "dark";
748
-
}> = ({ alignment, colorScheme }) => {
749
-
const palette = colorScheme === "dark" ? theme.dark : theme.light;
712
+
}> = ({ alignment }) => {
750
713
return (
751
714
<hr
752
715
style={{
753
716
...base.hr,
754
-
...palette.hr,
717
+
borderTopWidth: "1px",
718
+
borderTopStyle: "solid",
719
+
borderColor: `var(--atproto-color-border)`,
755
720
marginLeft: alignment ? "auto" : undefined,
756
721
marginRight: alignment ? "auto" : undefined,
757
722
}}
···
761
726
762
727
const LeafletBskyPostBlockView: React.FC<{
763
728
block: LeafletBskyPostBlock;
764
-
colorScheme: "light" | "dark";
765
-
}> = ({ block, colorScheme }) => {
729
+
}> = ({ block }) => {
766
730
const parsed = parseAtUri(block.postRef?.uri);
767
731
if (!parsed) {
768
732
return (
···
773
737
<BlueskyPost
774
738
did={parsed.did}
775
739
rkey={parsed.rkey}
776
-
colorScheme={colorScheme}
777
740
iconPlacement="linkInline"
778
741
/>
779
742
);
···
855
818
]);
856
819
}
857
820
}
858
-
const sortedBounds = [...boundaries].sort((a, b) => a - b);
821
+
const sortedBounds = Array.from(boundaries).sort((a, b) => a - b);
859
822
const segments: Segment[] = [];
860
823
let active: LeafletRichTextFeature[] = [];
861
824
for (let i = 0; i < sortedBounds.length - 1; i++) {
···
915
878
916
879
function renderSegment(
917
880
segment: Segment,
918
-
colorScheme: "light" | "dark",
919
881
): React.ReactNode {
920
882
const parts = segment.text.split("\n");
921
883
return parts.flatMap((part, idx) => {
···
924
886
part.length ? part : "\u00a0",
925
887
segment.features,
926
888
key,
927
-
colorScheme,
928
889
);
929
890
if (idx === parts.length - 1) return wrapped;
930
891
return [wrapped, <br key={`${key}-br`} />];
···
935
896
content: React.ReactNode,
936
897
features: LeafletRichTextFeature[],
937
898
key: string,
938
-
colorScheme: "light" | "dark",
939
899
): React.ReactNode {
940
900
if (!features?.length)
941
901
return <React.Fragment key={key}>{content}</React.Fragment>;
···
947
907
child,
948
908
feature,
949
909
`${key}-feature-${idx}`,
950
-
colorScheme,
951
910
),
952
911
content,
953
912
)}
···
959
918
child: React.ReactNode,
960
919
feature: LeafletRichTextFeature,
961
920
key: string,
962
-
colorScheme: "light" | "dark",
963
921
): React.ReactNode {
964
922
switch (feature.$type) {
965
923
case "pub.leaflet.richtext.facet#link":
···
969
927
href={feature.uri}
970
928
target="_blank"
971
929
rel="noopener noreferrer"
972
-
style={linkStyles[colorScheme]}
930
+
style={{ color: `var(--atproto-color-link)`, textDecoration: "underline" }}
973
931
>
974
932
{child}
975
933
</a>
976
934
);
977
935
case "pub.leaflet.richtext.facet#code":
978
936
return (
979
-
<code key={key} style={inlineCodeStyles[colorScheme]}>
937
+
<code key={key} style={{
938
+
fontFamily: 'Menlo, Consolas, "SFMono-Regular", ui-monospace',
939
+
background: `var(--atproto-color-bg-elevated)`,
940
+
padding: "0 4px",
941
+
borderRadius: 4,
942
+
}}>
980
943
{child}
981
944
</code>
982
945
);
983
946
case "pub.leaflet.richtext.facet#highlight":
984
947
return (
985
-
<mark key={key} style={highlightStyles[colorScheme]}>
948
+
<mark key={key} style={{ background: `var(--atproto-color-highlight)` }}>
986
949
{child}
987
950
</mark>
988
951
);
···
1020
983
gap: 24,
1021
984
padding: "24px 28px",
1022
985
borderRadius: 20,
1023
-
border: "1px solid transparent",
986
+
borderWidth: "1px",
987
+
borderStyle: "solid",
988
+
borderColor: "transparent",
1024
989
maxWidth: 720,
1025
990
width: "100%",
1026
991
fontFamily:
···
1075
1040
blockquote: {
1076
1041
margin: "1em 0 0",
1077
1042
padding: "0.6em 1em",
1078
-
borderLeft: "4px solid",
1043
+
borderLeftWidth: "4px",
1044
+
borderLeftStyle: "solid",
1079
1045
},
1080
1046
figure: {
1081
1047
margin: "1.2em 0 0",
···
1123
1089
},
1124
1090
linkCard: {
1125
1091
borderRadius: 16,
1126
-
border: "1px solid",
1092
+
borderWidth: "1px",
1093
+
borderStyle: "solid",
1127
1094
display: "flex",
1128
1095
flexDirection: "column",
1129
1096
overflow: "hidden",
···
1170
1137
},
1171
1138
hr: {
1172
1139
border: 0,
1173
-
borderTop: "1px solid",
1140
+
borderTopWidth: "1px",
1141
+
borderTopStyle: "solid",
1174
1142
margin: "24px 0 0",
1175
1143
},
1176
1144
embedFallback: {
···
1180
1148
fontSize: 14,
1181
1149
},
1182
1150
};
1183
-
1184
-
const theme = {
1185
-
light: {
1186
-
container: {
1187
-
background: "#ffffff",
1188
-
borderColor: "#e2e8f0",
1189
-
color: "#0f172a",
1190
-
boxShadow: "0 4px 18px rgba(15, 23, 42, 0.06)",
1191
-
},
1192
-
header: {},
1193
-
title: {
1194
-
color: "#0f172a",
1195
-
},
1196
-
subtitle: {
1197
-
color: "#475569",
1198
-
},
1199
-
meta: {
1200
-
color: "#64748b",
1201
-
},
1202
-
metaLink: {
1203
-
color: "#2563eb",
1204
-
textDecoration: "none",
1205
-
} satisfies React.CSSProperties,
1206
-
metaSeparator: {
1207
-
margin: "0 4px",
1208
-
} satisfies React.CSSProperties,
1209
-
paragraph: {
1210
-
color: "#1f2937",
1211
-
},
1212
-
heading: {
1213
-
1: { color: "#0f172a", fontSize: 30 },
1214
-
2: { color: "#0f172a", fontSize: 28 },
1215
-
3: { color: "#0f172a", fontSize: 24 },
1216
-
4: { color: "#0f172a", fontSize: 20 },
1217
-
5: { color: "#0f172a", fontSize: 18 },
1218
-
6: { color: "#0f172a", fontSize: 16 },
1219
-
} satisfies Record<number, React.CSSProperties>,
1220
-
blockquote: {
1221
-
background: "#f8fafc",
1222
-
borderColor: "#cbd5f5",
1223
-
color: "#1f2937",
1224
-
},
1225
-
figure: {},
1226
-
imageWrapper: {
1227
-
background: "#e2e8f0",
1228
-
},
1229
-
image: {},
1230
-
imagePlaceholder: {
1231
-
color: "#475569",
1232
-
},
1233
-
caption: {
1234
-
color: "#475569",
1235
-
},
1236
-
list: {
1237
-
color: "#1f2937",
1238
-
},
1239
-
linkCard: {
1240
-
borderColor: "#e2e8f0",
1241
-
background: "#f8fafc",
1242
-
color: "#0f172a",
1243
-
},
1244
-
linkPreview: {},
1245
-
linkPreviewPlaceholder: {
1246
-
background: "#e2e8f0",
1247
-
color: "#475569",
1248
-
},
1249
-
linkTitle: {
1250
-
fontSize: 16,
1251
-
color: "#0f172a",
1252
-
} satisfies React.CSSProperties,
1253
-
linkDescription: {
1254
-
margin: 0,
1255
-
fontSize: 14,
1256
-
color: "#475569",
1257
-
lineHeight: 1.5,
1258
-
} satisfies React.CSSProperties,
1259
-
linkUrl: {
1260
-
fontSize: 13,
1261
-
color: "#2563eb",
1262
-
wordBreak: "break-all",
1263
-
} satisfies React.CSSProperties,
1264
-
math: {
1265
-
background: "#f1f5f9",
1266
-
color: "#1f2937",
1267
-
border: "1px solid #e2e8f0",
1268
-
},
1269
-
code: {
1270
-
background: "#0f172a",
1271
-
color: "#e2e8f0",
1272
-
},
1273
-
hr: {
1274
-
borderColor: "#e2e8f0",
1275
-
},
1276
-
},
1277
-
dark: {
1278
-
container: {
1279
-
background: "rgba(15, 23, 42, 0.6)",
1280
-
borderColor: "rgba(148, 163, 184, 0.3)",
1281
-
color: "#e2e8f0",
1282
-
backdropFilter: "blur(8px)",
1283
-
boxShadow: "0 10px 40px rgba(2, 6, 23, 0.45)",
1284
-
},
1285
-
header: {},
1286
-
title: {
1287
-
color: "#f8fafc",
1288
-
},
1289
-
subtitle: {
1290
-
color: "#cbd5f5",
1291
-
},
1292
-
meta: {
1293
-
color: "#94a3b8",
1294
-
},
1295
-
metaLink: {
1296
-
color: "#38bdf8",
1297
-
textDecoration: "none",
1298
-
} satisfies React.CSSProperties,
1299
-
metaSeparator: {
1300
-
margin: "0 4px",
1301
-
} satisfies React.CSSProperties,
1302
-
paragraph: {
1303
-
color: "#e2e8f0",
1304
-
},
1305
-
heading: {
1306
-
1: { color: "#f8fafc", fontSize: 30 },
1307
-
2: { color: "#f8fafc", fontSize: 28 },
1308
-
3: { color: "#f8fafc", fontSize: 24 },
1309
-
4: { color: "#e2e8f0", fontSize: 20 },
1310
-
5: { color: "#e2e8f0", fontSize: 18 },
1311
-
6: { color: "#e2e8f0", fontSize: 16 },
1312
-
} satisfies Record<number, React.CSSProperties>,
1313
-
blockquote: {
1314
-
background: "rgba(30, 41, 59, 0.6)",
1315
-
borderColor: "#38bdf8",
1316
-
color: "#e2e8f0",
1317
-
},
1318
-
figure: {},
1319
-
imageWrapper: {
1320
-
background: "#1e293b",
1321
-
},
1322
-
image: {},
1323
-
imagePlaceholder: {
1324
-
color: "#94a3b8",
1325
-
},
1326
-
caption: {
1327
-
color: "#94a3b8",
1328
-
},
1329
-
list: {
1330
-
color: "#f1f5f9",
1331
-
},
1332
-
linkCard: {
1333
-
borderColor: "rgba(148, 163, 184, 0.3)",
1334
-
background: "rgba(15, 23, 42, 0.8)",
1335
-
color: "#e2e8f0",
1336
-
},
1337
-
linkPreview: {},
1338
-
linkPreviewPlaceholder: {
1339
-
background: "#1e293b",
1340
-
color: "#94a3b8",
1341
-
},
1342
-
linkTitle: {
1343
-
fontSize: 16,
1344
-
color: "#e0f2fe",
1345
-
} satisfies React.CSSProperties,
1346
-
linkDescription: {
1347
-
margin: 0,
1348
-
fontSize: 14,
1349
-
color: "#cbd5f5",
1350
-
lineHeight: 1.5,
1351
-
} satisfies React.CSSProperties,
1352
-
linkUrl: {
1353
-
fontSize: 13,
1354
-
color: "#38bdf8",
1355
-
wordBreak: "break-all",
1356
-
} satisfies React.CSSProperties,
1357
-
math: {
1358
-
background: "rgba(15, 23, 42, 0.8)",
1359
-
color: "#e2e8f0",
1360
-
border: "1px solid rgba(148, 163, 184, 0.35)",
1361
-
},
1362
-
code: {
1363
-
background: "#020617",
1364
-
color: "#e2e8f0",
1365
-
},
1366
-
hr: {
1367
-
borderColor: "rgba(148, 163, 184, 0.3)",
1368
-
},
1369
-
},
1370
-
} as const;
1371
-
1372
-
const linkStyles = {
1373
-
light: {
1374
-
color: "#2563eb",
1375
-
textDecoration: "underline",
1376
-
} satisfies React.CSSProperties,
1377
-
dark: {
1378
-
color: "#38bdf8",
1379
-
textDecoration: "underline",
1380
-
} satisfies React.CSSProperties,
1381
-
} as const;
1382
-
1383
-
const inlineCodeStyles = {
1384
-
light: {
1385
-
fontFamily: 'Menlo, Consolas, "SFMono-Regular", ui-monospace',
1386
-
background: "#f1f5f9",
1387
-
padding: "0 4px",
1388
-
borderRadius: 4,
1389
-
} satisfies React.CSSProperties,
1390
-
dark: {
1391
-
fontFamily: 'Menlo, Consolas, "SFMono-Regular", ui-monospace',
1392
-
background: "#1e293b",
1393
-
padding: "0 4px",
1394
-
borderRadius: 4,
1395
-
} satisfies React.CSSProperties,
1396
-
} as const;
1397
-
1398
-
const highlightStyles = {
1399
-
light: {
1400
-
background: "#fef08a",
1401
-
} satisfies React.CSSProperties,
1402
-
dark: {
1403
-
background: "#facc15",
1404
-
color: "#0f172a",
1405
-
} satisfies React.CSSProperties,
1406
-
} as const;
1407
1151
1408
1152
export default LeafletDocumentRenderer;
+330
lib/renderers/TangledRepoRenderer.tsx
+330
lib/renderers/TangledRepoRenderer.tsx
···
1
+
import React from "react";
2
+
import type { TangledRepoRecord } from "../types/tangled";
3
+
import { useAtProto } from "../providers/AtProtoProvider";
4
+
import { useBacklinks } from "../hooks/useBacklinks";
5
+
import { useRepoLanguages } from "../hooks/useRepoLanguages";
6
+
7
+
export interface TangledRepoRendererProps {
8
+
record: TangledRepoRecord;
9
+
error?: Error;
10
+
loading: boolean;
11
+
did: string;
12
+
rkey: string;
13
+
canonicalUrl?: string;
14
+
showStarCount?: boolean;
15
+
branch?: string;
16
+
languages?: string[];
17
+
}
18
+
19
+
export const TangledRepoRenderer: React.FC<TangledRepoRendererProps> = ({
20
+
record,
21
+
error,
22
+
loading,
23
+
did,
24
+
rkey,
25
+
canonicalUrl,
26
+
showStarCount = true,
27
+
branch,
28
+
languages,
29
+
}) => {
30
+
const { tangledBaseUrl, constellationBaseUrl } = useAtProto();
31
+
32
+
// Construct the AT-URI for this repo record
33
+
const atUri = `at://${did}/sh.tangled.repo/${rkey}`;
34
+
35
+
// Fetch star backlinks
36
+
const {
37
+
count: starCount,
38
+
loading: starsLoading,
39
+
error: starsError,
40
+
} = useBacklinks({
41
+
subject: atUri,
42
+
source: "sh.tangled.feed.star:subject",
43
+
limit: 100,
44
+
constellationBaseUrl,
45
+
enabled: showStarCount,
46
+
});
47
+
48
+
// Extract knot server from record.knot (e.g., "knot.gaze.systems")
49
+
const knotUrl = record?.knot
50
+
? record.knot.startsWith("http://") || record.knot.startsWith("https://")
51
+
? new URL(record.knot).hostname
52
+
: record.knot
53
+
: undefined;
54
+
55
+
// Fetch language data from knot server only if languages not provided
56
+
const {
57
+
data: languagesData,
58
+
loading: _languagesLoading,
59
+
error: _languagesError,
60
+
} = useRepoLanguages({
61
+
knot: knotUrl,
62
+
did,
63
+
repoName: record?.name,
64
+
branch,
65
+
enabled: !languages && !!knotUrl && !!record?.name,
66
+
});
67
+
68
+
// Convert provided language names to the format expected by the renderer
69
+
const providedLanguagesData = languages
70
+
? {
71
+
languages: languages.map((name) => ({
72
+
name,
73
+
percentage: 0,
74
+
size: 0,
75
+
})),
76
+
ref: branch || "main",
77
+
totalFiles: 0,
78
+
totalSize: 0,
79
+
}
80
+
: undefined;
81
+
82
+
// Use provided languages or fetched languages
83
+
const finalLanguagesData = providedLanguagesData ?? languagesData;
84
+
85
+
if (error)
86
+
return (
87
+
<div role="alert" style={{ padding: 8, color: "crimson" }}>
88
+
Failed to load repository.
89
+
</div>
90
+
);
91
+
if (loading && !record) return <div role="status" aria-live="polite" style={{ padding: 8 }}>Loadingโฆ</div>;
92
+
93
+
// Construct the canonical URL: tangled.org/[did]/[repo-name]
94
+
const viewUrl =
95
+
canonicalUrl ??
96
+
`${tangledBaseUrl}/${did}/${encodeURIComponent(record.name)}`;
97
+
98
+
const tangledIcon = (
99
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 25 25" style={{ display: "block" }}>
100
+
<path fill="currentColor" d="m 16.208435,23.914069 c -0.06147,-0.02273 -0.147027,-0.03034 -0.190158,-0.01691 -0.197279,0.06145 -1.31068,-0.230493 -1.388819,-0.364153 -0.01956,-0.03344 -0.163274,-0.134049 -0.319377,-0.223561 -0.550395,-0.315603 -1.010951,-0.696643 -1.428383,-1.181771 -0.264598,-0.307509 -0.597257,-0.785384 -0.597257,-0.857979 0,-0.0216 -0.02841,-0.06243 -0.06313,-0.0907 -0.04977,-0.04053 -0.160873,0.0436 -0.52488,0.397463 -0.479803,0.466432 -0.78924,0.689475 -1.355603,0.977118 -0.183693,0.0933 -0.323426,0.179989 -0.310516,0.192658 0.02801,0.02748 -0.7656391,0.270031 -1.209129,0.369517 -0.5378332,0.120647 -1.6341809,0.08626 -1.9721503,-0.06186 C 6.7977157,23.031391 6.56735,22.957551 6.3371134,22.889782 4.9717169,22.487902 3.7511914,21.481518 3.1172396,20.234838 2.6890391,19.392772 2.5582276,18.827446 2.5610489,17.831154 2.5639589,16.802192 2.7366641,16.125844 3.2142117,15.273187 3.3040457,15.112788 3.3713143,14.976533 3.3636956,14.9704 3.3560756,14.9643 3.2459634,14.90305 3.1189994,14.834381 1.7582586,14.098312 0.77760984,12.777439 0.44909837,11.23818 0.33531456,10.705039 0.33670119,9.7067968 0.45195381,9.1778795 0.72259241,7.9359287 1.3827188,6.8888436 2.4297498,6.0407205 2.6856126,5.8334648 3.2975489,5.4910878 3.6885849,5.3364049 L 4.0584319,5.190106 4.2333984,4.860432 C 4.8393906,3.7186139 5.8908314,2.7968028 7.1056396,2.3423025 7.7690673,2.0940921 8.2290216,2.0150935 9.01853,2.0137575 c 0.9625627,-0.00163 1.629181,0.1532762 2.485864,0.5776514 l 0.271744,0.1346134 0.42911,-0.3607688 c 1.082666,-0.9102346 2.185531,-1.3136811 3.578383,-1.3090327 0.916696,0.00306 1.573918,0.1517893 2.356121,0.5331927 1.465948,0.7148 2.54506,2.0625628 2.865177,3.57848 l 0.07653,0.362429 0.515095,0.2556611 c 1.022872,0.5076874 1.756122,1.1690944 2.288361,2.0641468 0.401896,0.6758594 0.537303,1.0442682 0.675505,1.8378683 0.288575,1.6570823 -0.266229,3.3548023 -1.490464,4.5608743 -0.371074,0.36557 -0.840205,0.718265 -1.203442,0.904754 -0.144112,0.07398 -0.271303,0.15826 -0.282647,0.187269 -0.01134,0.02901 0.02121,0.142764 0.07234,0.25279 0.184248,0.396467 0.451371,1.331823 0.619371,2.168779 0.463493,2.30908 -0.754646,4.693707 -2.92278,5.721632 -0.479538,0.227352 -0.717629,0.309322 -1.144194,0.39393 -0.321869,0.06383 -1.850573,0.09139 -2.000174,0.03604 z M 12.25443,18.636956 c 0.739923,-0.24652 1.382521,-0.718922 1.874623,-1.37812 0.0752,-0.100718 0.213883,-0.275851 0.308198,-0.389167 0.09432,-0.113318 0.210136,-0.271056 0.257381,-0.350531 0.416347,-0.700389 0.680936,-1.176102 0.766454,-1.378041 0.05594,-0.132087 0.114653,-0.239607 0.130477,-0.238929 0.01583,6.79e-4 0.08126,0.08531 0.145412,0.188069 0.178029,0.285173 0.614305,0.658998 0.868158,0.743878 0.259802,0.08686 0.656158,0.09598 0.911369,0.02095 0.213812,-0.06285 0.507296,-0.298016 0.645179,-0.516947 0.155165,-0.246374 0.327989,-0.989595 0.327989,-1.410501 0,-1.26718 -0.610975,-3.143405 -1.237774,-3.801045 -0.198483,-0.2082486 -0.208557,-0.2319396 -0.208557,-0.4904655 0,-0.2517771 -0.08774,-0.5704927 -0.258476,-0.938956 C 16.694963,8.50313 16.375697,8.1377479 16.135846,7.9543702 L 15.932296,7.7987471 15.683004,7.9356529 C 15.131767,8.2383821 14.435638,8.1945733 13.943459,7.8261812 L 13.782862,7.7059758 13.686773,7.8908012 C 13.338849,8.5600578 12.487087,8.8811064 11.743178,8.6233891 11.487199,8.5347109 11.358897,8.4505994 11.063189,8.1776138 L 10.69871,7.8411436 10.453484,8.0579255 C 10.318608,8.1771557 10.113778,8.3156283 9.9983037,8.3656417 9.7041488,8.4930449 9.1808299,8.5227884 8.8979004,8.4281886 8.7754792,8.3872574 8.6687415,8.3537661 8.6607053,8.3537661 c -0.03426,0 -0.3092864,0.3066098 -0.3791974,0.42275 -0.041935,0.069664 -0.1040482,0.1266636 -0.1380294,0.1266636 -0.1316419,0 -0.4197402,0.1843928 -0.6257041,0.4004735 -0.1923125,0.2017571 -0.6853701,0.9036038 -0.8926582,1.2706578 -0.042662,0.07554 -0.1803555,0.353687 -0.3059848,0.618091 -0.1256293,0.264406 -0.3270073,0.686768 -0.4475067,0.938581 -0.1204992,0.251816 -0.2469926,0.519654 -0.2810961,0.595199 -0.2592829,0.574347 -0.285919,1.391094 -0.057822,1.77304 0.1690683,0.283105 0.4224039,0.480895 0.7285507,0.568809 0.487122,0.139885 0.9109638,-0.004 1.6013422,-0.543768 l 0.4560939,-0.356568 0.0036,0.172041 c 0.01635,0.781837 0.1831084,1.813183 0.4016641,2.484154 0.1160449,0.356262 0.3781448,0.83968 0.5614081,1.035462 0.2171883,0.232025 0.7140951,0.577268 1.0100284,0.701749 0.121485,0.0511 0.351032,0.110795 0.510105,0.132647 0.396966,0.05452 1.2105,0.02265 1.448934,-0.05679 z"/>
101
+
</svg>
102
+
);
103
+
104
+
return (
105
+
<div
106
+
style={{
107
+
...base.container,
108
+
background: `var(--atproto-color-bg)`,
109
+
borderWidth: "1px",
110
+
borderStyle: "solid",
111
+
borderColor: `var(--atproto-color-border)`,
112
+
color: `var(--atproto-color-text)`,
113
+
}}
114
+
>
115
+
{/* Header with title and icons */}
116
+
<div
117
+
style={{
118
+
...base.header,
119
+
background: `var(--atproto-color-bg)`,
120
+
}}
121
+
>
122
+
<div style={base.headerTop}>
123
+
<strong
124
+
style={{
125
+
...base.repoName,
126
+
color: `var(--atproto-color-text)`,
127
+
}}
128
+
>
129
+
{record.name}
130
+
</strong>
131
+
<div style={base.headerRight}>
132
+
<a
133
+
href={viewUrl}
134
+
target="_blank"
135
+
rel="noopener noreferrer"
136
+
style={{
137
+
...base.iconLink,
138
+
color: `var(--atproto-color-text)`,
139
+
}}
140
+
title="View on Tangled"
141
+
>
142
+
{tangledIcon}
143
+
</a>
144
+
{record.source && (
145
+
<a
146
+
href={record.source}
147
+
target="_blank"
148
+
rel="noopener noreferrer"
149
+
style={{
150
+
...base.iconLink,
151
+
color: `var(--atproto-color-text)`,
152
+
}}
153
+
title="View source repository"
154
+
>
155
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 16 16" fill="currentColor" style={{ display: "block" }}>
156
+
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/>
157
+
</svg>
158
+
</a>
159
+
)}
160
+
</div>
161
+
</div>
162
+
</div>
163
+
164
+
{/* Description */}
165
+
{record.description && (
166
+
<div
167
+
style={{
168
+
...base.description,
169
+
background: `var(--atproto-color-bg)`,
170
+
color: `var(--atproto-color-text-secondary)`,
171
+
}}
172
+
>
173
+
{record.description}
174
+
</div>
175
+
)}
176
+
177
+
{/* Languages and Stars */}
178
+
<div
179
+
style={{
180
+
...base.languageSection,
181
+
background: `var(--atproto-color-bg)`,
182
+
}}
183
+
>
184
+
{/* Languages */}
185
+
{finalLanguagesData && finalLanguagesData.languages.length > 0 && (() => {
186
+
const topLanguages = finalLanguagesData.languages
187
+
.filter((lang) => lang.name && (lang.percentage > 0 || finalLanguagesData.languages.every(l => l.percentage === 0)))
188
+
.sort((a, b) => b.percentage - a.percentage)
189
+
.slice(0, 2);
190
+
return topLanguages.length > 0 ? (
191
+
<div style={base.languageTags}>
192
+
{topLanguages.map((lang) => (
193
+
<span key={lang.name} style={base.languageTag}>
194
+
{lang.name}
195
+
</span>
196
+
))}
197
+
</div>
198
+
) : null;
199
+
})()}
200
+
201
+
{/* Right side: Stars and View on Tangled link */}
202
+
<div style={base.rightSection}>
203
+
{/* Stars */}
204
+
{showStarCount && (
205
+
<div
206
+
style={{
207
+
...base.starCountContainer,
208
+
color: `var(--atproto-color-text-secondary)`,
209
+
}}
210
+
>
211
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" style={{ display: "block" }}>
212
+
<path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z"/>
213
+
</svg>
214
+
{starsLoading ? (
215
+
<span style={base.starCount}>...</span>
216
+
) : starsError ? (
217
+
<span style={base.starCount}>โ</span>
218
+
) : (
219
+
<span style={base.starCount}>{starCount}</span>
220
+
)}
221
+
</div>
222
+
)}
223
+
224
+
{/* View on Tangled link */}
225
+
<a
226
+
href={viewUrl}
227
+
target="_blank"
228
+
rel="noopener noreferrer"
229
+
style={{
230
+
...base.viewLink,
231
+
color: `var(--atproto-color-link)`,
232
+
}}
233
+
>
234
+
View on Tangled
235
+
</a>
236
+
</div>
237
+
</div>
238
+
</div>
239
+
);
240
+
};
241
+
242
+
const base: Record<string, React.CSSProperties> = {
243
+
container: {
244
+
fontFamily: "system-ui, sans-serif",
245
+
borderRadius: 6,
246
+
overflow: "hidden",
247
+
transition:
248
+
"background-color 180ms ease, border-color 180ms ease, color 180ms ease, box-shadow 180ms ease",
249
+
width: "100%",
250
+
},
251
+
header: {
252
+
padding: "16px",
253
+
display: "flex",
254
+
flexDirection: "column",
255
+
},
256
+
headerTop: {
257
+
display: "flex",
258
+
justifyContent: "space-between",
259
+
alignItems: "flex-start",
260
+
gap: 12,
261
+
},
262
+
headerRight: {
263
+
display: "flex",
264
+
alignItems: "center",
265
+
gap: 8,
266
+
},
267
+
repoName: {
268
+
fontFamily:
269
+
'SFMono-Regular, ui-monospace, Menlo, Monaco, "Courier New", monospace',
270
+
fontSize: 18,
271
+
fontWeight: 600,
272
+
wordBreak: "break-word",
273
+
margin: 0,
274
+
},
275
+
iconLink: {
276
+
display: "flex",
277
+
alignItems: "center",
278
+
textDecoration: "none",
279
+
opacity: 0.7,
280
+
transition: "opacity 150ms ease",
281
+
},
282
+
description: {
283
+
padding: "0 16px 16px 16px",
284
+
fontSize: 14,
285
+
lineHeight: 1.5,
286
+
},
287
+
languageSection: {
288
+
padding: "0 16px 16px 16px",
289
+
display: "flex",
290
+
justifyContent: "space-between",
291
+
alignItems: "center",
292
+
gap: 12,
293
+
flexWrap: "wrap",
294
+
},
295
+
languageTags: {
296
+
display: "flex",
297
+
gap: 8,
298
+
flexWrap: "wrap",
299
+
},
300
+
languageTag: {
301
+
fontSize: 12,
302
+
fontWeight: 500,
303
+
padding: "4px 10px",
304
+
background: `var(--atproto-color-bg)`,
305
+
borderRadius: 12,
306
+
border: "1px solid var(--atproto-color-border)",
307
+
},
308
+
rightSection: {
309
+
display: "flex",
310
+
alignItems: "center",
311
+
gap: 12,
312
+
},
313
+
starCountContainer: {
314
+
display: "flex",
315
+
alignItems: "center",
316
+
gap: 4,
317
+
fontSize: 13,
318
+
},
319
+
starCount: {
320
+
fontSize: 13,
321
+
fontWeight: 500,
322
+
},
323
+
viewLink: {
324
+
fontSize: 13,
325
+
fontWeight: 500,
326
+
textDecoration: "none",
327
+
},
328
+
};
329
+
330
+
export default TangledRepoRenderer;
+18
-91
lib/renderers/TangledStringRenderer.tsx
+18
-91
lib/renderers/TangledStringRenderer.tsx
···
1
1
import React from "react";
2
-
import type { ShTangledString } from "@atcute/tangled";
3
-
import {
4
-
useColorScheme,
5
-
type ColorSchemePreference,
6
-
} from "../hooks/useColorScheme";
7
-
8
-
export type TangledStringRecord = ShTangledString.Main;
2
+
import { useAtProto } from "../providers/AtProtoProvider";
3
+
import type { TangledStringRecord } from "../types/tangled";
9
4
10
5
export interface TangledStringRendererProps {
11
6
record: TangledStringRecord;
12
7
error?: Error;
13
8
loading: boolean;
14
-
colorScheme?: ColorSchemePreference;
15
9
did: string;
16
10
rkey: string;
17
11
canonicalUrl?: string;
···
21
15
record,
22
16
error,
23
17
loading,
24
-
colorScheme = "system",
25
18
did,
26
19
rkey,
27
20
canonicalUrl,
28
21
}) => {
29
-
const scheme = useColorScheme(colorScheme);
22
+
const { tangledBaseUrl } = useAtProto();
30
23
31
24
if (error)
32
25
return (
···
36
29
);
37
30
if (loading && !record) return <div style={{ padding: 8 }}>Loadingโฆ</div>;
38
31
39
-
const palette = scheme === "dark" ? theme.dark : theme.light;
40
32
const viewUrl =
41
33
canonicalUrl ??
42
-
`https://tangled.org/strings/${did}/${encodeURIComponent(rkey)}`;
34
+
`${tangledBaseUrl}/strings/${did}/${encodeURIComponent(rkey)}`;
43
35
const timestamp = new Date(record.createdAt).toLocaleString(undefined, {
44
36
dateStyle: "medium",
45
37
timeStyle: "short",
46
38
});
47
39
return (
48
-
<div style={{ ...base.container, ...palette.container }}>
49
-
<div style={{ ...base.header, ...palette.header }}>
50
-
<strong style={{ ...base.filename, ...palette.filename }}>
40
+
<div style={{ ...base.container, background: `var(--atproto-color-bg-elevated)`, borderWidth: "1px", borderStyle: "solid", borderColor: `var(--atproto-color-border)`, color: `var(--atproto-color-text)` }}>
41
+
<div style={{ ...base.header, background: `var(--atproto-color-bg-elevated)`, borderBottomWidth: "1px", borderBottomStyle: "solid", borderBottomColor: `var(--atproto-color-border)` }}>
42
+
<strong style={{ ...base.filename, color: `var(--atproto-color-text)` }}>
51
43
{record.filename}
52
44
</strong>
53
-
<div style={{ ...base.headerRight, ...palette.headerRight }}>
45
+
<div style={{ ...base.headerRight }}>
54
46
<time
55
-
style={{ ...base.timestamp, ...palette.timestamp }}
47
+
style={{ ...base.timestamp, color: `var(--atproto-color-text-secondary)` }}
56
48
dateTime={record.createdAt}
57
49
>
58
50
{timestamp}
···
61
53
href={viewUrl}
62
54
target="_blank"
63
55
rel="noopener noreferrer"
64
-
style={{ ...base.headerLink, ...palette.headerLink }}
56
+
style={{ ...base.headerLink, color: `var(--atproto-color-link)` }}
65
57
>
66
58
View on Tangled
67
59
</a>
68
60
</div>
69
61
</div>
70
62
{record.description && (
71
-
<div style={{ ...base.description, ...palette.description }}>
63
+
<div style={{ ...base.description, background: `var(--atproto-color-bg)`, borderTopWidth: "1px", borderTopStyle: "solid", borderTopColor: `var(--atproto-color-border)`, borderBottomWidth: "1px", borderBottomStyle: "solid", borderBottomColor: `var(--atproto-color-border)`, color: `var(--atproto-color-text)` }}>
72
64
{record.description}
73
65
</div>
74
66
)}
75
-
<pre style={{ ...base.codeBlock, ...palette.codeBlock }}>
67
+
<pre style={{ ...base.codeBlock, background: `var(--atproto-color-bg)`, color: `var(--atproto-color-text)`, borderTopWidth: "1px", borderTopStyle: "solid", borderTopColor: `var(--atproto-color-border)` }}>
76
68
<code>{record.contents}</code>
77
69
</pre>
78
70
</div>
···
119
111
description: {
120
112
padding: "10px 16px",
121
113
fontSize: 13,
122
-
borderTop: "1px solid transparent",
114
+
borderTopWidth: "1px",
115
+
borderTopStyle: "solid",
116
+
borderTopColor: "transparent",
123
117
},
124
118
codeBlock: {
125
119
margin: 0,
126
120
padding: "16px",
127
121
fontSize: 13,
128
122
overflowX: "auto",
129
-
borderTop: "1px solid transparent",
123
+
borderTopWidth: "1px",
124
+
borderTopStyle: "solid",
125
+
borderTopColor: "transparent",
130
126
fontFamily:
131
127
'SFMono-Regular, ui-monospace, Menlo, Monaco, "Courier New", monospace',
132
128
},
133
129
};
134
-
135
-
const theme = {
136
-
light: {
137
-
container: {
138
-
border: "1px solid #d0d7de",
139
-
background: "#f6f8fa",
140
-
color: "#1f2328",
141
-
boxShadow: "0 1px 2px rgba(31,35,40,0.05)",
142
-
},
143
-
header: {
144
-
background: "#f6f8fa",
145
-
borderBottom: "1px solid #d0d7de",
146
-
},
147
-
headerRight: {},
148
-
filename: {
149
-
color: "#1f2328",
150
-
},
151
-
timestamp: {
152
-
color: "#57606a",
153
-
},
154
-
headerLink: {
155
-
color: "#2563eb",
156
-
},
157
-
description: {
158
-
background: "#ffffff",
159
-
borderBottom: "1px solid #d0d7de",
160
-
borderTopColor: "#d0d7de",
161
-
color: "#1f2328",
162
-
},
163
-
codeBlock: {
164
-
background: "#ffffff",
165
-
color: "#1f2328",
166
-
borderTopColor: "#d0d7de",
167
-
},
168
-
},
169
-
dark: {
170
-
container: {
171
-
border: "1px solid #30363d",
172
-
background: "#0d1117",
173
-
color: "#c9d1d9",
174
-
boxShadow: "0 0 0 1px rgba(1,4,9,0.3) inset",
175
-
},
176
-
header: {
177
-
background: "#161b22",
178
-
borderBottom: "1px solid #30363d",
179
-
},
180
-
headerRight: {},
181
-
filename: {
182
-
color: "#c9d1d9",
183
-
},
184
-
timestamp: {
185
-
color: "#8b949e",
186
-
},
187
-
headerLink: {
188
-
color: "#58a6ff",
189
-
},
190
-
description: {
191
-
background: "#161b22",
192
-
borderBottom: "1px solid #30363d",
193
-
borderTopColor: "#30363d",
194
-
color: "#c9d1d9",
195
-
},
196
-
codeBlock: {
197
-
background: "#0d1117",
198
-
color: "#c9d1d9",
199
-
borderTopColor: "#30363d",
200
-
},
201
-
},
202
-
} satisfies Record<"light" | "dark", Record<string, React.CSSProperties>>;
203
130
204
131
export default TangledStringRenderer;
+97
lib/styles.css
+97
lib/styles.css
···
1
+
/**
2
+
* Global CSS variables for AtProto UI components
3
+
*
4
+
* These variables can be customized in your application by setting them
5
+
* at the :root level or within specific components.
6
+
*/
7
+
8
+
:root {
9
+
/* Light theme colors (default) */
10
+
--atproto-color-bg: #f5f7f9;
11
+
--atproto-color-bg-elevated: #f8f9fb;
12
+
--atproto-color-bg-secondary: #edf1f5;
13
+
--atproto-color-text: #0f172a;
14
+
--atproto-color-text-secondary: #475569;
15
+
--atproto-color-text-muted: #64748b;
16
+
--atproto-color-border: #d6dce3;
17
+
--atproto-color-border-subtle: #c1cad4;
18
+
--atproto-color-border-hover: #94a3b8;
19
+
--atproto-color-link: #2563eb;
20
+
--atproto-color-link-hover: #1d4ed8;
21
+
--atproto-color-error: #dc2626;
22
+
--atproto-color-primary: #2563eb;
23
+
--atproto-color-button-bg: #edf1f5;
24
+
--atproto-color-button-hover: #e3e9ef;
25
+
--atproto-color-button-text: #0f172a;
26
+
--atproto-color-bg-hover: #f0f3f6;
27
+
--atproto-color-bg-pressed: #e3e9ef;
28
+
--atproto-color-code-bg: #edf1f5;
29
+
--atproto-color-code-border: #d6dce3;
30
+
--atproto-color-blockquote-border: #c1cad4;
31
+
--atproto-color-blockquote-bg: #f0f3f6;
32
+
--atproto-color-hr: #d6dce3;
33
+
--atproto-color-image-bg: #edf1f5;
34
+
--atproto-color-highlight: #fef08a;
35
+
}
36
+
37
+
/* Dark theme - can be applied via [data-theme="dark"] or .dark class */
38
+
[data-theme="dark"],
39
+
.dark {
40
+
--atproto-color-bg: #141b22;
41
+
--atproto-color-bg-elevated: #1a222a;
42
+
--atproto-color-bg-secondary: #0f161c;
43
+
--atproto-color-text: #fafafa;
44
+
--atproto-color-text-secondary: #a1a1aa;
45
+
--atproto-color-text-muted: #71717a;
46
+
--atproto-color-border: #1f2933;
47
+
--atproto-color-border-subtle: #2d3748;
48
+
--atproto-color-border-hover: #4a5568;
49
+
--atproto-color-link: #60a5fa;
50
+
--atproto-color-link-hover: #93c5fd;
51
+
--atproto-color-error: #ef4444;
52
+
--atproto-color-primary: #3b82f6;
53
+
--atproto-color-button-bg: #1a222a;
54
+
--atproto-color-button-hover: #243039;
55
+
--atproto-color-button-text: #fafafa;
56
+
--atproto-color-bg-hover: #1a222a;
57
+
--atproto-color-bg-pressed: #243039;
58
+
--atproto-color-code-bg: #0f161c;
59
+
--atproto-color-code-border: #1f2933;
60
+
--atproto-color-blockquote-border: #2d3748;
61
+
--atproto-color-blockquote-bg: #1a222a;
62
+
--atproto-color-hr: #243039;
63
+
--atproto-color-image-bg: #1a222a;
64
+
--atproto-color-highlight: #854d0e;
65
+
}
66
+
67
+
/* Support for system preference based theming */
68
+
@media (prefers-color-scheme: dark) {
69
+
:root:not([data-theme]),
70
+
:root[data-theme="system"] {
71
+
--atproto-color-bg: #141b22;
72
+
--atproto-color-bg-elevated: #1a222a;
73
+
--atproto-color-bg-secondary: #0f161c;
74
+
--atproto-color-text: #fafafa;
75
+
--atproto-color-text-secondary: #a1a1aa;
76
+
--atproto-color-text-muted: #71717a;
77
+
--atproto-color-border: #1f2933;
78
+
--atproto-color-border-subtle: #2d3748;
79
+
--atproto-color-border-hover: #4a5568;
80
+
--atproto-color-link: #60a5fa;
81
+
--atproto-color-link-hover: #93c5fd;
82
+
--atproto-color-error: #ef4444;
83
+
--atproto-color-primary: #3b82f6;
84
+
--atproto-color-button-bg: #1a222a;
85
+
--atproto-color-button-hover: #243039;
86
+
--atproto-color-button-text: #fafafa;
87
+
--atproto-color-bg-hover: #1a222a;
88
+
--atproto-color-bg-pressed: #243039;
89
+
--atproto-color-code-bg: #0f161c;
90
+
--atproto-color-code-border: #1f2933;
91
+
--atproto-color-blockquote-border: #2d3748;
92
+
--atproto-color-blockquote-bg: #1a222a;
93
+
--atproto-color-hr: #243039;
94
+
--atproto-color-image-bg: #1a222a;
95
+
--atproto-color-highlight: #854d0e;
96
+
}
97
+
}
+95
lib/types/grain.ts
+95
lib/types/grain.ts
···
1
+
/**
2
+
* Type definitions for grain.social records
3
+
* Uses standard atcute blob types for compatibility
4
+
*/
5
+
import type { Blob } from "@atcute/lexicons/interfaces";
6
+
import type { BlobWithCdn } from "../hooks/useBlueskyAppview";
7
+
8
+
/**
9
+
* grain.social gallery record
10
+
* A container for a collection of photos
11
+
*/
12
+
export interface GrainGalleryRecord {
13
+
/**
14
+
* Record type identifier
15
+
*/
16
+
$type: "social.grain.gallery";
17
+
/**
18
+
* Gallery title
19
+
*/
20
+
title: string;
21
+
/**
22
+
* Gallery description
23
+
*/
24
+
description?: string;
25
+
/**
26
+
* Self-label values (content warnings)
27
+
*/
28
+
labels?: {
29
+
$type: "com.atproto.label.defs#selfLabels";
30
+
values: Array<{ val: string }>;
31
+
};
32
+
/**
33
+
* Timestamp when the gallery was created
34
+
*/
35
+
createdAt: string;
36
+
}
37
+
38
+
/**
39
+
* grain.social gallery item record
40
+
* Links a photo to a gallery
41
+
*/
42
+
export interface GrainGalleryItemRecord {
43
+
/**
44
+
* Record type identifier
45
+
*/
46
+
$type: "social.grain.gallery.item";
47
+
/**
48
+
* AT URI of the photo (social.grain.photo)
49
+
*/
50
+
item: string;
51
+
/**
52
+
* AT URI of the gallery this item belongs to
53
+
*/
54
+
gallery: string;
55
+
/**
56
+
* Position/order within the gallery
57
+
*/
58
+
position?: number;
59
+
/**
60
+
* Timestamp when the item was added to the gallery
61
+
*/
62
+
createdAt: string;
63
+
}
64
+
65
+
/**
66
+
* grain.social photo record
67
+
* Compatible with records from @atcute clients
68
+
*/
69
+
export interface GrainPhotoRecord {
70
+
/**
71
+
* Record type identifier
72
+
*/
73
+
$type: "social.grain.photo";
74
+
/**
75
+
* Alt text description of the image (required for accessibility)
76
+
*/
77
+
alt: string;
78
+
/**
79
+
* Photo blob reference - uses standard AT Proto blob format
80
+
* Supports any image/* mime type
81
+
* May include cdnUrl when fetched from appview
82
+
*/
83
+
photo: Blob<`image/${string}`> | BlobWithCdn;
84
+
/**
85
+
* Timestamp when the photo was created
86
+
*/
87
+
createdAt?: string;
88
+
/**
89
+
* Aspect ratio of the photo
90
+
*/
91
+
aspectRatio?: {
92
+
width: number;
93
+
height: number;
94
+
};
95
+
}
+22
lib/types/tangled.ts
+22
lib/types/tangled.ts
···
1
+
import type { ShTangledRepo, ShTangledString } from "@atcute/tangled";
2
+
3
+
export type TangledRepoRecord = ShTangledRepo.Main;
4
+
export type TangledStringRecord = ShTangledString.Main;
5
+
6
+
/** Language information from sh.tangled.repo.languages endpoint */
7
+
export interface RepoLanguage {
8
+
name: string;
9
+
percentage: number;
10
+
size: number;
11
+
}
12
+
13
+
/**
14
+
* Response from sh.tangled.repo.languages endpoint from tangled knot
15
+
*/
16
+
export interface RepoLanguagesResponse {
17
+
languages: RepoLanguage[];
18
+
/** Branch name */
19
+
ref: string;
20
+
totalFiles: number;
21
+
totalSize: number;
22
+
}
+40
lib/types/teal.ts
+40
lib/types/teal.ts
···
1
+
/**
2
+
* teal.fm record types for music listening history
3
+
* Specification: fm.teal.alpha.actor.status and fm.teal.alpha.feed.play
4
+
*/
5
+
6
+
export interface TealArtist {
7
+
artistName: string;
8
+
artistMbId?: string;
9
+
}
10
+
11
+
export interface TealPlayItem {
12
+
artists: TealArtist[];
13
+
originUrl?: string;
14
+
trackName: string;
15
+
playedTime: string;
16
+
releaseName?: string;
17
+
recordingMbId?: string;
18
+
releaseMbId?: string;
19
+
submissionClientAgent?: string;
20
+
musicServiceBaseDomain?: string;
21
+
isrc?: string;
22
+
duration?: number;
23
+
}
24
+
25
+
/**
26
+
* fm.teal.alpha.actor.status - The last played song
27
+
*/
28
+
export interface TealActorStatusRecord {
29
+
$type: "fm.teal.alpha.actor.status";
30
+
item: TealPlayItem;
31
+
time: string;
32
+
expiry?: string;
33
+
}
34
+
35
+
/**
36
+
* fm.teal.alpha.feed.play - A single play record
37
+
*/
38
+
export interface TealFeedPlayRecord extends TealPlayItem {
39
+
$type: "fm.teal.alpha.feed.play";
40
+
}
+23
lib/types/theme.ts
+23
lib/types/theme.ts
···
1
+
export type AtProtoStyles = React.CSSProperties & {
2
+
'--atproto-color-bg'?: string;
3
+
'--atproto-color-bg-elevated'?: string;
4
+
'--atproto-color-bg-secondary'?: string;
5
+
'--atproto-color-text'?: string;
6
+
'--atproto-color-text-secondary'?: string;
7
+
'--atproto-color-text-muted'?: string;
8
+
'--atproto-color-border'?: string;
9
+
'--atproto-color-border-subtle'?: string;
10
+
'--atproto-color-link'?: string;
11
+
'--atproto-color-link-hover'?: string;
12
+
'--atproto-color-error'?: string;
13
+
'--atproto-color-button-bg'?: string;
14
+
'--atproto-color-button-hover'?: string;
15
+
'--atproto-color-button-text'?: string;
16
+
'--atproto-color-code-bg'?: string;
17
+
'--atproto-color-code-border'?: string;
18
+
'--atproto-color-blockquote-border'?: string;
19
+
'--atproto-color-blockquote-bg'?: string;
20
+
'--atproto-color-hr'?: string;
21
+
'--atproto-color-image-bg'?: string;
22
+
'--atproto-color-highlight'?: string;
23
+
};
+37
-4
lib/utils/atproto-client.ts
+37
-4
lib/utils/atproto-client.ts
···
13
13
export interface ServiceResolverOptions {
14
14
plcDirectory?: string;
15
15
identityService?: string;
16
+
slingshotBaseUrl?: string;
16
17
fetch?: typeof fetch;
17
18
}
18
19
19
20
const DEFAULT_PLC = "https://plc.directory";
20
21
const DEFAULT_IDENTITY_SERVICE = "https://public.api.bsky.app";
22
+
const DEFAULT_SLINGSHOT = "https://slingshot.microcosm.blue";
23
+
const DEFAULT_APPVIEW = "https://public.api.bsky.app";
24
+
const DEFAULT_BLUESKY_APP = "https://bsky.app";
25
+
const DEFAULT_TANGLED = "https://tangled.org";
26
+
const DEFAULT_CONSTELLATION = "https://constellation.microcosm.blue";
27
+
21
28
const ABSOLUTE_URL_RE = /^[a-zA-Z][a-zA-Z\d+\-.]*:/;
22
29
const SUPPORTED_DID_METHODS = ["plc", "web"] as const;
23
30
type SupportedDidMethod = (typeof SUPPORTED_DID_METHODS)[number];
24
31
type SupportedDid = Did<SupportedDidMethod>;
25
32
26
-
export const SLINGSHOT_BASE_URL = "https://slingshot.microcosm.blue";
33
+
/**
34
+
* Default configuration values for AT Protocol services.
35
+
* These can be overridden via AtProtoProvider props.
36
+
*/
37
+
export const DEFAULT_CONFIG = {
38
+
plcDirectory: DEFAULT_PLC,
39
+
identityService: DEFAULT_IDENTITY_SERVICE,
40
+
slingshotBaseUrl: DEFAULT_SLINGSHOT,
41
+
blueskyAppviewService: DEFAULT_APPVIEW,
42
+
blueskyAppBaseUrl: DEFAULT_BLUESKY_APP,
43
+
tangledBaseUrl: DEFAULT_TANGLED,
44
+
constellationBaseUrl: DEFAULT_CONSTELLATION,
45
+
} as const;
46
+
47
+
export const SLINGSHOT_BASE_URL = DEFAULT_SLINGSHOT;
27
48
28
49
export const normalizeBaseUrl = (input: string): string => {
29
50
const trimmed = input.trim();
···
38
59
39
60
export class ServiceResolver {
40
61
private plc: string;
62
+
private slingshot: string;
41
63
private didResolver: CompositeDidDocumentResolver<SupportedDidMethod>;
42
64
private handleResolver: XrpcHandleResolver;
43
65
private fetchImpl: typeof fetch;
···
50
72
opts.identityService && opts.identityService.trim()
51
73
? opts.identityService
52
74
: DEFAULT_IDENTITY_SERVICE;
75
+
const slingshotSource =
76
+
opts.slingshotBaseUrl && opts.slingshotBaseUrl.trim()
77
+
? opts.slingshotBaseUrl
78
+
: DEFAULT_SLINGSHOT;
53
79
this.plc = normalizeBaseUrl(plcSource);
54
80
const identityBase = normalizeBaseUrl(identitySource);
81
+
this.slingshot = normalizeBaseUrl(slingshotSource);
55
82
this.fetchImpl = bindFetch(opts.fetch);
56
83
const plcResolver = new PlcDidDocumentResolver({
57
84
apiUrl: this.plc,
···
97
124
return svc.serviceEndpoint.replace(/\/$/, "");
98
125
}
99
126
127
+
getSlingshotUrl(): string {
128
+
return this.slingshot;
129
+
}
130
+
100
131
async resolveHandle(handle: string): Promise<string> {
101
132
const normalized = handle.trim().toLowerCase();
102
133
if (!normalized) throw new Error("Handle cannot be empty");
···
104
135
try {
105
136
const url = new URL(
106
137
"/xrpc/com.atproto.identity.resolveHandle",
107
-
SLINGSHOT_BASE_URL,
138
+
this.slingshot,
108
139
);
109
140
url.searchParams.set("handle", normalized);
110
141
const response = await this.fetchImpl(url);
···
161
192
}
162
193
if (!service) throw new Error("service or did required");
163
194
const normalizedService = normalizeBaseUrl(service);
164
-
const handler = createSlingshotAwareHandler(normalizedService, fetchImpl);
195
+
const slingshotUrl = resolver.getSlingshotUrl();
196
+
const handler = createSlingshotAwareHandler(normalizedService, slingshotUrl, fetchImpl);
165
197
const rpc = new Client({ handler });
166
198
return { rpc, service: normalizedService, resolver };
167
199
}
···
177
209
178
210
function createSlingshotAwareHandler(
179
211
service: string,
212
+
slingshotBaseUrl: string,
180
213
fetchImpl: typeof fetch,
181
214
): FetchHandler {
182
215
const primary = simpleFetchHandler({ service, fetch: fetchImpl });
183
216
const slingshot = simpleFetchHandler({
184
-
service: SLINGSHOT_BASE_URL,
217
+
service: slingshotBaseUrl,
185
218
fetch: fetchImpl,
186
219
});
187
220
return async (pathname, init) => {
+37
lib/utils/blob.ts
+37
lib/utils/blob.ts
···
1
+
import type { BlobWithCdn } from "../hooks/useBlueskyAppview";
2
+
3
+
/**
4
+
* Type guard to check if a blob has a CDN URL from appview.
5
+
*/
6
+
export function isBlobWithCdn(value: unknown): value is BlobWithCdn {
7
+
if (typeof value !== "object" || value === null) return false;
8
+
const obj = value as Record<string, unknown>;
9
+
return (
10
+
obj.$type === "blob" &&
11
+
typeof obj.cdnUrl === "string" &&
12
+
typeof obj.ref === "object" &&
13
+
obj.ref !== null &&
14
+
typeof (obj.ref as { $link?: unknown }).$link === "string"
15
+
);
16
+
}
17
+
18
+
/**
19
+
* Extracts CID from a blob reference object.
20
+
* Works with both legacy and modern blob formats.
21
+
*/
22
+
export function extractCidFromBlob(blob: unknown): string | undefined {
23
+
if (typeof blob !== "object" || blob === null) return undefined;
24
+
25
+
const blobObj = blob as {
26
+
ref?: { $link?: string };
27
+
cid?: string;
28
+
};
29
+
30
+
if (typeof blobObj.cid === "string") return blobObj.cid;
31
+
if (typeof blobObj.ref === "object" && blobObj.ref !== null) {
32
+
const link = blobObj.ref.$link;
33
+
if (typeof link === "string") return link;
34
+
}
35
+
36
+
return undefined;
37
+
}
+141
-1
lib/utils/cache.ts
+141
-1
lib/utils/cache.ts
···
7
7
doc?: DidDocument;
8
8
pdsEndpoint?: string;
9
9
timestamp: number;
10
+
snapshot?: DidCacheSnapshot; // Memoized snapshot to prevent rerenders
10
11
}
11
12
12
13
export interface DidCacheSnapshot {
···
20
21
entry: DidCacheEntry | undefined,
21
22
): DidCacheSnapshot | undefined => {
22
23
if (!entry) return undefined;
24
+
// Return memoized snapshot if it exists
25
+
if (entry.snapshot) return entry.snapshot;
26
+
// Create and cache new snapshot
23
27
const { did, handle, doc, pdsEndpoint } = entry;
24
-
return { did, handle, doc, pdsEndpoint };
28
+
const snapshot = { did, handle, doc, pdsEndpoint };
29
+
entry.snapshot = snapshot;
30
+
return snapshot;
25
31
};
26
32
27
33
const derivePdsEndpoint = (
···
78
84
derivePdsEndpoint(doc) ??
79
85
existing?.pdsEndpoint;
80
86
87
+
// Check if data has changed - if not, reuse existing snapshot
88
+
if (
89
+
existing &&
90
+
existing.did === did &&
91
+
existing.handle === handle &&
92
+
existing.doc === doc &&
93
+
existing.pdsEndpoint === pdsEndpoint
94
+
) {
95
+
// Data unchanged, return existing memoized snapshot
96
+
return toSnapshot(existing) as DidCacheSnapshot;
97
+
}
98
+
99
+
// Data changed, create new entry (snapshot will be created on first access)
81
100
const merged: DidCacheEntry = {
82
101
did,
83
102
handle,
84
103
doc,
85
104
pdsEndpoint,
86
105
timestamp: Date.now(),
106
+
snapshot: undefined, // Will be created lazily by toSnapshot
87
107
};
88
108
89
109
this.byDid.set(did, merged);
···
250
270
}
251
271
}
252
272
}
273
+
274
+
interface RecordCacheEntry<T = unknown> {
275
+
record: T;
276
+
timestamp: number;
277
+
}
278
+
279
+
interface InFlightRecordEntry<T = unknown> {
280
+
promise: Promise<T>;
281
+
abort: () => void;
282
+
refCount: number;
283
+
}
284
+
285
+
interface RecordEnsureResult<T = unknown> {
286
+
promise: Promise<T>;
287
+
release: () => void;
288
+
}
289
+
290
+
export class RecordCache {
291
+
private store = new Map<string, RecordCacheEntry>();
292
+
private inFlight = new Map<string, InFlightRecordEntry>();
293
+
// Collections that should not be cached (e.g., status records that change frequently)
294
+
private noCacheCollections = new Set<string>([
295
+
"fm.teal.alpha.actor.status",
296
+
"fm.teal.alpha.feed.play",
297
+
]);
298
+
299
+
private key(did: string, collection: string, rkey: string): string {
300
+
return `${did}::${collection}::${rkey}`;
301
+
}
302
+
303
+
private shouldCache(collection: string): boolean {
304
+
return !this.noCacheCollections.has(collection);
305
+
}
306
+
307
+
get<T = unknown>(
308
+
did?: string,
309
+
collection?: string,
310
+
rkey?: string,
311
+
): T | undefined {
312
+
if (!did || !collection || !rkey) return undefined;
313
+
// Don't return cached data for non-cacheable collections
314
+
if (!this.shouldCache(collection)) return undefined;
315
+
return this.store.get(this.key(did, collection, rkey))?.record as
316
+
| T
317
+
| undefined;
318
+
}
319
+
320
+
set<T = unknown>(
321
+
did: string,
322
+
collection: string,
323
+
rkey: string,
324
+
record: T,
325
+
): void {
326
+
// Don't cache records for non-cacheable collections
327
+
if (!this.shouldCache(collection)) return;
328
+
this.store.set(this.key(did, collection, rkey), {
329
+
record,
330
+
timestamp: Date.now(),
331
+
});
332
+
}
333
+
334
+
ensure<T = unknown>(
335
+
did: string,
336
+
collection: string,
337
+
rkey: string,
338
+
loader: () => { promise: Promise<T>; abort: () => void },
339
+
): RecordEnsureResult<T> {
340
+
const cached = this.get<T>(did, collection, rkey);
341
+
if (cached !== undefined) {
342
+
return { promise: Promise.resolve(cached), release: () => {} };
343
+
}
344
+
345
+
const key = this.key(did, collection, rkey);
346
+
const existing = this.inFlight.get(key) as
347
+
| InFlightRecordEntry<T>
348
+
| undefined;
349
+
if (existing) {
350
+
existing.refCount += 1;
351
+
return {
352
+
promise: existing.promise,
353
+
release: () => this.release(key),
354
+
};
355
+
}
356
+
357
+
const { promise, abort } = loader();
358
+
const wrapped = promise.then((record) => {
359
+
this.set(did, collection, rkey, record);
360
+
return record;
361
+
});
362
+
363
+
const entry: InFlightRecordEntry<T> = {
364
+
promise: wrapped,
365
+
abort,
366
+
refCount: 1,
367
+
};
368
+
369
+
this.inFlight.set(key, entry as InFlightRecordEntry);
370
+
371
+
wrapped
372
+
.catch(() => {})
373
+
.finally(() => {
374
+
this.inFlight.delete(key);
375
+
});
376
+
377
+
return {
378
+
promise: wrapped,
379
+
release: () => this.release(key),
380
+
};
381
+
}
382
+
383
+
private release(key: string) {
384
+
const entry = this.inFlight.get(key);
385
+
if (!entry) return;
386
+
entry.refCount -= 1;
387
+
if (entry.refCount <= 0) {
388
+
this.inFlight.delete(key);
389
+
entry.abort();
390
+
}
391
+
}
392
+
}
+120
lib/utils/richtext.ts
+120
lib/utils/richtext.ts
···
1
+
import type { AppBskyRichtextFacet } from "@atcute/bluesky";
2
+
3
+
export interface TextSegment {
4
+
text: string;
5
+
facet?: AppBskyRichtextFacet.Main;
6
+
}
7
+
8
+
/**
9
+
* Converts a text string with facets into segments that can be rendered
10
+
* with appropriate styling and interactivity.
11
+
*/
12
+
export function createTextSegments(
13
+
text: string,
14
+
facets?: AppBskyRichtextFacet.Main[],
15
+
): TextSegment[] {
16
+
if (!facets || facets.length === 0) {
17
+
return [{ text }];
18
+
}
19
+
20
+
// Build byte-to-char index mapping
21
+
const bytePrefix = buildBytePrefix(text);
22
+
23
+
// Sort facets by start position
24
+
const sortedFacets = [...facets].sort(
25
+
(a, b) => a.index.byteStart - b.index.byteStart,
26
+
);
27
+
28
+
const segments: TextSegment[] = [];
29
+
let currentPos = 0;
30
+
31
+
for (const facet of sortedFacets) {
32
+
const startChar = byteOffsetToCharIndex(bytePrefix, facet.index.byteStart);
33
+
const endChar = byteOffsetToCharIndex(bytePrefix, facet.index.byteEnd);
34
+
35
+
// Add plain text before this facet
36
+
if (startChar > currentPos) {
37
+
segments.push({
38
+
text: sliceByCharRange(text, currentPos, startChar),
39
+
});
40
+
}
41
+
42
+
// Add the faceted text
43
+
segments.push({
44
+
text: sliceByCharRange(text, startChar, endChar),
45
+
facet,
46
+
});
47
+
48
+
currentPos = endChar;
49
+
}
50
+
51
+
// Add remaining plain text
52
+
if (currentPos < text.length) {
53
+
segments.push({
54
+
text: sliceByCharRange(text, currentPos, text.length),
55
+
});
56
+
}
57
+
58
+
return segments;
59
+
}
60
+
61
+
/**
62
+
* Builds a byte offset prefix array for UTF-8 encoded text.
63
+
* This handles multi-byte characters correctly.
64
+
*/
65
+
function buildBytePrefix(text: string): number[] {
66
+
const encoder = new TextEncoder();
67
+
const prefix: number[] = [0];
68
+
let byteCount = 0;
69
+
70
+
for (let i = 0; i < text.length; ) {
71
+
const codePoint = text.codePointAt(i);
72
+
if (codePoint === undefined) break;
73
+
74
+
const char = String.fromCodePoint(codePoint);
75
+
const encoded = encoder.encode(char);
76
+
byteCount += encoded.length;
77
+
prefix.push(byteCount);
78
+
79
+
// Handle surrogate pairs (emojis, etc.)
80
+
i += codePoint > 0xffff ? 2 : 1;
81
+
}
82
+
83
+
return prefix;
84
+
}
85
+
86
+
/**
87
+
* Converts a byte offset to a character index using the byte prefix array.
88
+
*/
89
+
function byteOffsetToCharIndex(prefix: number[], byteOffset: number): number {
90
+
for (let i = 0; i < prefix.length; i++) {
91
+
if (prefix[i] === byteOffset) return i;
92
+
if (prefix[i] > byteOffset) return Math.max(0, i - 1);
93
+
}
94
+
return prefix.length - 1;
95
+
}
96
+
97
+
/**
98
+
* Slices text by character range, handling multi-byte characters correctly.
99
+
*/
100
+
function sliceByCharRange(text: string, start: number, end: number): string {
101
+
if (start <= 0 && end >= text.length) return text;
102
+
103
+
let result = "";
104
+
let charIndex = 0;
105
+
106
+
for (let i = 0; i < text.length && charIndex < end; ) {
107
+
const codePoint = text.codePointAt(i);
108
+
if (codePoint === undefined) break;
109
+
110
+
const char = String.fromCodePoint(codePoint);
111
+
if (charIndex >= start && charIndex < end) {
112
+
result += char;
113
+
}
114
+
115
+
i += codePoint > 0xffff ? 2 : 1;
116
+
charIndex++;
117
+
}
118
+
119
+
return result;
120
+
}
+4073
-2861
package-lock.json
+4073
-2861
package-lock.json
···
1
1
{
2
-
"name": "atproto-ui",
3
-
"version": "0.2.0",
4
-
"lockfileVersion": 3,
5
-
"requires": true,
6
-
"packages": {
7
-
"": {
8
-
"name": "atproto-ui",
9
-
"version": "0.2.0",
10
-
"dependencies": {
11
-
"@atcute/atproto": "^3.1.7",
12
-
"@atcute/bluesky": "^3.2.3",
13
-
"@atcute/client": "^4.0.3",
14
-
"@atcute/identity-resolver": "^1.1.3",
15
-
"@atcute/tangled": "^1.0.6"
16
-
},
17
-
"devDependencies": {
18
-
"@eslint/js": "^9.36.0",
19
-
"@types/node": "^24.6.0",
20
-
"@types/react": "^19.1.16",
21
-
"@types/react-dom": "^19.1.9",
22
-
"@vitejs/plugin-react": "^5.0.4",
23
-
"eslint": "^9.36.0",
24
-
"eslint-plugin-react-hooks": "^5.2.0",
25
-
"eslint-plugin-react-refresh": "^0.4.22",
26
-
"globals": "^16.4.0",
27
-
"react": "^19.1.1",
28
-
"react-dom": "^19.1.1",
29
-
"typescript": "~5.9.3",
30
-
"typescript-eslint": "^8.45.0",
31
-
"vite": "npm:rolldown-vite@7.1.14"
32
-
},
33
-
"peerDependencies": {
34
-
"react": "^18.2.0 || ^19.0.0",
35
-
"react-dom": "^18.2.0 || ^19.0.0"
36
-
},
37
-
"peerDependenciesMeta": {
38
-
"react-dom": {
39
-
"optional": true
40
-
}
41
-
}
42
-
},
43
-
"node_modules/@atcute/atproto": {
44
-
"version": "3.1.7",
45
-
"resolved": "https://registry.npmjs.org/@atcute/atproto/-/atproto-3.1.7.tgz",
46
-
"integrity": "sha512-3Ym8qaVZg2vf8qw0KO1aue39z/5oik5J+UDoSes1vr8ddw40UVLA5sV4bXSKmLnhzQHiLLgoVZXe4zaKfozPoQ==",
47
-
"license": "0BSD",
48
-
"dependencies": {
49
-
"@atcute/lexicons": "^1.2.2"
50
-
}
51
-
},
52
-
"node_modules/@atcute/bluesky": {
53
-
"version": "3.2.3",
54
-
"resolved": "https://registry.npmjs.org/@atcute/bluesky/-/bluesky-3.2.3.tgz",
55
-
"integrity": "sha512-IdPQQ54F1BLhW5z49k81ZUC/GQl/tVygZ+CzLHYvQySHA6GJRcvPzwEf8aV21u0SZOJF+yF4CWEGNgtryyxPmg==",
56
-
"license": "0BSD",
57
-
"dependencies": {
58
-
"@atcute/atproto": "^3.1.4",
59
-
"@atcute/lexicons": "^1.1.1"
60
-
}
61
-
},
62
-
"node_modules/@atcute/client": {
63
-
"version": "4.0.3",
64
-
"resolved": "https://registry.npmjs.org/@atcute/client/-/client-4.0.3.tgz",
65
-
"integrity": "sha512-RIOZWFVLca/HiPAAUDqQPOdOreCxTbL5cb+WUf5yqQOKIu5yEAP3eksinmlLmgIrlr5qVOE7brazUUzaskFCfw==",
66
-
"license": "MIT",
67
-
"dependencies": {
68
-
"@atcute/identity": "^1.0.2",
69
-
"@atcute/lexicons": "^1.0.3"
70
-
}
71
-
},
72
-
"node_modules/@atcute/identity": {
73
-
"version": "1.1.0",
74
-
"resolved": "https://registry.npmjs.org/@atcute/identity/-/identity-1.1.0.tgz",
75
-
"integrity": "sha512-6vRvRqJatDB+JUQsb+UswYmtBGQnSZcqC3a2y6H5DB/v5KcIh+6nFFtc17G0+3W9rxdk7k9M4KkgkdKf/YDNoQ==",
76
-
"license": "0BSD",
77
-
"dependencies": {
78
-
"@atcute/lexicons": "^1.1.1",
79
-
"@badrap/valita": "^0.4.5"
80
-
}
81
-
},
82
-
"node_modules/@atcute/identity-resolver": {
83
-
"version": "1.1.4",
84
-
"resolved": "https://registry.npmjs.org/@atcute/identity-resolver/-/identity-resolver-1.1.4.tgz",
85
-
"integrity": "sha512-/SVh8vf2cXFJenmBnGeYF2aY3WGQm3cJeew5NWTlkqoy3LvJ5wkvKq9PWu4Tv653VF40rPOp6LOdVr9Fa+q5rA==",
86
-
"license": "0BSD",
87
-
"dependencies": {
88
-
"@atcute/lexicons": "^1.2.2",
89
-
"@atcute/util-fetch": "^1.0.3",
90
-
"@badrap/valita": "^0.4.6"
91
-
},
92
-
"peerDependencies": {
93
-
"@atcute/identity": "^1.0.0"
94
-
}
95
-
},
96
-
"node_modules/@atcute/lexicons": {
97
-
"version": "1.2.2",
98
-
"resolved": "https://registry.npmjs.org/@atcute/lexicons/-/lexicons-1.2.2.tgz",
99
-
"integrity": "sha512-bgEhJq5Z70/0TbK5sx+tAkrR8FsCODNiL2gUEvS5PuJfPxmFmRYNWaMGehxSPaXWpU2+Oa9ckceHiYbrItDTkA==",
100
-
"license": "0BSD",
101
-
"dependencies": {
102
-
"@standard-schema/spec": "^1.0.0",
103
-
"esm-env": "^1.2.2"
104
-
}
105
-
},
106
-
"node_modules/@atcute/tangled": {
107
-
"version": "1.0.6",
108
-
"resolved": "https://registry.npmjs.org/@atcute/tangled/-/tangled-1.0.6.tgz",
109
-
"integrity": "sha512-eEOtrKRbjKfeLYtb5hmkhE45w8h4sV6mT4E2CQzJmhOMGCiK31GX7Vqfh59rhNLb9AlbW72RcQTV737pxx+ksw==",
110
-
"license": "0BSD",
111
-
"dependencies": {
112
-
"@atcute/atproto": "^3.1.4",
113
-
"@atcute/lexicons": "^1.1.1"
114
-
}
115
-
},
116
-
"node_modules/@atcute/util-fetch": {
117
-
"version": "1.0.3",
118
-
"resolved": "https://registry.npmjs.org/@atcute/util-fetch/-/util-fetch-1.0.3.tgz",
119
-
"integrity": "sha512-f8zzTb/xlKIwv2OQ31DhShPUNCmIIleX6p7qIXwWwEUjX6x8skUtpdISSjnImq01LXpltGV5y8yhV4/Mlb7CRQ==",
120
-
"license": "0BSD",
121
-
"dependencies": {
122
-
"@badrap/valita": "^0.4.6"
123
-
}
124
-
},
125
-
"node_modules/@babel/code-frame": {
126
-
"version": "7.27.1",
127
-
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
128
-
"integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
129
-
"dev": true,
130
-
"license": "MIT",
131
-
"dependencies": {
132
-
"@babel/helper-validator-identifier": "^7.27.1",
133
-
"js-tokens": "^4.0.0",
134
-
"picocolors": "^1.1.1"
135
-
},
136
-
"engines": {
137
-
"node": ">=6.9.0"
138
-
}
139
-
},
140
-
"node_modules/@babel/compat-data": {
141
-
"version": "7.28.4",
142
-
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz",
143
-
"integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==",
144
-
"dev": true,
145
-
"license": "MIT",
146
-
"engines": {
147
-
"node": ">=6.9.0"
148
-
}
149
-
},
150
-
"node_modules/@babel/core": {
151
-
"version": "7.28.4",
152
-
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz",
153
-
"integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==",
154
-
"dev": true,
155
-
"license": "MIT",
156
-
"dependencies": {
157
-
"@babel/code-frame": "^7.27.1",
158
-
"@babel/generator": "^7.28.3",
159
-
"@babel/helper-compilation-targets": "^7.27.2",
160
-
"@babel/helper-module-transforms": "^7.28.3",
161
-
"@babel/helpers": "^7.28.4",
162
-
"@babel/parser": "^7.28.4",
163
-
"@babel/template": "^7.27.2",
164
-
"@babel/traverse": "^7.28.4",
165
-
"@babel/types": "^7.28.4",
166
-
"@jridgewell/remapping": "^2.3.5",
167
-
"convert-source-map": "^2.0.0",
168
-
"debug": "^4.1.0",
169
-
"gensync": "^1.0.0-beta.2",
170
-
"json5": "^2.2.3",
171
-
"semver": "^6.3.1"
172
-
},
173
-
"engines": {
174
-
"node": ">=6.9.0"
175
-
},
176
-
"funding": {
177
-
"type": "opencollective",
178
-
"url": "https://opencollective.com/babel"
179
-
}
180
-
},
181
-
"node_modules/@babel/generator": {
182
-
"version": "7.28.3",
183
-
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz",
184
-
"integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==",
185
-
"dev": true,
186
-
"license": "MIT",
187
-
"dependencies": {
188
-
"@babel/parser": "^7.28.3",
189
-
"@babel/types": "^7.28.2",
190
-
"@jridgewell/gen-mapping": "^0.3.12",
191
-
"@jridgewell/trace-mapping": "^0.3.28",
192
-
"jsesc": "^3.0.2"
193
-
},
194
-
"engines": {
195
-
"node": ">=6.9.0"
196
-
}
197
-
},
198
-
"node_modules/@babel/helper-compilation-targets": {
199
-
"version": "7.27.2",
200
-
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
201
-
"integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
202
-
"dev": true,
203
-
"license": "MIT",
204
-
"dependencies": {
205
-
"@babel/compat-data": "^7.27.2",
206
-
"@babel/helper-validator-option": "^7.27.1",
207
-
"browserslist": "^4.24.0",
208
-
"lru-cache": "^5.1.1",
209
-
"semver": "^6.3.1"
210
-
},
211
-
"engines": {
212
-
"node": ">=6.9.0"
213
-
}
214
-
},
215
-
"node_modules/@babel/helper-globals": {
216
-
"version": "7.28.0",
217
-
"resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
218
-
"integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
219
-
"dev": true,
220
-
"license": "MIT",
221
-
"engines": {
222
-
"node": ">=6.9.0"
223
-
}
224
-
},
225
-
"node_modules/@babel/helper-module-imports": {
226
-
"version": "7.27.1",
227
-
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
228
-
"integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
229
-
"dev": true,
230
-
"license": "MIT",
231
-
"dependencies": {
232
-
"@babel/traverse": "^7.27.1",
233
-
"@babel/types": "^7.27.1"
234
-
},
235
-
"engines": {
236
-
"node": ">=6.9.0"
237
-
}
238
-
},
239
-
"node_modules/@babel/helper-module-transforms": {
240
-
"version": "7.28.3",
241
-
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz",
242
-
"integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==",
243
-
"dev": true,
244
-
"license": "MIT",
245
-
"dependencies": {
246
-
"@babel/helper-module-imports": "^7.27.1",
247
-
"@babel/helper-validator-identifier": "^7.27.1",
248
-
"@babel/traverse": "^7.28.3"
249
-
},
250
-
"engines": {
251
-
"node": ">=6.9.0"
252
-
},
253
-
"peerDependencies": {
254
-
"@babel/core": "^7.0.0"
255
-
}
256
-
},
257
-
"node_modules/@babel/helper-plugin-utils": {
258
-
"version": "7.27.1",
259
-
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz",
260
-
"integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==",
261
-
"dev": true,
262
-
"license": "MIT",
263
-
"engines": {
264
-
"node": ">=6.9.0"
265
-
}
266
-
},
267
-
"node_modules/@babel/helper-string-parser": {
268
-
"version": "7.27.1",
269
-
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
270
-
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
271
-
"dev": true,
272
-
"license": "MIT",
273
-
"engines": {
274
-
"node": ">=6.9.0"
275
-
}
276
-
},
277
-
"node_modules/@babel/helper-validator-identifier": {
278
-
"version": "7.27.1",
279
-
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
280
-
"integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
281
-
"dev": true,
282
-
"license": "MIT",
283
-
"engines": {
284
-
"node": ">=6.9.0"
285
-
}
286
-
},
287
-
"node_modules/@babel/helper-validator-option": {
288
-
"version": "7.27.1",
289
-
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
290
-
"integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
291
-
"dev": true,
292
-
"license": "MIT",
293
-
"engines": {
294
-
"node": ">=6.9.0"
295
-
}
296
-
},
297
-
"node_modules/@babel/helpers": {
298
-
"version": "7.28.4",
299
-
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz",
300
-
"integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==",
301
-
"dev": true,
302
-
"license": "MIT",
303
-
"dependencies": {
304
-
"@babel/template": "^7.27.2",
305
-
"@babel/types": "^7.28.4"
306
-
},
307
-
"engines": {
308
-
"node": ">=6.9.0"
309
-
}
310
-
},
311
-
"node_modules/@babel/parser": {
312
-
"version": "7.28.4",
313
-
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz",
314
-
"integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==",
315
-
"dev": true,
316
-
"license": "MIT",
317
-
"dependencies": {
318
-
"@babel/types": "^7.28.4"
319
-
},
320
-
"bin": {
321
-
"parser": "bin/babel-parser.js"
322
-
},
323
-
"engines": {
324
-
"node": ">=6.0.0"
325
-
}
326
-
},
327
-
"node_modules/@babel/plugin-transform-react-jsx-self": {
328
-
"version": "7.27.1",
329
-
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz",
330
-
"integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==",
331
-
"dev": true,
332
-
"license": "MIT",
333
-
"dependencies": {
334
-
"@babel/helper-plugin-utils": "^7.27.1"
335
-
},
336
-
"engines": {
337
-
"node": ">=6.9.0"
338
-
},
339
-
"peerDependencies": {
340
-
"@babel/core": "^7.0.0-0"
341
-
}
342
-
},
343
-
"node_modules/@babel/plugin-transform-react-jsx-source": {
344
-
"version": "7.27.1",
345
-
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz",
346
-
"integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==",
347
-
"dev": true,
348
-
"license": "MIT",
349
-
"dependencies": {
350
-
"@babel/helper-plugin-utils": "^7.27.1"
351
-
},
352
-
"engines": {
353
-
"node": ">=6.9.0"
354
-
},
355
-
"peerDependencies": {
356
-
"@babel/core": "^7.0.0-0"
357
-
}
358
-
},
359
-
"node_modules/@babel/template": {
360
-
"version": "7.27.2",
361
-
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
362
-
"integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
363
-
"dev": true,
364
-
"license": "MIT",
365
-
"dependencies": {
366
-
"@babel/code-frame": "^7.27.1",
367
-
"@babel/parser": "^7.27.2",
368
-
"@babel/types": "^7.27.1"
369
-
},
370
-
"engines": {
371
-
"node": ">=6.9.0"
372
-
}
373
-
},
374
-
"node_modules/@babel/traverse": {
375
-
"version": "7.28.4",
376
-
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz",
377
-
"integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==",
378
-
"dev": true,
379
-
"license": "MIT",
380
-
"dependencies": {
381
-
"@babel/code-frame": "^7.27.1",
382
-
"@babel/generator": "^7.28.3",
383
-
"@babel/helper-globals": "^7.28.0",
384
-
"@babel/parser": "^7.28.4",
385
-
"@babel/template": "^7.27.2",
386
-
"@babel/types": "^7.28.4",
387
-
"debug": "^4.3.1"
388
-
},
389
-
"engines": {
390
-
"node": ">=6.9.0"
391
-
}
392
-
},
393
-
"node_modules/@babel/types": {
394
-
"version": "7.28.4",
395
-
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz",
396
-
"integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==",
397
-
"dev": true,
398
-
"license": "MIT",
399
-
"dependencies": {
400
-
"@babel/helper-string-parser": "^7.27.1",
401
-
"@babel/helper-validator-identifier": "^7.27.1"
402
-
},
403
-
"engines": {
404
-
"node": ">=6.9.0"
405
-
}
406
-
},
407
-
"node_modules/@badrap/valita": {
408
-
"version": "0.4.6",
409
-
"resolved": "https://registry.npmjs.org/@badrap/valita/-/valita-0.4.6.tgz",
410
-
"integrity": "sha512-4kdqcjyxo/8RQ8ayjms47HCWZIF5981oE5nIenbfThKDxWXtEHKipAOWlflpPJzZx9y/JWYQkp18Awr7VuepFg==",
411
-
"license": "MIT",
412
-
"engines": {
413
-
"node": ">= 18"
414
-
}
415
-
},
416
-
"node_modules/@eslint-community/eslint-utils": {
417
-
"version": "4.9.0",
418
-
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz",
419
-
"integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==",
420
-
"dev": true,
421
-
"license": "MIT",
422
-
"dependencies": {
423
-
"eslint-visitor-keys": "^3.4.3"
424
-
},
425
-
"engines": {
426
-
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
427
-
},
428
-
"funding": {
429
-
"url": "https://opencollective.com/eslint"
430
-
},
431
-
"peerDependencies": {
432
-
"eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
433
-
}
434
-
},
435
-
"node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
436
-
"version": "3.4.3",
437
-
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
438
-
"integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
439
-
"dev": true,
440
-
"license": "Apache-2.0",
441
-
"engines": {
442
-
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
443
-
},
444
-
"funding": {
445
-
"url": "https://opencollective.com/eslint"
446
-
}
447
-
},
448
-
"node_modules/@eslint-community/regexpp": {
449
-
"version": "4.12.1",
450
-
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
451
-
"integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
452
-
"dev": true,
453
-
"license": "MIT",
454
-
"engines": {
455
-
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
456
-
}
457
-
},
458
-
"node_modules/@eslint/config-array": {
459
-
"version": "0.21.0",
460
-
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz",
461
-
"integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==",
462
-
"dev": true,
463
-
"license": "Apache-2.0",
464
-
"dependencies": {
465
-
"@eslint/object-schema": "^2.1.6",
466
-
"debug": "^4.3.1",
467
-
"minimatch": "^3.1.2"
468
-
},
469
-
"engines": {
470
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
471
-
}
472
-
},
473
-
"node_modules/@eslint/config-helpers": {
474
-
"version": "0.4.0",
475
-
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.0.tgz",
476
-
"integrity": "sha512-WUFvV4WoIwW8Bv0KeKCIIEgdSiFOsulyN0xrMu+7z43q/hkOLXjvb5u7UC9jDxvRzcrbEmuZBX5yJZz1741jog==",
477
-
"dev": true,
478
-
"license": "Apache-2.0",
479
-
"dependencies": {
480
-
"@eslint/core": "^0.16.0"
481
-
},
482
-
"engines": {
483
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
484
-
}
485
-
},
486
-
"node_modules/@eslint/core": {
487
-
"version": "0.16.0",
488
-
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.16.0.tgz",
489
-
"integrity": "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==",
490
-
"dev": true,
491
-
"license": "Apache-2.0",
492
-
"dependencies": {
493
-
"@types/json-schema": "^7.0.15"
494
-
},
495
-
"engines": {
496
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
497
-
}
498
-
},
499
-
"node_modules/@eslint/eslintrc": {
500
-
"version": "3.3.1",
501
-
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz",
502
-
"integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==",
503
-
"dev": true,
504
-
"license": "MIT",
505
-
"dependencies": {
506
-
"ajv": "^6.12.4",
507
-
"debug": "^4.3.2",
508
-
"espree": "^10.0.1",
509
-
"globals": "^14.0.0",
510
-
"ignore": "^5.2.0",
511
-
"import-fresh": "^3.2.1",
512
-
"js-yaml": "^4.1.0",
513
-
"minimatch": "^3.1.2",
514
-
"strip-json-comments": "^3.1.1"
515
-
},
516
-
"engines": {
517
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
518
-
},
519
-
"funding": {
520
-
"url": "https://opencollective.com/eslint"
521
-
}
522
-
},
523
-
"node_modules/@eslint/eslintrc/node_modules/globals": {
524
-
"version": "14.0.0",
525
-
"resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
526
-
"integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
527
-
"dev": true,
528
-
"license": "MIT",
529
-
"engines": {
530
-
"node": ">=18"
531
-
},
532
-
"funding": {
533
-
"url": "https://github.com/sponsors/sindresorhus"
534
-
}
535
-
},
536
-
"node_modules/@eslint/js": {
537
-
"version": "9.37.0",
538
-
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.37.0.tgz",
539
-
"integrity": "sha512-jaS+NJ+hximswBG6pjNX0uEJZkrT0zwpVi3BA3vX22aFGjJjmgSTSmPpZCRKmoBL5VY/M6p0xsSJx7rk7sy5gg==",
540
-
"dev": true,
541
-
"license": "MIT",
542
-
"engines": {
543
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
544
-
},
545
-
"funding": {
546
-
"url": "https://eslint.org/donate"
547
-
}
548
-
},
549
-
"node_modules/@eslint/object-schema": {
550
-
"version": "2.1.6",
551
-
"resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz",
552
-
"integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
553
-
"dev": true,
554
-
"license": "Apache-2.0",
555
-
"engines": {
556
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
557
-
}
558
-
},
559
-
"node_modules/@eslint/plugin-kit": {
560
-
"version": "0.4.0",
561
-
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.0.tgz",
562
-
"integrity": "sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==",
563
-
"dev": true,
564
-
"license": "Apache-2.0",
565
-
"dependencies": {
566
-
"@eslint/core": "^0.16.0",
567
-
"levn": "^0.4.1"
568
-
},
569
-
"engines": {
570
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
571
-
}
572
-
},
573
-
"node_modules/@humanfs/core": {
574
-
"version": "0.19.1",
575
-
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
576
-
"integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
577
-
"dev": true,
578
-
"license": "Apache-2.0",
579
-
"engines": {
580
-
"node": ">=18.18.0"
581
-
}
582
-
},
583
-
"node_modules/@humanfs/node": {
584
-
"version": "0.16.7",
585
-
"resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz",
586
-
"integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==",
587
-
"dev": true,
588
-
"license": "Apache-2.0",
589
-
"dependencies": {
590
-
"@humanfs/core": "^0.19.1",
591
-
"@humanwhocodes/retry": "^0.4.0"
592
-
},
593
-
"engines": {
594
-
"node": ">=18.18.0"
595
-
}
596
-
},
597
-
"node_modules/@humanwhocodes/module-importer": {
598
-
"version": "1.0.1",
599
-
"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
600
-
"integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
601
-
"dev": true,
602
-
"license": "Apache-2.0",
603
-
"engines": {
604
-
"node": ">=12.22"
605
-
},
606
-
"funding": {
607
-
"type": "github",
608
-
"url": "https://github.com/sponsors/nzakas"
609
-
}
610
-
},
611
-
"node_modules/@humanwhocodes/retry": {
612
-
"version": "0.4.3",
613
-
"resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
614
-
"integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
615
-
"dev": true,
616
-
"license": "Apache-2.0",
617
-
"engines": {
618
-
"node": ">=18.18"
619
-
},
620
-
"funding": {
621
-
"type": "github",
622
-
"url": "https://github.com/sponsors/nzakas"
623
-
}
624
-
},
625
-
"node_modules/@jridgewell/gen-mapping": {
626
-
"version": "0.3.13",
627
-
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
628
-
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
629
-
"dev": true,
630
-
"license": "MIT",
631
-
"dependencies": {
632
-
"@jridgewell/sourcemap-codec": "^1.5.0",
633
-
"@jridgewell/trace-mapping": "^0.3.24"
634
-
}
635
-
},
636
-
"node_modules/@jridgewell/remapping": {
637
-
"version": "2.3.5",
638
-
"resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
639
-
"integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
640
-
"dev": true,
641
-
"license": "MIT",
642
-
"dependencies": {
643
-
"@jridgewell/gen-mapping": "^0.3.5",
644
-
"@jridgewell/trace-mapping": "^0.3.24"
645
-
}
646
-
},
647
-
"node_modules/@jridgewell/resolve-uri": {
648
-
"version": "3.1.2",
649
-
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
650
-
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
651
-
"dev": true,
652
-
"license": "MIT",
653
-
"engines": {
654
-
"node": ">=6.0.0"
655
-
}
656
-
},
657
-
"node_modules/@jridgewell/sourcemap-codec": {
658
-
"version": "1.5.5",
659
-
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
660
-
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
661
-
"dev": true,
662
-
"license": "MIT"
663
-
},
664
-
"node_modules/@jridgewell/trace-mapping": {
665
-
"version": "0.3.31",
666
-
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
667
-
"integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
668
-
"dev": true,
669
-
"license": "MIT",
670
-
"dependencies": {
671
-
"@jridgewell/resolve-uri": "^3.1.0",
672
-
"@jridgewell/sourcemap-codec": "^1.4.14"
673
-
}
674
-
},
675
-
"node_modules/@nodelib/fs.scandir": {
676
-
"version": "2.1.5",
677
-
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
678
-
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
679
-
"dev": true,
680
-
"license": "MIT",
681
-
"dependencies": {
682
-
"@nodelib/fs.stat": "2.0.5",
683
-
"run-parallel": "^1.1.9"
684
-
},
685
-
"engines": {
686
-
"node": ">= 8"
687
-
}
688
-
},
689
-
"node_modules/@nodelib/fs.stat": {
690
-
"version": "2.0.5",
691
-
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
692
-
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
693
-
"dev": true,
694
-
"license": "MIT",
695
-
"engines": {
696
-
"node": ">= 8"
697
-
}
698
-
},
699
-
"node_modules/@nodelib/fs.walk": {
700
-
"version": "1.2.8",
701
-
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
702
-
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
703
-
"dev": true,
704
-
"license": "MIT",
705
-
"dependencies": {
706
-
"@nodelib/fs.scandir": "2.1.5",
707
-
"fastq": "^1.6.0"
708
-
},
709
-
"engines": {
710
-
"node": ">= 8"
711
-
}
712
-
},
713
-
"node_modules/@oxc-project/runtime": {
714
-
"version": "0.92.0",
715
-
"resolved": "https://registry.npmjs.org/@oxc-project/runtime/-/runtime-0.92.0.tgz",
716
-
"integrity": "sha512-Z7x2dZOmznihvdvCvLKMl+nswtOSVxS2H2ocar+U9xx6iMfTp0VGIrX6a4xB1v80IwOPC7dT1LXIJrY70Xu3Jw==",
717
-
"dev": true,
718
-
"license": "MIT",
719
-
"engines": {
720
-
"node": "^20.19.0 || >=22.12.0"
721
-
}
722
-
},
723
-
"node_modules/@oxc-project/types": {
724
-
"version": "0.93.0",
725
-
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.93.0.tgz",
726
-
"integrity": "sha512-yNtwmWZIBtJsMr5TEfoZFDxIWV6OdScOpza/f5YxbqUMJk+j6QX3Cf3jgZShGEFYWQJ5j9mJ6jM0tZHu2J9Yrg==",
727
-
"dev": true,
728
-
"license": "MIT",
729
-
"funding": {
730
-
"url": "https://github.com/sponsors/Boshen"
731
-
}
732
-
},
733
-
"node_modules/@rolldown/binding-darwin-arm64": {
734
-
"version": "1.0.0-beta.41",
735
-
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-beta.41.tgz",
736
-
"integrity": "sha512-XGCzqfjdk7550PlyZRTBKbypXrB7ATtXhw/+bjtxnklLQs0mKP/XkQVOKyn9qGKSlvH8I56JLYryVxl0PCvSNw==",
737
-
"cpu": [
738
-
"arm64"
739
-
],
740
-
"dev": true,
741
-
"license": "MIT",
742
-
"optional": true,
743
-
"os": [
744
-
"darwin"
745
-
],
746
-
"engines": {
747
-
"node": "^20.19.0 || >=22.12.0"
748
-
}
749
-
},
750
-
"node_modules/@rolldown/pluginutils": {
751
-
"version": "1.0.0-beta.38",
752
-
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.38.tgz",
753
-
"integrity": "sha512-N/ICGKleNhA5nc9XXQG/kkKHJ7S55u0x0XUJbbkmdCnFuoRkM1Il12q9q0eX19+M7KKUEPw/daUPIRnxhcxAIw==",
754
-
"dev": true,
755
-
"license": "MIT"
756
-
},
757
-
"node_modules/@standard-schema/spec": {
758
-
"version": "1.0.0",
759
-
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz",
760
-
"integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==",
761
-
"license": "MIT"
762
-
},
763
-
"node_modules/@types/babel__core": {
764
-
"version": "7.20.5",
765
-
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
766
-
"integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
767
-
"dev": true,
768
-
"license": "MIT",
769
-
"dependencies": {
770
-
"@babel/parser": "^7.20.7",
771
-
"@babel/types": "^7.20.7",
772
-
"@types/babel__generator": "*",
773
-
"@types/babel__template": "*",
774
-
"@types/babel__traverse": "*"
775
-
}
776
-
},
777
-
"node_modules/@types/babel__generator": {
778
-
"version": "7.27.0",
779
-
"resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
780
-
"integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
781
-
"dev": true,
782
-
"license": "MIT",
783
-
"dependencies": {
784
-
"@babel/types": "^7.0.0"
785
-
}
786
-
},
787
-
"node_modules/@types/babel__template": {
788
-
"version": "7.4.4",
789
-
"resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
790
-
"integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
791
-
"dev": true,
792
-
"license": "MIT",
793
-
"dependencies": {
794
-
"@babel/parser": "^7.1.0",
795
-
"@babel/types": "^7.0.0"
796
-
}
797
-
},
798
-
"node_modules/@types/babel__traverse": {
799
-
"version": "7.28.0",
800
-
"resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
801
-
"integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
802
-
"dev": true,
803
-
"license": "MIT",
804
-
"dependencies": {
805
-
"@babel/types": "^7.28.2"
806
-
}
807
-
},
808
-
"node_modules/@types/estree": {
809
-
"version": "1.0.8",
810
-
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
811
-
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
812
-
"dev": true,
813
-
"license": "MIT"
814
-
},
815
-
"node_modules/@types/json-schema": {
816
-
"version": "7.0.15",
817
-
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
818
-
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
819
-
"dev": true,
820
-
"license": "MIT"
821
-
},
822
-
"node_modules/@types/node": {
823
-
"version": "24.7.0",
824
-
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.7.0.tgz",
825
-
"integrity": "sha512-IbKooQVqUBrlzWTi79E8Fw78l8k1RNtlDDNWsFZs7XonuQSJ8oNYfEeclhprUldXISRMLzBpILuKgPlIxm+/Yw==",
826
-
"dev": true,
827
-
"license": "MIT",
828
-
"dependencies": {
829
-
"undici-types": "~7.14.0"
830
-
}
831
-
},
832
-
"node_modules/@types/react": {
833
-
"version": "19.2.2",
834
-
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz",
835
-
"integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==",
836
-
"dev": true,
837
-
"license": "MIT",
838
-
"dependencies": {
839
-
"csstype": "^3.0.2"
840
-
}
841
-
},
842
-
"node_modules/@types/react-dom": {
843
-
"version": "19.2.1",
844
-
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.1.tgz",
845
-
"integrity": "sha512-/EEvYBdT3BflCWvTMO7YkYBHVE9Ci6XdqZciZANQgKpaiDRGOLIlRo91jbTNRQjgPFWVaRxcYc0luVNFitz57A==",
846
-
"dev": true,
847
-
"license": "MIT",
848
-
"peerDependencies": {
849
-
"@types/react": "^19.2.0"
850
-
}
851
-
},
852
-
"node_modules/@typescript-eslint/eslint-plugin": {
853
-
"version": "8.46.0",
854
-
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.0.tgz",
855
-
"integrity": "sha512-hA8gxBq4ukonVXPy0OKhiaUh/68D0E88GSmtC1iAEnGaieuDi38LhS7jdCHRLi6ErJBNDGCzvh5EnzdPwUc0DA==",
856
-
"dev": true,
857
-
"license": "MIT",
858
-
"dependencies": {
859
-
"@eslint-community/regexpp": "^4.10.0",
860
-
"@typescript-eslint/scope-manager": "8.46.0",
861
-
"@typescript-eslint/type-utils": "8.46.0",
862
-
"@typescript-eslint/utils": "8.46.0",
863
-
"@typescript-eslint/visitor-keys": "8.46.0",
864
-
"graphemer": "^1.4.0",
865
-
"ignore": "^7.0.0",
866
-
"natural-compare": "^1.4.0",
867
-
"ts-api-utils": "^2.1.0"
868
-
},
869
-
"engines": {
870
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
871
-
},
872
-
"funding": {
873
-
"type": "opencollective",
874
-
"url": "https://opencollective.com/typescript-eslint"
875
-
},
876
-
"peerDependencies": {
877
-
"@typescript-eslint/parser": "^8.46.0",
878
-
"eslint": "^8.57.0 || ^9.0.0",
879
-
"typescript": ">=4.8.4 <6.0.0"
880
-
}
881
-
},
882
-
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
883
-
"version": "7.0.5",
884
-
"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
885
-
"integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
886
-
"dev": true,
887
-
"license": "MIT",
888
-
"engines": {
889
-
"node": ">= 4"
890
-
}
891
-
},
892
-
"node_modules/@typescript-eslint/parser": {
893
-
"version": "8.46.0",
894
-
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.0.tgz",
895
-
"integrity": "sha512-n1H6IcDhmmUEG7TNVSspGmiHHutt7iVKtZwRppD7e04wha5MrkV1h3pti9xQLcCMt6YWsncpoT0HMjkH1FNwWQ==",
896
-
"dev": true,
897
-
"license": "MIT",
898
-
"dependencies": {
899
-
"@typescript-eslint/scope-manager": "8.46.0",
900
-
"@typescript-eslint/types": "8.46.0",
901
-
"@typescript-eslint/typescript-estree": "8.46.0",
902
-
"@typescript-eslint/visitor-keys": "8.46.0",
903
-
"debug": "^4.3.4"
904
-
},
905
-
"engines": {
906
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
907
-
},
908
-
"funding": {
909
-
"type": "opencollective",
910
-
"url": "https://opencollective.com/typescript-eslint"
911
-
},
912
-
"peerDependencies": {
913
-
"eslint": "^8.57.0 || ^9.0.0",
914
-
"typescript": ">=4.8.4 <6.0.0"
915
-
}
916
-
},
917
-
"node_modules/@typescript-eslint/project-service": {
918
-
"version": "8.46.0",
919
-
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.0.tgz",
920
-
"integrity": "sha512-OEhec0mH+U5Je2NZOeK1AbVCdm0ChyapAyTeXVIYTPXDJ3F07+cu87PPXcGoYqZ7M9YJVvFnfpGg1UmCIqM+QQ==",
921
-
"dev": true,
922
-
"license": "MIT",
923
-
"dependencies": {
924
-
"@typescript-eslint/tsconfig-utils": "^8.46.0",
925
-
"@typescript-eslint/types": "^8.46.0",
926
-
"debug": "^4.3.4"
927
-
},
928
-
"engines": {
929
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
930
-
},
931
-
"funding": {
932
-
"type": "opencollective",
933
-
"url": "https://opencollective.com/typescript-eslint"
934
-
},
935
-
"peerDependencies": {
936
-
"typescript": ">=4.8.4 <6.0.0"
937
-
}
938
-
},
939
-
"node_modules/@typescript-eslint/scope-manager": {
940
-
"version": "8.46.0",
941
-
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.0.tgz",
942
-
"integrity": "sha512-lWETPa9XGcBes4jqAMYD9fW0j4n6hrPtTJwWDmtqgFO/4HF4jmdH/Q6wggTw5qIT5TXjKzbt7GsZUBnWoO3dqw==",
943
-
"dev": true,
944
-
"license": "MIT",
945
-
"dependencies": {
946
-
"@typescript-eslint/types": "8.46.0",
947
-
"@typescript-eslint/visitor-keys": "8.46.0"
948
-
},
949
-
"engines": {
950
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
951
-
},
952
-
"funding": {
953
-
"type": "opencollective",
954
-
"url": "https://opencollective.com/typescript-eslint"
955
-
}
956
-
},
957
-
"node_modules/@typescript-eslint/tsconfig-utils": {
958
-
"version": "8.46.0",
959
-
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.0.tgz",
960
-
"integrity": "sha512-WrYXKGAHY836/N7zoK/kzi6p8tXFhasHh8ocFL9VZSAkvH956gfeRfcnhs3xzRy8qQ/dq3q44v1jvQieMFg2cw==",
961
-
"dev": true,
962
-
"license": "MIT",
963
-
"engines": {
964
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
965
-
},
966
-
"funding": {
967
-
"type": "opencollective",
968
-
"url": "https://opencollective.com/typescript-eslint"
969
-
},
970
-
"peerDependencies": {
971
-
"typescript": ">=4.8.4 <6.0.0"
972
-
}
973
-
},
974
-
"node_modules/@typescript-eslint/type-utils": {
975
-
"version": "8.46.0",
976
-
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.0.tgz",
977
-
"integrity": "sha512-hy+lvYV1lZpVs2jRaEYvgCblZxUoJiPyCemwbQZ+NGulWkQRy0HRPYAoef/CNSzaLt+MLvMptZsHXHlkEilaeg==",
978
-
"dev": true,
979
-
"license": "MIT",
980
-
"dependencies": {
981
-
"@typescript-eslint/types": "8.46.0",
982
-
"@typescript-eslint/typescript-estree": "8.46.0",
983
-
"@typescript-eslint/utils": "8.46.0",
984
-
"debug": "^4.3.4",
985
-
"ts-api-utils": "^2.1.0"
986
-
},
987
-
"engines": {
988
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
989
-
},
990
-
"funding": {
991
-
"type": "opencollective",
992
-
"url": "https://opencollective.com/typescript-eslint"
993
-
},
994
-
"peerDependencies": {
995
-
"eslint": "^8.57.0 || ^9.0.0",
996
-
"typescript": ">=4.8.4 <6.0.0"
997
-
}
998
-
},
999
-
"node_modules/@typescript-eslint/types": {
1000
-
"version": "8.46.0",
1001
-
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.0.tgz",
1002
-
"integrity": "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA==",
1003
-
"dev": true,
1004
-
"license": "MIT",
1005
-
"engines": {
1006
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1007
-
},
1008
-
"funding": {
1009
-
"type": "opencollective",
1010
-
"url": "https://opencollective.com/typescript-eslint"
1011
-
}
1012
-
},
1013
-
"node_modules/@typescript-eslint/typescript-estree": {
1014
-
"version": "8.46.0",
1015
-
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.0.tgz",
1016
-
"integrity": "sha512-ekDCUfVpAKWJbRfm8T1YRrCot1KFxZn21oV76v5Fj4tr7ELyk84OS+ouvYdcDAwZL89WpEkEj2DKQ+qg//+ucg==",
1017
-
"dev": true,
1018
-
"license": "MIT",
1019
-
"dependencies": {
1020
-
"@typescript-eslint/project-service": "8.46.0",
1021
-
"@typescript-eslint/tsconfig-utils": "8.46.0",
1022
-
"@typescript-eslint/types": "8.46.0",
1023
-
"@typescript-eslint/visitor-keys": "8.46.0",
1024
-
"debug": "^4.3.4",
1025
-
"fast-glob": "^3.3.2",
1026
-
"is-glob": "^4.0.3",
1027
-
"minimatch": "^9.0.4",
1028
-
"semver": "^7.6.0",
1029
-
"ts-api-utils": "^2.1.0"
1030
-
},
1031
-
"engines": {
1032
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1033
-
},
1034
-
"funding": {
1035
-
"type": "opencollective",
1036
-
"url": "https://opencollective.com/typescript-eslint"
1037
-
},
1038
-
"peerDependencies": {
1039
-
"typescript": ">=4.8.4 <6.0.0"
1040
-
}
1041
-
},
1042
-
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
1043
-
"version": "2.0.2",
1044
-
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
1045
-
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
1046
-
"dev": true,
1047
-
"license": "MIT",
1048
-
"dependencies": {
1049
-
"balanced-match": "^1.0.0"
1050
-
}
1051
-
},
1052
-
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
1053
-
"version": "9.0.5",
1054
-
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
1055
-
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
1056
-
"dev": true,
1057
-
"license": "ISC",
1058
-
"dependencies": {
1059
-
"brace-expansion": "^2.0.1"
1060
-
},
1061
-
"engines": {
1062
-
"node": ">=16 || 14 >=14.17"
1063
-
},
1064
-
"funding": {
1065
-
"url": "https://github.com/sponsors/isaacs"
1066
-
}
1067
-
},
1068
-
"node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
1069
-
"version": "7.7.3",
1070
-
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
1071
-
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
1072
-
"dev": true,
1073
-
"license": "ISC",
1074
-
"bin": {
1075
-
"semver": "bin/semver.js"
1076
-
},
1077
-
"engines": {
1078
-
"node": ">=10"
1079
-
}
1080
-
},
1081
-
"node_modules/@typescript-eslint/utils": {
1082
-
"version": "8.46.0",
1083
-
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.0.tgz",
1084
-
"integrity": "sha512-nD6yGWPj1xiOm4Gk0k6hLSZz2XkNXhuYmyIrOWcHoPuAhjT9i5bAG+xbWPgFeNR8HPHHtpNKdYUXJl/D3x7f5g==",
1085
-
"dev": true,
1086
-
"license": "MIT",
1087
-
"dependencies": {
1088
-
"@eslint-community/eslint-utils": "^4.7.0",
1089
-
"@typescript-eslint/scope-manager": "8.46.0",
1090
-
"@typescript-eslint/types": "8.46.0",
1091
-
"@typescript-eslint/typescript-estree": "8.46.0"
1092
-
},
1093
-
"engines": {
1094
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1095
-
},
1096
-
"funding": {
1097
-
"type": "opencollective",
1098
-
"url": "https://opencollective.com/typescript-eslint"
1099
-
},
1100
-
"peerDependencies": {
1101
-
"eslint": "^8.57.0 || ^9.0.0",
1102
-
"typescript": ">=4.8.4 <6.0.0"
1103
-
}
1104
-
},
1105
-
"node_modules/@typescript-eslint/visitor-keys": {
1106
-
"version": "8.46.0",
1107
-
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.0.tgz",
1108
-
"integrity": "sha512-FrvMpAK+hTbFy7vH5j1+tMYHMSKLE6RzluFJlkFNKD0p9YsUT75JlBSmr5so3QRzvMwU5/bIEdeNrxm8du8l3Q==",
1109
-
"dev": true,
1110
-
"license": "MIT",
1111
-
"dependencies": {
1112
-
"@typescript-eslint/types": "8.46.0",
1113
-
"eslint-visitor-keys": "^4.2.1"
1114
-
},
1115
-
"engines": {
1116
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1117
-
},
1118
-
"funding": {
1119
-
"type": "opencollective",
1120
-
"url": "https://opencollective.com/typescript-eslint"
1121
-
}
1122
-
},
1123
-
"node_modules/@vitejs/plugin-react": {
1124
-
"version": "5.0.4",
1125
-
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.0.4.tgz",
1126
-
"integrity": "sha512-La0KD0vGkVkSk6K+piWDKRUyg8Rl5iAIKRMH0vMJI0Eg47bq1eOxmoObAaQG37WMW9MSyk7Cs8EIWwJC1PtzKA==",
1127
-
"dev": true,
1128
-
"license": "MIT",
1129
-
"dependencies": {
1130
-
"@babel/core": "^7.28.4",
1131
-
"@babel/plugin-transform-react-jsx-self": "^7.27.1",
1132
-
"@babel/plugin-transform-react-jsx-source": "^7.27.1",
1133
-
"@rolldown/pluginutils": "1.0.0-beta.38",
1134
-
"@types/babel__core": "^7.20.5",
1135
-
"react-refresh": "^0.17.0"
1136
-
},
1137
-
"engines": {
1138
-
"node": "^20.19.0 || >=22.12.0"
1139
-
},
1140
-
"peerDependencies": {
1141
-
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
1142
-
}
1143
-
},
1144
-
"node_modules/acorn": {
1145
-
"version": "8.15.0",
1146
-
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
1147
-
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
1148
-
"dev": true,
1149
-
"license": "MIT",
1150
-
"bin": {
1151
-
"acorn": "bin/acorn"
1152
-
},
1153
-
"engines": {
1154
-
"node": ">=0.4.0"
1155
-
}
1156
-
},
1157
-
"node_modules/acorn-jsx": {
1158
-
"version": "5.3.2",
1159
-
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
1160
-
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
1161
-
"dev": true,
1162
-
"license": "MIT",
1163
-
"peerDependencies": {
1164
-
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
1165
-
}
1166
-
},
1167
-
"node_modules/ajv": {
1168
-
"version": "6.12.6",
1169
-
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
1170
-
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
1171
-
"dev": true,
1172
-
"license": "MIT",
1173
-
"dependencies": {
1174
-
"fast-deep-equal": "^3.1.1",
1175
-
"fast-json-stable-stringify": "^2.0.0",
1176
-
"json-schema-traverse": "^0.4.1",
1177
-
"uri-js": "^4.2.2"
1178
-
},
1179
-
"funding": {
1180
-
"type": "github",
1181
-
"url": "https://github.com/sponsors/epoberezkin"
1182
-
}
1183
-
},
1184
-
"node_modules/ansi-styles": {
1185
-
"version": "4.3.0",
1186
-
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
1187
-
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
1188
-
"dev": true,
1189
-
"license": "MIT",
1190
-
"dependencies": {
1191
-
"color-convert": "^2.0.1"
1192
-
},
1193
-
"engines": {
1194
-
"node": ">=8"
1195
-
},
1196
-
"funding": {
1197
-
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
1198
-
}
1199
-
},
1200
-
"node_modules/ansis": {
1201
-
"version": "4.2.0",
1202
-
"resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz",
1203
-
"integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==",
1204
-
"dev": true,
1205
-
"license": "ISC",
1206
-
"engines": {
1207
-
"node": ">=14"
1208
-
}
1209
-
},
1210
-
"node_modules/argparse": {
1211
-
"version": "2.0.1",
1212
-
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
1213
-
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
1214
-
"dev": true,
1215
-
"license": "Python-2.0"
1216
-
},
1217
-
"node_modules/balanced-match": {
1218
-
"version": "1.0.2",
1219
-
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
1220
-
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
1221
-
"dev": true,
1222
-
"license": "MIT"
1223
-
},
1224
-
"node_modules/baseline-browser-mapping": {
1225
-
"version": "2.8.13",
1226
-
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.13.tgz",
1227
-
"integrity": "sha512-7s16KR8io8nIBWQyCYhmFhd+ebIzb9VKTzki+wOJXHTxTnV6+mFGH3+Jwn1zoKaY9/H9T/0BcKCZnzXljPnpSQ==",
1228
-
"dev": true,
1229
-
"license": "Apache-2.0",
1230
-
"bin": {
1231
-
"baseline-browser-mapping": "dist/cli.js"
1232
-
}
1233
-
},
1234
-
"node_modules/brace-expansion": {
1235
-
"version": "1.1.12",
1236
-
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
1237
-
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
1238
-
"dev": true,
1239
-
"license": "MIT",
1240
-
"dependencies": {
1241
-
"balanced-match": "^1.0.0",
1242
-
"concat-map": "0.0.1"
1243
-
}
1244
-
},
1245
-
"node_modules/braces": {
1246
-
"version": "3.0.3",
1247
-
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
1248
-
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
1249
-
"dev": true,
1250
-
"license": "MIT",
1251
-
"dependencies": {
1252
-
"fill-range": "^7.1.1"
1253
-
},
1254
-
"engines": {
1255
-
"node": ">=8"
1256
-
}
1257
-
},
1258
-
"node_modules/browserslist": {
1259
-
"version": "4.26.3",
1260
-
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.3.tgz",
1261
-
"integrity": "sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==",
1262
-
"dev": true,
1263
-
"funding": [
1264
-
{
1265
-
"type": "opencollective",
1266
-
"url": "https://opencollective.com/browserslist"
1267
-
},
1268
-
{
1269
-
"type": "tidelift",
1270
-
"url": "https://tidelift.com/funding/github/npm/browserslist"
1271
-
},
1272
-
{
1273
-
"type": "github",
1274
-
"url": "https://github.com/sponsors/ai"
1275
-
}
1276
-
],
1277
-
"license": "MIT",
1278
-
"dependencies": {
1279
-
"baseline-browser-mapping": "^2.8.9",
1280
-
"caniuse-lite": "^1.0.30001746",
1281
-
"electron-to-chromium": "^1.5.227",
1282
-
"node-releases": "^2.0.21",
1283
-
"update-browserslist-db": "^1.1.3"
1284
-
},
1285
-
"bin": {
1286
-
"browserslist": "cli.js"
1287
-
},
1288
-
"engines": {
1289
-
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
1290
-
}
1291
-
},
1292
-
"node_modules/callsites": {
1293
-
"version": "3.1.0",
1294
-
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
1295
-
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
1296
-
"dev": true,
1297
-
"license": "MIT",
1298
-
"engines": {
1299
-
"node": ">=6"
1300
-
}
1301
-
},
1302
-
"node_modules/caniuse-lite": {
1303
-
"version": "1.0.30001748",
1304
-
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001748.tgz",
1305
-
"integrity": "sha512-5P5UgAr0+aBmNiplks08JLw+AW/XG/SurlgZLgB1dDLfAw7EfRGxIwzPHxdSCGY/BTKDqIVyJL87cCN6s0ZR0w==",
1306
-
"dev": true,
1307
-
"funding": [
1308
-
{
1309
-
"type": "opencollective",
1310
-
"url": "https://opencollective.com/browserslist"
1311
-
},
1312
-
{
1313
-
"type": "tidelift",
1314
-
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
1315
-
},
1316
-
{
1317
-
"type": "github",
1318
-
"url": "https://github.com/sponsors/ai"
1319
-
}
1320
-
],
1321
-
"license": "CC-BY-4.0"
1322
-
},
1323
-
"node_modules/chalk": {
1324
-
"version": "4.1.2",
1325
-
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
1326
-
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
1327
-
"dev": true,
1328
-
"license": "MIT",
1329
-
"dependencies": {
1330
-
"ansi-styles": "^4.1.0",
1331
-
"supports-color": "^7.1.0"
1332
-
},
1333
-
"engines": {
1334
-
"node": ">=10"
1335
-
},
1336
-
"funding": {
1337
-
"url": "https://github.com/chalk/chalk?sponsor=1"
1338
-
}
1339
-
},
1340
-
"node_modules/color-convert": {
1341
-
"version": "2.0.1",
1342
-
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
1343
-
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
1344
-
"dev": true,
1345
-
"license": "MIT",
1346
-
"dependencies": {
1347
-
"color-name": "~1.1.4"
1348
-
},
1349
-
"engines": {
1350
-
"node": ">=7.0.0"
1351
-
}
1352
-
},
1353
-
"node_modules/color-name": {
1354
-
"version": "1.1.4",
1355
-
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
1356
-
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
1357
-
"dev": true,
1358
-
"license": "MIT"
1359
-
},
1360
-
"node_modules/concat-map": {
1361
-
"version": "0.0.1",
1362
-
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
1363
-
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
1364
-
"dev": true,
1365
-
"license": "MIT"
1366
-
},
1367
-
"node_modules/convert-source-map": {
1368
-
"version": "2.0.0",
1369
-
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
1370
-
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
1371
-
"dev": true,
1372
-
"license": "MIT"
1373
-
},
1374
-
"node_modules/cross-spawn": {
1375
-
"version": "7.0.6",
1376
-
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
1377
-
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
1378
-
"dev": true,
1379
-
"license": "MIT",
1380
-
"dependencies": {
1381
-
"path-key": "^3.1.0",
1382
-
"shebang-command": "^2.0.0",
1383
-
"which": "^2.0.1"
1384
-
},
1385
-
"engines": {
1386
-
"node": ">= 8"
1387
-
}
1388
-
},
1389
-
"node_modules/csstype": {
1390
-
"version": "3.1.3",
1391
-
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
1392
-
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
1393
-
"dev": true,
1394
-
"license": "MIT"
1395
-
},
1396
-
"node_modules/debug": {
1397
-
"version": "4.4.3",
1398
-
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
1399
-
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
1400
-
"dev": true,
1401
-
"license": "MIT",
1402
-
"dependencies": {
1403
-
"ms": "^2.1.3"
1404
-
},
1405
-
"engines": {
1406
-
"node": ">=6.0"
1407
-
},
1408
-
"peerDependenciesMeta": {
1409
-
"supports-color": {
1410
-
"optional": true
1411
-
}
1412
-
}
1413
-
},
1414
-
"node_modules/deep-is": {
1415
-
"version": "0.1.4",
1416
-
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
1417
-
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
1418
-
"dev": true,
1419
-
"license": "MIT"
1420
-
},
1421
-
"node_modules/detect-libc": {
1422
-
"version": "2.1.2",
1423
-
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
1424
-
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
1425
-
"dev": true,
1426
-
"license": "Apache-2.0",
1427
-
"engines": {
1428
-
"node": ">=8"
1429
-
}
1430
-
},
1431
-
"node_modules/electron-to-chromium": {
1432
-
"version": "1.5.232",
1433
-
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.232.tgz",
1434
-
"integrity": "sha512-ENirSe7wf8WzyPCibqKUG1Cg43cPaxH4wRR7AJsX7MCABCHBIOFqvaYODSLKUuZdraxUTHRE/0A2Aq8BYKEHOg==",
1435
-
"dev": true,
1436
-
"license": "ISC"
1437
-
},
1438
-
"node_modules/escalade": {
1439
-
"version": "3.2.0",
1440
-
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
1441
-
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
1442
-
"dev": true,
1443
-
"license": "MIT",
1444
-
"engines": {
1445
-
"node": ">=6"
1446
-
}
1447
-
},
1448
-
"node_modules/escape-string-regexp": {
1449
-
"version": "4.0.0",
1450
-
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
1451
-
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
1452
-
"dev": true,
1453
-
"license": "MIT",
1454
-
"engines": {
1455
-
"node": ">=10"
1456
-
},
1457
-
"funding": {
1458
-
"url": "https://github.com/sponsors/sindresorhus"
1459
-
}
1460
-
},
1461
-
"node_modules/eslint": {
1462
-
"version": "9.37.0",
1463
-
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.37.0.tgz",
1464
-
"integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==",
1465
-
"dev": true,
1466
-
"license": "MIT",
1467
-
"dependencies": {
1468
-
"@eslint-community/eslint-utils": "^4.8.0",
1469
-
"@eslint-community/regexpp": "^4.12.1",
1470
-
"@eslint/config-array": "^0.21.0",
1471
-
"@eslint/config-helpers": "^0.4.0",
1472
-
"@eslint/core": "^0.16.0",
1473
-
"@eslint/eslintrc": "^3.3.1",
1474
-
"@eslint/js": "9.37.0",
1475
-
"@eslint/plugin-kit": "^0.4.0",
1476
-
"@humanfs/node": "^0.16.6",
1477
-
"@humanwhocodes/module-importer": "^1.0.1",
1478
-
"@humanwhocodes/retry": "^0.4.2",
1479
-
"@types/estree": "^1.0.6",
1480
-
"@types/json-schema": "^7.0.15",
1481
-
"ajv": "^6.12.4",
1482
-
"chalk": "^4.0.0",
1483
-
"cross-spawn": "^7.0.6",
1484
-
"debug": "^4.3.2",
1485
-
"escape-string-regexp": "^4.0.0",
1486
-
"eslint-scope": "^8.4.0",
1487
-
"eslint-visitor-keys": "^4.2.1",
1488
-
"espree": "^10.4.0",
1489
-
"esquery": "^1.5.0",
1490
-
"esutils": "^2.0.2",
1491
-
"fast-deep-equal": "^3.1.3",
1492
-
"file-entry-cache": "^8.0.0",
1493
-
"find-up": "^5.0.0",
1494
-
"glob-parent": "^6.0.2",
1495
-
"ignore": "^5.2.0",
1496
-
"imurmurhash": "^0.1.4",
1497
-
"is-glob": "^4.0.0",
1498
-
"json-stable-stringify-without-jsonify": "^1.0.1",
1499
-
"lodash.merge": "^4.6.2",
1500
-
"minimatch": "^3.1.2",
1501
-
"natural-compare": "^1.4.0",
1502
-
"optionator": "^0.9.3"
1503
-
},
1504
-
"bin": {
1505
-
"eslint": "bin/eslint.js"
1506
-
},
1507
-
"engines": {
1508
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1509
-
},
1510
-
"funding": {
1511
-
"url": "https://eslint.org/donate"
1512
-
},
1513
-
"peerDependencies": {
1514
-
"jiti": "*"
1515
-
},
1516
-
"peerDependenciesMeta": {
1517
-
"jiti": {
1518
-
"optional": true
1519
-
}
1520
-
}
1521
-
},
1522
-
"node_modules/eslint-plugin-react-hooks": {
1523
-
"version": "5.2.0",
1524
-
"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz",
1525
-
"integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==",
1526
-
"dev": true,
1527
-
"license": "MIT",
1528
-
"engines": {
1529
-
"node": ">=10"
1530
-
},
1531
-
"peerDependencies": {
1532
-
"eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
1533
-
}
1534
-
},
1535
-
"node_modules/eslint-plugin-react-refresh": {
1536
-
"version": "0.4.23",
1537
-
"resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.23.tgz",
1538
-
"integrity": "sha512-G4j+rv0NmbIR45kni5xJOrYvCtyD3/7LjpVH8MPPcudXDcNu8gv+4ATTDXTtbRR8rTCM5HxECvCSsRmxKnWDsA==",
1539
-
"dev": true,
1540
-
"license": "MIT",
1541
-
"peerDependencies": {
1542
-
"eslint": ">=8.40"
1543
-
}
1544
-
},
1545
-
"node_modules/eslint-scope": {
1546
-
"version": "8.4.0",
1547
-
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
1548
-
"integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
1549
-
"dev": true,
1550
-
"license": "BSD-2-Clause",
1551
-
"dependencies": {
1552
-
"esrecurse": "^4.3.0",
1553
-
"estraverse": "^5.2.0"
1554
-
},
1555
-
"engines": {
1556
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1557
-
},
1558
-
"funding": {
1559
-
"url": "https://opencollective.com/eslint"
1560
-
}
1561
-
},
1562
-
"node_modules/eslint-visitor-keys": {
1563
-
"version": "4.2.1",
1564
-
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
1565
-
"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
1566
-
"dev": true,
1567
-
"license": "Apache-2.0",
1568
-
"engines": {
1569
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1570
-
},
1571
-
"funding": {
1572
-
"url": "https://opencollective.com/eslint"
1573
-
}
1574
-
},
1575
-
"node_modules/esm-env": {
1576
-
"version": "1.2.2",
1577
-
"resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz",
1578
-
"integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==",
1579
-
"license": "MIT"
1580
-
},
1581
-
"node_modules/espree": {
1582
-
"version": "10.4.0",
1583
-
"resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
1584
-
"integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
1585
-
"dev": true,
1586
-
"license": "BSD-2-Clause",
1587
-
"dependencies": {
1588
-
"acorn": "^8.15.0",
1589
-
"acorn-jsx": "^5.3.2",
1590
-
"eslint-visitor-keys": "^4.2.1"
1591
-
},
1592
-
"engines": {
1593
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1594
-
},
1595
-
"funding": {
1596
-
"url": "https://opencollective.com/eslint"
1597
-
}
1598
-
},
1599
-
"node_modules/esquery": {
1600
-
"version": "1.6.0",
1601
-
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
1602
-
"integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
1603
-
"dev": true,
1604
-
"license": "BSD-3-Clause",
1605
-
"dependencies": {
1606
-
"estraverse": "^5.1.0"
1607
-
},
1608
-
"engines": {
1609
-
"node": ">=0.10"
1610
-
}
1611
-
},
1612
-
"node_modules/esrecurse": {
1613
-
"version": "4.3.0",
1614
-
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
1615
-
"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
1616
-
"dev": true,
1617
-
"license": "BSD-2-Clause",
1618
-
"dependencies": {
1619
-
"estraverse": "^5.2.0"
1620
-
},
1621
-
"engines": {
1622
-
"node": ">=4.0"
1623
-
}
1624
-
},
1625
-
"node_modules/estraverse": {
1626
-
"version": "5.3.0",
1627
-
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
1628
-
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
1629
-
"dev": true,
1630
-
"license": "BSD-2-Clause",
1631
-
"engines": {
1632
-
"node": ">=4.0"
1633
-
}
1634
-
},
1635
-
"node_modules/esutils": {
1636
-
"version": "2.0.3",
1637
-
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
1638
-
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
1639
-
"dev": true,
1640
-
"license": "BSD-2-Clause",
1641
-
"engines": {
1642
-
"node": ">=0.10.0"
1643
-
}
1644
-
},
1645
-
"node_modules/fast-deep-equal": {
1646
-
"version": "3.1.3",
1647
-
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
1648
-
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
1649
-
"dev": true,
1650
-
"license": "MIT"
1651
-
},
1652
-
"node_modules/fast-glob": {
1653
-
"version": "3.3.3",
1654
-
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
1655
-
"integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
1656
-
"dev": true,
1657
-
"license": "MIT",
1658
-
"dependencies": {
1659
-
"@nodelib/fs.stat": "^2.0.2",
1660
-
"@nodelib/fs.walk": "^1.2.3",
1661
-
"glob-parent": "^5.1.2",
1662
-
"merge2": "^1.3.0",
1663
-
"micromatch": "^4.0.8"
1664
-
},
1665
-
"engines": {
1666
-
"node": ">=8.6.0"
1667
-
}
1668
-
},
1669
-
"node_modules/fast-glob/node_modules/glob-parent": {
1670
-
"version": "5.1.2",
1671
-
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
1672
-
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
1673
-
"dev": true,
1674
-
"license": "ISC",
1675
-
"dependencies": {
1676
-
"is-glob": "^4.0.1"
1677
-
},
1678
-
"engines": {
1679
-
"node": ">= 6"
1680
-
}
1681
-
},
1682
-
"node_modules/fast-json-stable-stringify": {
1683
-
"version": "2.1.0",
1684
-
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
1685
-
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
1686
-
"dev": true,
1687
-
"license": "MIT"
1688
-
},
1689
-
"node_modules/fast-levenshtein": {
1690
-
"version": "2.0.6",
1691
-
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
1692
-
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
1693
-
"dev": true,
1694
-
"license": "MIT"
1695
-
},
1696
-
"node_modules/fastq": {
1697
-
"version": "1.19.1",
1698
-
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
1699
-
"integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==",
1700
-
"dev": true,
1701
-
"license": "ISC",
1702
-
"dependencies": {
1703
-
"reusify": "^1.0.4"
1704
-
}
1705
-
},
1706
-
"node_modules/file-entry-cache": {
1707
-
"version": "8.0.0",
1708
-
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
1709
-
"integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
1710
-
"dev": true,
1711
-
"license": "MIT",
1712
-
"dependencies": {
1713
-
"flat-cache": "^4.0.0"
1714
-
},
1715
-
"engines": {
1716
-
"node": ">=16.0.0"
1717
-
}
1718
-
},
1719
-
"node_modules/fill-range": {
1720
-
"version": "7.1.1",
1721
-
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
1722
-
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
1723
-
"dev": true,
1724
-
"license": "MIT",
1725
-
"dependencies": {
1726
-
"to-regex-range": "^5.0.1"
1727
-
},
1728
-
"engines": {
1729
-
"node": ">=8"
1730
-
}
1731
-
},
1732
-
"node_modules/find-up": {
1733
-
"version": "5.0.0",
1734
-
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
1735
-
"integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
1736
-
"dev": true,
1737
-
"license": "MIT",
1738
-
"dependencies": {
1739
-
"locate-path": "^6.0.0",
1740
-
"path-exists": "^4.0.0"
1741
-
},
1742
-
"engines": {
1743
-
"node": ">=10"
1744
-
},
1745
-
"funding": {
1746
-
"url": "https://github.com/sponsors/sindresorhus"
1747
-
}
1748
-
},
1749
-
"node_modules/flat-cache": {
1750
-
"version": "4.0.1",
1751
-
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
1752
-
"integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
1753
-
"dev": true,
1754
-
"license": "MIT",
1755
-
"dependencies": {
1756
-
"flatted": "^3.2.9",
1757
-
"keyv": "^4.5.4"
1758
-
},
1759
-
"engines": {
1760
-
"node": ">=16"
1761
-
}
1762
-
},
1763
-
"node_modules/flatted": {
1764
-
"version": "3.3.3",
1765
-
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
1766
-
"integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
1767
-
"dev": true,
1768
-
"license": "ISC"
1769
-
},
1770
-
"node_modules/fsevents": {
1771
-
"version": "2.3.3",
1772
-
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
1773
-
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
1774
-
"dev": true,
1775
-
"hasInstallScript": true,
1776
-
"license": "MIT",
1777
-
"optional": true,
1778
-
"os": [
1779
-
"darwin"
1780
-
],
1781
-
"engines": {
1782
-
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
1783
-
}
1784
-
},
1785
-
"node_modules/gensync": {
1786
-
"version": "1.0.0-beta.2",
1787
-
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
1788
-
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
1789
-
"dev": true,
1790
-
"license": "MIT",
1791
-
"engines": {
1792
-
"node": ">=6.9.0"
1793
-
}
1794
-
},
1795
-
"node_modules/glob-parent": {
1796
-
"version": "6.0.2",
1797
-
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
1798
-
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
1799
-
"dev": true,
1800
-
"license": "ISC",
1801
-
"dependencies": {
1802
-
"is-glob": "^4.0.3"
1803
-
},
1804
-
"engines": {
1805
-
"node": ">=10.13.0"
1806
-
}
1807
-
},
1808
-
"node_modules/globals": {
1809
-
"version": "16.4.0",
1810
-
"resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz",
1811
-
"integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==",
1812
-
"dev": true,
1813
-
"license": "MIT",
1814
-
"engines": {
1815
-
"node": ">=18"
1816
-
},
1817
-
"funding": {
1818
-
"url": "https://github.com/sponsors/sindresorhus"
1819
-
}
1820
-
},
1821
-
"node_modules/graphemer": {
1822
-
"version": "1.4.0",
1823
-
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
1824
-
"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
1825
-
"dev": true,
1826
-
"license": "MIT"
1827
-
},
1828
-
"node_modules/has-flag": {
1829
-
"version": "4.0.0",
1830
-
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
1831
-
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
1832
-
"dev": true,
1833
-
"license": "MIT",
1834
-
"engines": {
1835
-
"node": ">=8"
1836
-
}
1837
-
},
1838
-
"node_modules/ignore": {
1839
-
"version": "5.3.2",
1840
-
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
1841
-
"integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
1842
-
"dev": true,
1843
-
"license": "MIT",
1844
-
"engines": {
1845
-
"node": ">= 4"
1846
-
}
1847
-
},
1848
-
"node_modules/import-fresh": {
1849
-
"version": "3.3.1",
1850
-
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
1851
-
"integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
1852
-
"dev": true,
1853
-
"license": "MIT",
1854
-
"dependencies": {
1855
-
"parent-module": "^1.0.0",
1856
-
"resolve-from": "^4.0.0"
1857
-
},
1858
-
"engines": {
1859
-
"node": ">=6"
1860
-
},
1861
-
"funding": {
1862
-
"url": "https://github.com/sponsors/sindresorhus"
1863
-
}
1864
-
},
1865
-
"node_modules/imurmurhash": {
1866
-
"version": "0.1.4",
1867
-
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
1868
-
"integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
1869
-
"dev": true,
1870
-
"license": "MIT",
1871
-
"engines": {
1872
-
"node": ">=0.8.19"
1873
-
}
1874
-
},
1875
-
"node_modules/is-extglob": {
1876
-
"version": "2.1.1",
1877
-
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
1878
-
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
1879
-
"dev": true,
1880
-
"license": "MIT",
1881
-
"engines": {
1882
-
"node": ">=0.10.0"
1883
-
}
1884
-
},
1885
-
"node_modules/is-glob": {
1886
-
"version": "4.0.3",
1887
-
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
1888
-
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
1889
-
"dev": true,
1890
-
"license": "MIT",
1891
-
"dependencies": {
1892
-
"is-extglob": "^2.1.1"
1893
-
},
1894
-
"engines": {
1895
-
"node": ">=0.10.0"
1896
-
}
1897
-
},
1898
-
"node_modules/is-number": {
1899
-
"version": "7.0.0",
1900
-
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
1901
-
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
1902
-
"dev": true,
1903
-
"license": "MIT",
1904
-
"engines": {
1905
-
"node": ">=0.12.0"
1906
-
}
1907
-
},
1908
-
"node_modules/isexe": {
1909
-
"version": "2.0.0",
1910
-
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
1911
-
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
1912
-
"dev": true,
1913
-
"license": "ISC"
1914
-
},
1915
-
"node_modules/js-tokens": {
1916
-
"version": "4.0.0",
1917
-
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
1918
-
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
1919
-
"dev": true,
1920
-
"license": "MIT"
1921
-
},
1922
-
"node_modules/js-yaml": {
1923
-
"version": "4.1.0",
1924
-
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
1925
-
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
1926
-
"dev": true,
1927
-
"license": "MIT",
1928
-
"dependencies": {
1929
-
"argparse": "^2.0.1"
1930
-
},
1931
-
"bin": {
1932
-
"js-yaml": "bin/js-yaml.js"
1933
-
}
1934
-
},
1935
-
"node_modules/jsesc": {
1936
-
"version": "3.1.0",
1937
-
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
1938
-
"integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
1939
-
"dev": true,
1940
-
"license": "MIT",
1941
-
"bin": {
1942
-
"jsesc": "bin/jsesc"
1943
-
},
1944
-
"engines": {
1945
-
"node": ">=6"
1946
-
}
1947
-
},
1948
-
"node_modules/json-buffer": {
1949
-
"version": "3.0.1",
1950
-
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
1951
-
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
1952
-
"dev": true,
1953
-
"license": "MIT"
1954
-
},
1955
-
"node_modules/json-schema-traverse": {
1956
-
"version": "0.4.1",
1957
-
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
1958
-
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
1959
-
"dev": true,
1960
-
"license": "MIT"
1961
-
},
1962
-
"node_modules/json-stable-stringify-without-jsonify": {
1963
-
"version": "1.0.1",
1964
-
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
1965
-
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
1966
-
"dev": true,
1967
-
"license": "MIT"
1968
-
},
1969
-
"node_modules/json5": {
1970
-
"version": "2.2.3",
1971
-
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
1972
-
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
1973
-
"dev": true,
1974
-
"license": "MIT",
1975
-
"bin": {
1976
-
"json5": "lib/cli.js"
1977
-
},
1978
-
"engines": {
1979
-
"node": ">=6"
1980
-
}
1981
-
},
1982
-
"node_modules/keyv": {
1983
-
"version": "4.5.4",
1984
-
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
1985
-
"integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
1986
-
"dev": true,
1987
-
"license": "MIT",
1988
-
"dependencies": {
1989
-
"json-buffer": "3.0.1"
1990
-
}
1991
-
},
1992
-
"node_modules/levn": {
1993
-
"version": "0.4.1",
1994
-
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
1995
-
"integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
1996
-
"dev": true,
1997
-
"license": "MIT",
1998
-
"dependencies": {
1999
-
"prelude-ls": "^1.2.1",
2000
-
"type-check": "~0.4.0"
2001
-
},
2002
-
"engines": {
2003
-
"node": ">= 0.8.0"
2004
-
}
2005
-
},
2006
-
"node_modules/lightningcss": {
2007
-
"version": "1.30.2",
2008
-
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz",
2009
-
"integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==",
2010
-
"dev": true,
2011
-
"license": "MPL-2.0",
2012
-
"dependencies": {
2013
-
"detect-libc": "^2.0.3"
2014
-
},
2015
-
"engines": {
2016
-
"node": ">= 12.0.0"
2017
-
},
2018
-
"funding": {
2019
-
"type": "opencollective",
2020
-
"url": "https://opencollective.com/parcel"
2021
-
},
2022
-
"optionalDependencies": {
2023
-
"lightningcss-android-arm64": "1.30.2",
2024
-
"lightningcss-darwin-arm64": "1.30.2",
2025
-
"lightningcss-darwin-x64": "1.30.2",
2026
-
"lightningcss-freebsd-x64": "1.30.2",
2027
-
"lightningcss-linux-arm-gnueabihf": "1.30.2",
2028
-
"lightningcss-linux-arm64-gnu": "1.30.2",
2029
-
"lightningcss-linux-arm64-musl": "1.30.2",
2030
-
"lightningcss-linux-x64-gnu": "1.30.2",
2031
-
"lightningcss-linux-x64-musl": "1.30.2",
2032
-
"lightningcss-win32-arm64-msvc": "1.30.2",
2033
-
"lightningcss-win32-x64-msvc": "1.30.2"
2034
-
}
2035
-
},
2036
-
"node_modules/lightningcss-darwin-arm64": {
2037
-
"version": "1.30.2",
2038
-
"resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz",
2039
-
"integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==",
2040
-
"cpu": [
2041
-
"arm64"
2042
-
],
2043
-
"dev": true,
2044
-
"license": "MPL-2.0",
2045
-
"optional": true,
2046
-
"os": [
2047
-
"darwin"
2048
-
],
2049
-
"engines": {
2050
-
"node": ">= 12.0.0"
2051
-
},
2052
-
"funding": {
2053
-
"type": "opencollective",
2054
-
"url": "https://opencollective.com/parcel"
2055
-
}
2056
-
},
2057
-
"node_modules/locate-path": {
2058
-
"version": "6.0.0",
2059
-
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
2060
-
"integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
2061
-
"dev": true,
2062
-
"license": "MIT",
2063
-
"dependencies": {
2064
-
"p-locate": "^5.0.0"
2065
-
},
2066
-
"engines": {
2067
-
"node": ">=10"
2068
-
},
2069
-
"funding": {
2070
-
"url": "https://github.com/sponsors/sindresorhus"
2071
-
}
2072
-
},
2073
-
"node_modules/lodash.merge": {
2074
-
"version": "4.6.2",
2075
-
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
2076
-
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
2077
-
"dev": true,
2078
-
"license": "MIT"
2079
-
},
2080
-
"node_modules/lru-cache": {
2081
-
"version": "5.1.1",
2082
-
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
2083
-
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
2084
-
"dev": true,
2085
-
"license": "ISC",
2086
-
"dependencies": {
2087
-
"yallist": "^3.0.2"
2088
-
}
2089
-
},
2090
-
"node_modules/merge2": {
2091
-
"version": "1.4.1",
2092
-
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
2093
-
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
2094
-
"dev": true,
2095
-
"license": "MIT",
2096
-
"engines": {
2097
-
"node": ">= 8"
2098
-
}
2099
-
},
2100
-
"node_modules/micromatch": {
2101
-
"version": "4.0.8",
2102
-
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
2103
-
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
2104
-
"dev": true,
2105
-
"license": "MIT",
2106
-
"dependencies": {
2107
-
"braces": "^3.0.3",
2108
-
"picomatch": "^2.3.1"
2109
-
},
2110
-
"engines": {
2111
-
"node": ">=8.6"
2112
-
}
2113
-
},
2114
-
"node_modules/minimatch": {
2115
-
"version": "3.1.2",
2116
-
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
2117
-
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
2118
-
"dev": true,
2119
-
"license": "ISC",
2120
-
"dependencies": {
2121
-
"brace-expansion": "^1.1.7"
2122
-
},
2123
-
"engines": {
2124
-
"node": "*"
2125
-
}
2126
-
},
2127
-
"node_modules/ms": {
2128
-
"version": "2.1.3",
2129
-
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
2130
-
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
2131
-
"dev": true,
2132
-
"license": "MIT"
2133
-
},
2134
-
"node_modules/nanoid": {
2135
-
"version": "3.3.11",
2136
-
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
2137
-
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
2138
-
"dev": true,
2139
-
"funding": [
2140
-
{
2141
-
"type": "github",
2142
-
"url": "https://github.com/sponsors/ai"
2143
-
}
2144
-
],
2145
-
"license": "MIT",
2146
-
"bin": {
2147
-
"nanoid": "bin/nanoid.cjs"
2148
-
},
2149
-
"engines": {
2150
-
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
2151
-
}
2152
-
},
2153
-
"node_modules/natural-compare": {
2154
-
"version": "1.4.0",
2155
-
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
2156
-
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
2157
-
"dev": true,
2158
-
"license": "MIT"
2159
-
},
2160
-
"node_modules/node-releases": {
2161
-
"version": "2.0.23",
2162
-
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.23.tgz",
2163
-
"integrity": "sha512-cCmFDMSm26S6tQSDpBCg/NR8NENrVPhAJSf+XbxBG4rPFaaonlEoE9wHQmun+cls499TQGSb7ZyPBRlzgKfpeg==",
2164
-
"dev": true,
2165
-
"license": "MIT"
2166
-
},
2167
-
"node_modules/optionator": {
2168
-
"version": "0.9.4",
2169
-
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
2170
-
"integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
2171
-
"dev": true,
2172
-
"license": "MIT",
2173
-
"dependencies": {
2174
-
"deep-is": "^0.1.3",
2175
-
"fast-levenshtein": "^2.0.6",
2176
-
"levn": "^0.4.1",
2177
-
"prelude-ls": "^1.2.1",
2178
-
"type-check": "^0.4.0",
2179
-
"word-wrap": "^1.2.5"
2180
-
},
2181
-
"engines": {
2182
-
"node": ">= 0.8.0"
2183
-
}
2184
-
},
2185
-
"node_modules/p-limit": {
2186
-
"version": "3.1.0",
2187
-
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
2188
-
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
2189
-
"dev": true,
2190
-
"license": "MIT",
2191
-
"dependencies": {
2192
-
"yocto-queue": "^0.1.0"
2193
-
},
2194
-
"engines": {
2195
-
"node": ">=10"
2196
-
},
2197
-
"funding": {
2198
-
"url": "https://github.com/sponsors/sindresorhus"
2199
-
}
2200
-
},
2201
-
"node_modules/p-locate": {
2202
-
"version": "5.0.0",
2203
-
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
2204
-
"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
2205
-
"dev": true,
2206
-
"license": "MIT",
2207
-
"dependencies": {
2208
-
"p-limit": "^3.0.2"
2209
-
},
2210
-
"engines": {
2211
-
"node": ">=10"
2212
-
},
2213
-
"funding": {
2214
-
"url": "https://github.com/sponsors/sindresorhus"
2215
-
}
2216
-
},
2217
-
"node_modules/parent-module": {
2218
-
"version": "1.0.1",
2219
-
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
2220
-
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
2221
-
"dev": true,
2222
-
"license": "MIT",
2223
-
"dependencies": {
2224
-
"callsites": "^3.0.0"
2225
-
},
2226
-
"engines": {
2227
-
"node": ">=6"
2228
-
}
2229
-
},
2230
-
"node_modules/path-exists": {
2231
-
"version": "4.0.0",
2232
-
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
2233
-
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
2234
-
"dev": true,
2235
-
"license": "MIT",
2236
-
"engines": {
2237
-
"node": ">=8"
2238
-
}
2239
-
},
2240
-
"node_modules/path-key": {
2241
-
"version": "3.1.1",
2242
-
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
2243
-
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
2244
-
"dev": true,
2245
-
"license": "MIT",
2246
-
"engines": {
2247
-
"node": ">=8"
2248
-
}
2249
-
},
2250
-
"node_modules/picocolors": {
2251
-
"version": "1.1.1",
2252
-
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
2253
-
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
2254
-
"dev": true,
2255
-
"license": "ISC"
2256
-
},
2257
-
"node_modules/picomatch": {
2258
-
"version": "2.3.1",
2259
-
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
2260
-
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
2261
-
"dev": true,
2262
-
"license": "MIT",
2263
-
"engines": {
2264
-
"node": ">=8.6"
2265
-
},
2266
-
"funding": {
2267
-
"url": "https://github.com/sponsors/jonschlinkert"
2268
-
}
2269
-
},
2270
-
"node_modules/postcss": {
2271
-
"version": "8.5.6",
2272
-
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
2273
-
"integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
2274
-
"dev": true,
2275
-
"funding": [
2276
-
{
2277
-
"type": "opencollective",
2278
-
"url": "https://opencollective.com/postcss/"
2279
-
},
2280
-
{
2281
-
"type": "tidelift",
2282
-
"url": "https://tidelift.com/funding/github/npm/postcss"
2283
-
},
2284
-
{
2285
-
"type": "github",
2286
-
"url": "https://github.com/sponsors/ai"
2287
-
}
2288
-
],
2289
-
"license": "MIT",
2290
-
"dependencies": {
2291
-
"nanoid": "^3.3.11",
2292
-
"picocolors": "^1.1.1",
2293
-
"source-map-js": "^1.2.1"
2294
-
},
2295
-
"engines": {
2296
-
"node": "^10 || ^12 || >=14"
2297
-
}
2298
-
},
2299
-
"node_modules/prelude-ls": {
2300
-
"version": "1.2.1",
2301
-
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
2302
-
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
2303
-
"dev": true,
2304
-
"license": "MIT",
2305
-
"engines": {
2306
-
"node": ">= 0.8.0"
2307
-
}
2308
-
},
2309
-
"node_modules/punycode": {
2310
-
"version": "2.3.1",
2311
-
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
2312
-
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
2313
-
"dev": true,
2314
-
"license": "MIT",
2315
-
"engines": {
2316
-
"node": ">=6"
2317
-
}
2318
-
},
2319
-
"node_modules/queue-microtask": {
2320
-
"version": "1.2.3",
2321
-
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
2322
-
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
2323
-
"dev": true,
2324
-
"funding": [
2325
-
{
2326
-
"type": "github",
2327
-
"url": "https://github.com/sponsors/feross"
2328
-
},
2329
-
{
2330
-
"type": "patreon",
2331
-
"url": "https://www.patreon.com/feross"
2332
-
},
2333
-
{
2334
-
"type": "consulting",
2335
-
"url": "https://feross.org/support"
2336
-
}
2337
-
],
2338
-
"license": "MIT"
2339
-
},
2340
-
"node_modules/react": {
2341
-
"version": "19.2.0",
2342
-
"resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz",
2343
-
"integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==",
2344
-
"dev": true,
2345
-
"license": "MIT",
2346
-
"engines": {
2347
-
"node": ">=0.10.0"
2348
-
}
2349
-
},
2350
-
"node_modules/react-dom": {
2351
-
"version": "19.2.0",
2352
-
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz",
2353
-
"integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==",
2354
-
"dev": true,
2355
-
"license": "MIT",
2356
-
"dependencies": {
2357
-
"scheduler": "^0.27.0"
2358
-
},
2359
-
"peerDependencies": {
2360
-
"react": "^19.2.0"
2361
-
}
2362
-
},
2363
-
"node_modules/react-refresh": {
2364
-
"version": "0.17.0",
2365
-
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
2366
-
"integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==",
2367
-
"dev": true,
2368
-
"license": "MIT",
2369
-
"engines": {
2370
-
"node": ">=0.10.0"
2371
-
}
2372
-
},
2373
-
"node_modules/resolve-from": {
2374
-
"version": "4.0.0",
2375
-
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
2376
-
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
2377
-
"dev": true,
2378
-
"license": "MIT",
2379
-
"engines": {
2380
-
"node": ">=4"
2381
-
}
2382
-
},
2383
-
"node_modules/reusify": {
2384
-
"version": "1.1.0",
2385
-
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
2386
-
"integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
2387
-
"dev": true,
2388
-
"license": "MIT",
2389
-
"engines": {
2390
-
"iojs": ">=1.0.0",
2391
-
"node": ">=0.10.0"
2392
-
}
2393
-
},
2394
-
"node_modules/rolldown": {
2395
-
"version": "1.0.0-beta.41",
2396
-
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-beta.41.tgz",
2397
-
"integrity": "sha512-U+NPR0Bkg3wm61dteD2L4nAM1U9dtaqVrpDXwC36IKRHpEO/Ubpid4Nijpa2imPchcVNHfxVFwSSMJdwdGFUbg==",
2398
-
"dev": true,
2399
-
"license": "MIT",
2400
-
"dependencies": {
2401
-
"@oxc-project/types": "=0.93.0",
2402
-
"@rolldown/pluginutils": "1.0.0-beta.41",
2403
-
"ansis": "=4.2.0"
2404
-
},
2405
-
"bin": {
2406
-
"rolldown": "bin/cli.mjs"
2407
-
},
2408
-
"engines": {
2409
-
"node": "^20.19.0 || >=22.12.0"
2410
-
},
2411
-
"optionalDependencies": {
2412
-
"@rolldown/binding-android-arm64": "1.0.0-beta.41",
2413
-
"@rolldown/binding-darwin-arm64": "1.0.0-beta.41",
2414
-
"@rolldown/binding-darwin-x64": "1.0.0-beta.41",
2415
-
"@rolldown/binding-freebsd-x64": "1.0.0-beta.41",
2416
-
"@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.41",
2417
-
"@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.41",
2418
-
"@rolldown/binding-linux-arm64-musl": "1.0.0-beta.41",
2419
-
"@rolldown/binding-linux-x64-gnu": "1.0.0-beta.41",
2420
-
"@rolldown/binding-linux-x64-musl": "1.0.0-beta.41",
2421
-
"@rolldown/binding-openharmony-arm64": "1.0.0-beta.41",
2422
-
"@rolldown/binding-wasm32-wasi": "1.0.0-beta.41",
2423
-
"@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.41",
2424
-
"@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.41",
2425
-
"@rolldown/binding-win32-x64-msvc": "1.0.0-beta.41"
2426
-
}
2427
-
},
2428
-
"node_modules/rolldown/node_modules/@rolldown/pluginutils": {
2429
-
"version": "1.0.0-beta.41",
2430
-
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.41.tgz",
2431
-
"integrity": "sha512-ycMEPrS3StOIeb87BT3/+bu+blEtyvwQ4zmo2IcJQy0Rd1DAAhKksA0iUZ3MYSpJtjlPhg0Eo6mvVS6ggPhRbw==",
2432
-
"dev": true,
2433
-
"license": "MIT"
2434
-
},
2435
-
"node_modules/run-parallel": {
2436
-
"version": "1.2.0",
2437
-
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
2438
-
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
2439
-
"dev": true,
2440
-
"funding": [
2441
-
{
2442
-
"type": "github",
2443
-
"url": "https://github.com/sponsors/feross"
2444
-
},
2445
-
{
2446
-
"type": "patreon",
2447
-
"url": "https://www.patreon.com/feross"
2448
-
},
2449
-
{
2450
-
"type": "consulting",
2451
-
"url": "https://feross.org/support"
2452
-
}
2453
-
],
2454
-
"license": "MIT",
2455
-
"dependencies": {
2456
-
"queue-microtask": "^1.2.2"
2457
-
}
2458
-
},
2459
-
"node_modules/scheduler": {
2460
-
"version": "0.27.0",
2461
-
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
2462
-
"integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
2463
-
"dev": true,
2464
-
"license": "MIT"
2465
-
},
2466
-
"node_modules/semver": {
2467
-
"version": "6.3.1",
2468
-
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
2469
-
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
2470
-
"dev": true,
2471
-
"license": "ISC",
2472
-
"bin": {
2473
-
"semver": "bin/semver.js"
2474
-
}
2475
-
},
2476
-
"node_modules/shebang-command": {
2477
-
"version": "2.0.0",
2478
-
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
2479
-
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
2480
-
"dev": true,
2481
-
"license": "MIT",
2482
-
"dependencies": {
2483
-
"shebang-regex": "^3.0.0"
2484
-
},
2485
-
"engines": {
2486
-
"node": ">=8"
2487
-
}
2488
-
},
2489
-
"node_modules/shebang-regex": {
2490
-
"version": "3.0.0",
2491
-
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
2492
-
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
2493
-
"dev": true,
2494
-
"license": "MIT",
2495
-
"engines": {
2496
-
"node": ">=8"
2497
-
}
2498
-
},
2499
-
"node_modules/source-map-js": {
2500
-
"version": "1.2.1",
2501
-
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
2502
-
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
2503
-
"dev": true,
2504
-
"license": "BSD-3-Clause",
2505
-
"engines": {
2506
-
"node": ">=0.10.0"
2507
-
}
2508
-
},
2509
-
"node_modules/strip-json-comments": {
2510
-
"version": "3.1.1",
2511
-
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
2512
-
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
2513
-
"dev": true,
2514
-
"license": "MIT",
2515
-
"engines": {
2516
-
"node": ">=8"
2517
-
},
2518
-
"funding": {
2519
-
"url": "https://github.com/sponsors/sindresorhus"
2520
-
}
2521
-
},
2522
-
"node_modules/supports-color": {
2523
-
"version": "7.2.0",
2524
-
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
2525
-
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
2526
-
"dev": true,
2527
-
"license": "MIT",
2528
-
"dependencies": {
2529
-
"has-flag": "^4.0.0"
2530
-
},
2531
-
"engines": {
2532
-
"node": ">=8"
2533
-
}
2534
-
},
2535
-
"node_modules/tinyglobby": {
2536
-
"version": "0.2.15",
2537
-
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
2538
-
"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
2539
-
"dev": true,
2540
-
"license": "MIT",
2541
-
"dependencies": {
2542
-
"fdir": "^6.5.0",
2543
-
"picomatch": "^4.0.3"
2544
-
},
2545
-
"engines": {
2546
-
"node": ">=12.0.0"
2547
-
},
2548
-
"funding": {
2549
-
"url": "https://github.com/sponsors/SuperchupuDev"
2550
-
}
2551
-
},
2552
-
"node_modules/tinyglobby/node_modules/fdir": {
2553
-
"version": "6.5.0",
2554
-
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
2555
-
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
2556
-
"dev": true,
2557
-
"license": "MIT",
2558
-
"engines": {
2559
-
"node": ">=12.0.0"
2560
-
},
2561
-
"peerDependencies": {
2562
-
"picomatch": "^3 || ^4"
2563
-
},
2564
-
"peerDependenciesMeta": {
2565
-
"picomatch": {
2566
-
"optional": true
2567
-
}
2568
-
}
2569
-
},
2570
-
"node_modules/tinyglobby/node_modules/picomatch": {
2571
-
"version": "4.0.3",
2572
-
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
2573
-
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
2574
-
"dev": true,
2575
-
"license": "MIT",
2576
-
"engines": {
2577
-
"node": ">=12"
2578
-
},
2579
-
"funding": {
2580
-
"url": "https://github.com/sponsors/jonschlinkert"
2581
-
}
2582
-
},
2583
-
"node_modules/to-regex-range": {
2584
-
"version": "5.0.1",
2585
-
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
2586
-
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
2587
-
"dev": true,
2588
-
"license": "MIT",
2589
-
"dependencies": {
2590
-
"is-number": "^7.0.0"
2591
-
},
2592
-
"engines": {
2593
-
"node": ">=8.0"
2594
-
}
2595
-
},
2596
-
"node_modules/ts-api-utils": {
2597
-
"version": "2.1.0",
2598
-
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
2599
-
"integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==",
2600
-
"dev": true,
2601
-
"license": "MIT",
2602
-
"engines": {
2603
-
"node": ">=18.12"
2604
-
},
2605
-
"peerDependencies": {
2606
-
"typescript": ">=4.8.4"
2607
-
}
2608
-
},
2609
-
"node_modules/type-check": {
2610
-
"version": "0.4.0",
2611
-
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
2612
-
"integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
2613
-
"dev": true,
2614
-
"license": "MIT",
2615
-
"dependencies": {
2616
-
"prelude-ls": "^1.2.1"
2617
-
},
2618
-
"engines": {
2619
-
"node": ">= 0.8.0"
2620
-
}
2621
-
},
2622
-
"node_modules/typescript": {
2623
-
"version": "5.9.3",
2624
-
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
2625
-
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
2626
-
"dev": true,
2627
-
"license": "Apache-2.0",
2628
-
"bin": {
2629
-
"tsc": "bin/tsc",
2630
-
"tsserver": "bin/tsserver"
2631
-
},
2632
-
"engines": {
2633
-
"node": ">=14.17"
2634
-
}
2635
-
},
2636
-
"node_modules/typescript-eslint": {
2637
-
"version": "8.46.0",
2638
-
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.46.0.tgz",
2639
-
"integrity": "sha512-6+ZrB6y2bT2DX3K+Qd9vn7OFOJR+xSLDj+Aw/N3zBwUt27uTw2sw2TE2+UcY1RiyBZkaGbTkVg9SSdPNUG6aUw==",
2640
-
"dev": true,
2641
-
"license": "MIT",
2642
-
"dependencies": {
2643
-
"@typescript-eslint/eslint-plugin": "8.46.0",
2644
-
"@typescript-eslint/parser": "8.46.0",
2645
-
"@typescript-eslint/typescript-estree": "8.46.0",
2646
-
"@typescript-eslint/utils": "8.46.0"
2647
-
},
2648
-
"engines": {
2649
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
2650
-
},
2651
-
"funding": {
2652
-
"type": "opencollective",
2653
-
"url": "https://opencollective.com/typescript-eslint"
2654
-
},
2655
-
"peerDependencies": {
2656
-
"eslint": "^8.57.0 || ^9.0.0",
2657
-
"typescript": ">=4.8.4 <6.0.0"
2658
-
}
2659
-
},
2660
-
"node_modules/undici-types": {
2661
-
"version": "7.14.0",
2662
-
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.14.0.tgz",
2663
-
"integrity": "sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==",
2664
-
"dev": true,
2665
-
"license": "MIT"
2666
-
},
2667
-
"node_modules/update-browserslist-db": {
2668
-
"version": "1.1.3",
2669
-
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
2670
-
"integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
2671
-
"dev": true,
2672
-
"funding": [
2673
-
{
2674
-
"type": "opencollective",
2675
-
"url": "https://opencollective.com/browserslist"
2676
-
},
2677
-
{
2678
-
"type": "tidelift",
2679
-
"url": "https://tidelift.com/funding/github/npm/browserslist"
2680
-
},
2681
-
{
2682
-
"type": "github",
2683
-
"url": "https://github.com/sponsors/ai"
2684
-
}
2685
-
],
2686
-
"license": "MIT",
2687
-
"dependencies": {
2688
-
"escalade": "^3.2.0",
2689
-
"picocolors": "^1.1.1"
2690
-
},
2691
-
"bin": {
2692
-
"update-browserslist-db": "cli.js"
2693
-
},
2694
-
"peerDependencies": {
2695
-
"browserslist": ">= 4.21.0"
2696
-
}
2697
-
},
2698
-
"node_modules/uri-js": {
2699
-
"version": "4.4.1",
2700
-
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
2701
-
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
2702
-
"dev": true,
2703
-
"license": "BSD-2-Clause",
2704
-
"dependencies": {
2705
-
"punycode": "^2.1.0"
2706
-
}
2707
-
},
2708
-
"node_modules/vite": {
2709
-
"name": "rolldown-vite",
2710
-
"version": "7.1.14",
2711
-
"resolved": "https://registry.npmjs.org/rolldown-vite/-/rolldown-vite-7.1.14.tgz",
2712
-
"integrity": "sha512-eSiiRJmovt8qDJkGyZuLnbxAOAdie6NCmmd0NkTC0RJI9duiSBTfr8X2mBYJOUFzxQa2USaHmL99J9uMxkjCyw==",
2713
-
"dev": true,
2714
-
"license": "MIT",
2715
-
"dependencies": {
2716
-
"@oxc-project/runtime": "0.92.0",
2717
-
"fdir": "^6.5.0",
2718
-
"lightningcss": "^1.30.1",
2719
-
"picomatch": "^4.0.3",
2720
-
"postcss": "^8.5.6",
2721
-
"rolldown": "1.0.0-beta.41",
2722
-
"tinyglobby": "^0.2.15"
2723
-
},
2724
-
"bin": {
2725
-
"vite": "bin/vite.js"
2726
-
},
2727
-
"engines": {
2728
-
"node": "^20.19.0 || >=22.12.0"
2729
-
},
2730
-
"funding": {
2731
-
"url": "https://github.com/vitejs/vite?sponsor=1"
2732
-
},
2733
-
"optionalDependencies": {
2734
-
"fsevents": "~2.3.3"
2735
-
},
2736
-
"peerDependencies": {
2737
-
"@types/node": "^20.19.0 || >=22.12.0",
2738
-
"esbuild": "^0.25.0",
2739
-
"jiti": ">=1.21.0",
2740
-
"less": "^4.0.0",
2741
-
"sass": "^1.70.0",
2742
-
"sass-embedded": "^1.70.0",
2743
-
"stylus": ">=0.54.8",
2744
-
"sugarss": "^5.0.0",
2745
-
"terser": "^5.16.0",
2746
-
"tsx": "^4.8.1",
2747
-
"yaml": "^2.4.2"
2748
-
},
2749
-
"peerDependenciesMeta": {
2750
-
"@types/node": {
2751
-
"optional": true
2752
-
},
2753
-
"esbuild": {
2754
-
"optional": true
2755
-
},
2756
-
"jiti": {
2757
-
"optional": true
2758
-
},
2759
-
"less": {
2760
-
"optional": true
2761
-
},
2762
-
"sass": {
2763
-
"optional": true
2764
-
},
2765
-
"sass-embedded": {
2766
-
"optional": true
2767
-
},
2768
-
"stylus": {
2769
-
"optional": true
2770
-
},
2771
-
"sugarss": {
2772
-
"optional": true
2773
-
},
2774
-
"terser": {
2775
-
"optional": true
2776
-
},
2777
-
"tsx": {
2778
-
"optional": true
2779
-
},
2780
-
"yaml": {
2781
-
"optional": true
2782
-
}
2783
-
}
2784
-
},
2785
-
"node_modules/vite/node_modules/fdir": {
2786
-
"version": "6.5.0",
2787
-
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
2788
-
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
2789
-
"dev": true,
2790
-
"license": "MIT",
2791
-
"engines": {
2792
-
"node": ">=12.0.0"
2793
-
},
2794
-
"peerDependencies": {
2795
-
"picomatch": "^3 || ^4"
2796
-
},
2797
-
"peerDependenciesMeta": {
2798
-
"picomatch": {
2799
-
"optional": true
2800
-
}
2801
-
}
2802
-
},
2803
-
"node_modules/vite/node_modules/picomatch": {
2804
-
"version": "4.0.3",
2805
-
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
2806
-
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
2807
-
"dev": true,
2808
-
"license": "MIT",
2809
-
"engines": {
2810
-
"node": ">=12"
2811
-
},
2812
-
"funding": {
2813
-
"url": "https://github.com/sponsors/jonschlinkert"
2814
-
}
2815
-
},
2816
-
"node_modules/which": {
2817
-
"version": "2.0.2",
2818
-
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
2819
-
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
2820
-
"dev": true,
2821
-
"license": "ISC",
2822
-
"dependencies": {
2823
-
"isexe": "^2.0.0"
2824
-
},
2825
-
"bin": {
2826
-
"node-which": "bin/node-which"
2827
-
},
2828
-
"engines": {
2829
-
"node": ">= 8"
2830
-
}
2831
-
},
2832
-
"node_modules/word-wrap": {
2833
-
"version": "1.2.5",
2834
-
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
2835
-
"integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
2836
-
"dev": true,
2837
-
"license": "MIT",
2838
-
"engines": {
2839
-
"node": ">=0.10.0"
2840
-
}
2841
-
},
2842
-
"node_modules/yallist": {
2843
-
"version": "3.1.1",
2844
-
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
2845
-
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
2846
-
"dev": true,
2847
-
"license": "ISC"
2848
-
},
2849
-
"node_modules/yocto-queue": {
2850
-
"version": "0.1.0",
2851
-
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
2852
-
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
2853
-
"dev": true,
2854
-
"license": "MIT",
2855
-
"engines": {
2856
-
"node": ">=10"
2857
-
},
2858
-
"funding": {
2859
-
"url": "https://github.com/sponsors/sindresorhus"
2860
-
}
2861
-
}
2862
-
}
2
+
"name": "atproto-ui",
3
+
"version": "0.12",
4
+
"lockfileVersion": 3,
5
+
"requires": true,
6
+
"packages": {
7
+
"": {
8
+
"name": "atproto-ui",
9
+
"version": "0.12",
10
+
"dependencies": {
11
+
"@atcute/atproto": "^3.1.7",
12
+
"@atcute/bluesky": "^3.2.3",
13
+
"@atcute/client": "^4.0.3",
14
+
"@atcute/identity-resolver": "^1.1.3",
15
+
"@atcute/tangled": "^1.0.10"
16
+
},
17
+
"devDependencies": {
18
+
"@eslint/js": "^9.36.0",
19
+
"@microsoft/api-extractor": "^7.53.1",
20
+
"@types/node": "^24.6.0",
21
+
"@types/react": "^19.1.16",
22
+
"@types/react-dom": "^19.1.9",
23
+
"@vitejs/plugin-react": "^5.0.4",
24
+
"eslint": "^9.36.0",
25
+
"eslint-plugin-react-hooks": "^5.2.0",
26
+
"eslint-plugin-react-refresh": "^0.4.22",
27
+
"globals": "^16.4.0",
28
+
"react": "^19.1.1",
29
+
"react-dom": "^19.1.1",
30
+
"rollup-plugin-typescript2": "^0.36.0",
31
+
"typescript": "~5.9.3",
32
+
"typescript-eslint": "^8.45.0",
33
+
"unplugin-dts": "^1.0.0-beta.6",
34
+
"vite": "npm:rolldown-vite@7.1.14"
35
+
},
36
+
"peerDependencies": {
37
+
"react": "^18.2.0 || ^19.0.0",
38
+
"react-dom": "^18.2.0 || ^19.0.0"
39
+
},
40
+
"peerDependenciesMeta": {
41
+
"react-dom": {
42
+
"optional": true
43
+
}
44
+
}
45
+
},
46
+
"node_modules/@atcute/atproto": {
47
+
"version": "3.1.9",
48
+
"license": "0BSD",
49
+
"dependencies": {
50
+
"@atcute/lexicons": "^1.2.2"
51
+
}
52
+
},
53
+
"node_modules/@atcute/bluesky": {
54
+
"version": "3.2.11",
55
+
"license": "0BSD",
56
+
"dependencies": {
57
+
"@atcute/atproto": "^3.1.9",
58
+
"@atcute/lexicons": "^1.2.5"
59
+
}
60
+
},
61
+
"node_modules/@atcute/client": {
62
+
"version": "4.1.0",
63
+
"license": "0BSD",
64
+
"dependencies": {
65
+
"@atcute/identity": "^1.1.3",
66
+
"@atcute/lexicons": "^1.2.5"
67
+
}
68
+
},
69
+
"node_modules/@atcute/identity": {
70
+
"version": "1.1.3",
71
+
"license": "0BSD",
72
+
"peer": true,
73
+
"dependencies": {
74
+
"@atcute/lexicons": "^1.2.4",
75
+
"@badrap/valita": "^0.4.6"
76
+
}
77
+
},
78
+
"node_modules/@atcute/identity-resolver": {
79
+
"version": "1.1.4",
80
+
"license": "0BSD",
81
+
"dependencies": {
82
+
"@atcute/lexicons": "^1.2.2",
83
+
"@atcute/util-fetch": "^1.0.3",
84
+
"@badrap/valita": "^0.4.6"
85
+
},
86
+
"peerDependencies": {
87
+
"@atcute/identity": "^1.0.0"
88
+
}
89
+
},
90
+
"node_modules/@atcute/lexicons": {
91
+
"version": "1.2.5",
92
+
"license": "0BSD",
93
+
"dependencies": {
94
+
"@standard-schema/spec": "^1.0.0",
95
+
"esm-env": "^1.2.2"
96
+
}
97
+
},
98
+
"node_modules/@atcute/tangled": {
99
+
"version": "1.0.12",
100
+
"license": "0BSD",
101
+
"dependencies": {
102
+
"@atcute/atproto": "^3.1.9",
103
+
"@atcute/lexicons": "^1.2.3"
104
+
}
105
+
},
106
+
"node_modules/@atcute/util-fetch": {
107
+
"version": "1.0.4",
108
+
"license": "0BSD",
109
+
"dependencies": {
110
+
"@badrap/valita": "^0.4.6"
111
+
}
112
+
},
113
+
"node_modules/@babel/code-frame": {
114
+
"version": "7.27.1",
115
+
"dev": true,
116
+
"license": "MIT",
117
+
"dependencies": {
118
+
"@babel/helper-validator-identifier": "^7.27.1",
119
+
"js-tokens": "^4.0.0",
120
+
"picocolors": "^1.1.1"
121
+
},
122
+
"engines": {
123
+
"node": ">=6.9.0"
124
+
}
125
+
},
126
+
"node_modules/@babel/compat-data": {
127
+
"version": "7.28.5",
128
+
"dev": true,
129
+
"license": "MIT",
130
+
"engines": {
131
+
"node": ">=6.9.0"
132
+
}
133
+
},
134
+
"node_modules/@babel/core": {
135
+
"version": "7.28.5",
136
+
"dev": true,
137
+
"license": "MIT",
138
+
"peer": true,
139
+
"dependencies": {
140
+
"@babel/code-frame": "^7.27.1",
141
+
"@babel/generator": "^7.28.5",
142
+
"@babel/helper-compilation-targets": "^7.27.2",
143
+
"@babel/helper-module-transforms": "^7.28.3",
144
+
"@babel/helpers": "^7.28.4",
145
+
"@babel/parser": "^7.28.5",
146
+
"@babel/template": "^7.27.2",
147
+
"@babel/traverse": "^7.28.5",
148
+
"@babel/types": "^7.28.5",
149
+
"@jridgewell/remapping": "^2.3.5",
150
+
"convert-source-map": "^2.0.0",
151
+
"debug": "^4.1.0",
152
+
"gensync": "^1.0.0-beta.2",
153
+
"json5": "^2.2.3",
154
+
"semver": "^6.3.1"
155
+
},
156
+
"engines": {
157
+
"node": ">=6.9.0"
158
+
},
159
+
"funding": {
160
+
"type": "opencollective",
161
+
"url": "https://opencollective.com/babel"
162
+
}
163
+
},
164
+
"node_modules/@babel/core/node_modules/semver": {
165
+
"version": "6.3.1",
166
+
"dev": true,
167
+
"license": "ISC",
168
+
"bin": {
169
+
"semver": "bin/semver.js"
170
+
}
171
+
},
172
+
"node_modules/@babel/generator": {
173
+
"version": "7.28.5",
174
+
"dev": true,
175
+
"license": "MIT",
176
+
"dependencies": {
177
+
"@babel/parser": "^7.28.5",
178
+
"@babel/types": "^7.28.5",
179
+
"@jridgewell/gen-mapping": "^0.3.12",
180
+
"@jridgewell/trace-mapping": "^0.3.28",
181
+
"jsesc": "^3.0.2"
182
+
},
183
+
"engines": {
184
+
"node": ">=6.9.0"
185
+
}
186
+
},
187
+
"node_modules/@babel/helper-compilation-targets": {
188
+
"version": "7.27.2",
189
+
"dev": true,
190
+
"license": "MIT",
191
+
"dependencies": {
192
+
"@babel/compat-data": "^7.27.2",
193
+
"@babel/helper-validator-option": "^7.27.1",
194
+
"browserslist": "^4.24.0",
195
+
"lru-cache": "^5.1.1",
196
+
"semver": "^6.3.1"
197
+
},
198
+
"engines": {
199
+
"node": ">=6.9.0"
200
+
}
201
+
},
202
+
"node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": {
203
+
"version": "5.1.1",
204
+
"dev": true,
205
+
"license": "ISC",
206
+
"dependencies": {
207
+
"yallist": "^3.0.2"
208
+
}
209
+
},
210
+
"node_modules/@babel/helper-compilation-targets/node_modules/lru-cache/node_modules/yallist": {
211
+
"version": "3.1.1",
212
+
"dev": true,
213
+
"license": "ISC"
214
+
},
215
+
"node_modules/@babel/helper-compilation-targets/node_modules/semver": {
216
+
"version": "6.3.1",
217
+
"dev": true,
218
+
"license": "ISC",
219
+
"bin": {
220
+
"semver": "bin/semver.js"
221
+
}
222
+
},
223
+
"node_modules/@babel/helper-globals": {
224
+
"version": "7.28.0",
225
+
"dev": true,
226
+
"license": "MIT",
227
+
"engines": {
228
+
"node": ">=6.9.0"
229
+
}
230
+
},
231
+
"node_modules/@babel/helper-module-imports": {
232
+
"version": "7.27.1",
233
+
"dev": true,
234
+
"license": "MIT",
235
+
"dependencies": {
236
+
"@babel/traverse": "^7.27.1",
237
+
"@babel/types": "^7.27.1"
238
+
},
239
+
"engines": {
240
+
"node": ">=6.9.0"
241
+
}
242
+
},
243
+
"node_modules/@babel/helper-module-transforms": {
244
+
"version": "7.28.3",
245
+
"dev": true,
246
+
"license": "MIT",
247
+
"dependencies": {
248
+
"@babel/helper-module-imports": "^7.27.1",
249
+
"@babel/helper-validator-identifier": "^7.27.1",
250
+
"@babel/traverse": "^7.28.3"
251
+
},
252
+
"engines": {
253
+
"node": ">=6.9.0"
254
+
},
255
+
"peerDependencies": {
256
+
"@babel/core": "^7.0.0"
257
+
}
258
+
},
259
+
"node_modules/@babel/helper-plugin-utils": {
260
+
"version": "7.27.1",
261
+
"dev": true,
262
+
"license": "MIT",
263
+
"engines": {
264
+
"node": ">=6.9.0"
265
+
}
266
+
},
267
+
"node_modules/@babel/helper-string-parser": {
268
+
"version": "7.27.1",
269
+
"dev": true,
270
+
"license": "MIT",
271
+
"engines": {
272
+
"node": ">=6.9.0"
273
+
}
274
+
},
275
+
"node_modules/@babel/helper-validator-identifier": {
276
+
"version": "7.28.5",
277
+
"dev": true,
278
+
"license": "MIT",
279
+
"engines": {
280
+
"node": ">=6.9.0"
281
+
}
282
+
},
283
+
"node_modules/@babel/helper-validator-option": {
284
+
"version": "7.27.1",
285
+
"dev": true,
286
+
"license": "MIT",
287
+
"engines": {
288
+
"node": ">=6.9.0"
289
+
}
290
+
},
291
+
"node_modules/@babel/helpers": {
292
+
"version": "7.28.4",
293
+
"dev": true,
294
+
"license": "MIT",
295
+
"dependencies": {
296
+
"@babel/template": "^7.27.2",
297
+
"@babel/types": "^7.28.4"
298
+
},
299
+
"engines": {
300
+
"node": ">=6.9.0"
301
+
}
302
+
},
303
+
"node_modules/@babel/parser": {
304
+
"version": "7.28.5",
305
+
"dev": true,
306
+
"license": "MIT",
307
+
"dependencies": {
308
+
"@babel/types": "^7.28.5"
309
+
},
310
+
"bin": {
311
+
"parser": "bin/babel-parser.js"
312
+
},
313
+
"engines": {
314
+
"node": ">=6.0.0"
315
+
}
316
+
},
317
+
"node_modules/@babel/plugin-transform-react-jsx-self": {
318
+
"version": "7.27.1",
319
+
"dev": true,
320
+
"license": "MIT",
321
+
"dependencies": {
322
+
"@babel/helper-plugin-utils": "^7.27.1"
323
+
},
324
+
"engines": {
325
+
"node": ">=6.9.0"
326
+
},
327
+
"peerDependencies": {
328
+
"@babel/core": "^7.0.0-0"
329
+
}
330
+
},
331
+
"node_modules/@babel/plugin-transform-react-jsx-source": {
332
+
"version": "7.27.1",
333
+
"dev": true,
334
+
"license": "MIT",
335
+
"dependencies": {
336
+
"@babel/helper-plugin-utils": "^7.27.1"
337
+
},
338
+
"engines": {
339
+
"node": ">=6.9.0"
340
+
},
341
+
"peerDependencies": {
342
+
"@babel/core": "^7.0.0-0"
343
+
}
344
+
},
345
+
"node_modules/@babel/template": {
346
+
"version": "7.27.2",
347
+
"dev": true,
348
+
"license": "MIT",
349
+
"dependencies": {
350
+
"@babel/code-frame": "^7.27.1",
351
+
"@babel/parser": "^7.27.2",
352
+
"@babel/types": "^7.27.1"
353
+
},
354
+
"engines": {
355
+
"node": ">=6.9.0"
356
+
}
357
+
},
358
+
"node_modules/@babel/traverse": {
359
+
"version": "7.28.5",
360
+
"dev": true,
361
+
"license": "MIT",
362
+
"dependencies": {
363
+
"@babel/code-frame": "^7.27.1",
364
+
"@babel/generator": "^7.28.5",
365
+
"@babel/helper-globals": "^7.28.0",
366
+
"@babel/parser": "^7.28.5",
367
+
"@babel/template": "^7.27.2",
368
+
"@babel/types": "^7.28.5",
369
+
"debug": "^4.3.1"
370
+
},
371
+
"engines": {
372
+
"node": ">=6.9.0"
373
+
}
374
+
},
375
+
"node_modules/@babel/types": {
376
+
"version": "7.28.5",
377
+
"dev": true,
378
+
"license": "MIT",
379
+
"dependencies": {
380
+
"@babel/helper-string-parser": "^7.27.1",
381
+
"@babel/helper-validator-identifier": "^7.28.5"
382
+
},
383
+
"engines": {
384
+
"node": ">=6.9.0"
385
+
}
386
+
},
387
+
"node_modules/@badrap/valita": {
388
+
"version": "0.4.6",
389
+
"license": "MIT",
390
+
"engines": {
391
+
"node": ">= 18"
392
+
}
393
+
},
394
+
"node_modules/@emnapi/core": {
395
+
"version": "1.7.1",
396
+
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz",
397
+
"integrity": "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==",
398
+
"dev": true,
399
+
"license": "MIT",
400
+
"optional": true,
401
+
"dependencies": {
402
+
"@emnapi/wasi-threads": "1.1.0",
403
+
"tslib": "^2.4.0"
404
+
}
405
+
},
406
+
"node_modules/@emnapi/runtime": {
407
+
"version": "1.7.1",
408
+
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz",
409
+
"integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==",
410
+
"dev": true,
411
+
"license": "MIT",
412
+
"optional": true,
413
+
"dependencies": {
414
+
"tslib": "^2.4.0"
415
+
}
416
+
},
417
+
"node_modules/@emnapi/wasi-threads": {
418
+
"version": "1.1.0",
419
+
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz",
420
+
"integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==",
421
+
"dev": true,
422
+
"license": "MIT",
423
+
"optional": true,
424
+
"dependencies": {
425
+
"tslib": "^2.4.0"
426
+
}
427
+
},
428
+
"node_modules/@eslint-community/eslint-utils": {
429
+
"version": "4.9.0",
430
+
"dev": true,
431
+
"license": "MIT",
432
+
"dependencies": {
433
+
"eslint-visitor-keys": "^3.4.3"
434
+
},
435
+
"engines": {
436
+
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
437
+
},
438
+
"funding": {
439
+
"url": "https://opencollective.com/eslint"
440
+
},
441
+
"peerDependencies": {
442
+
"eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
443
+
}
444
+
},
445
+
"node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
446
+
"version": "3.4.3",
447
+
"dev": true,
448
+
"license": "Apache-2.0",
449
+
"engines": {
450
+
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
451
+
},
452
+
"funding": {
453
+
"url": "https://opencollective.com/eslint"
454
+
}
455
+
},
456
+
"node_modules/@eslint-community/regexpp": {
457
+
"version": "4.12.2",
458
+
"dev": true,
459
+
"license": "MIT",
460
+
"engines": {
461
+
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
462
+
}
463
+
},
464
+
"node_modules/@eslint/config-array": {
465
+
"version": "0.21.1",
466
+
"dev": true,
467
+
"license": "Apache-2.0",
468
+
"dependencies": {
469
+
"@eslint/object-schema": "^2.1.7",
470
+
"debug": "^4.3.1",
471
+
"minimatch": "^3.1.2"
472
+
},
473
+
"engines": {
474
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
475
+
}
476
+
},
477
+
"node_modules/@eslint/config-array/node_modules/minimatch": {
478
+
"version": "3.1.2",
479
+
"dev": true,
480
+
"license": "ISC",
481
+
"dependencies": {
482
+
"brace-expansion": "^1.1.7"
483
+
},
484
+
"engines": {
485
+
"node": "*"
486
+
}
487
+
},
488
+
"node_modules/@eslint/config-helpers": {
489
+
"version": "0.4.2",
490
+
"dev": true,
491
+
"license": "Apache-2.0",
492
+
"dependencies": {
493
+
"@eslint/core": "^0.17.0"
494
+
},
495
+
"engines": {
496
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
497
+
}
498
+
},
499
+
"node_modules/@eslint/core": {
500
+
"version": "0.17.0",
501
+
"dev": true,
502
+
"license": "Apache-2.0",
503
+
"dependencies": {
504
+
"@types/json-schema": "^7.0.15"
505
+
},
506
+
"engines": {
507
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
508
+
}
509
+
},
510
+
"node_modules/@eslint/eslintrc": {
511
+
"version": "3.3.3",
512
+
"dev": true,
513
+
"license": "MIT",
514
+
"dependencies": {
515
+
"ajv": "^6.12.4",
516
+
"debug": "^4.3.2",
517
+
"espree": "^10.0.1",
518
+
"globals": "^14.0.0",
519
+
"ignore": "^5.2.0",
520
+
"import-fresh": "^3.2.1",
521
+
"js-yaml": "^4.1.1",
522
+
"minimatch": "^3.1.2",
523
+
"strip-json-comments": "^3.1.1"
524
+
},
525
+
"engines": {
526
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
527
+
},
528
+
"funding": {
529
+
"url": "https://opencollective.com/eslint"
530
+
}
531
+
},
532
+
"node_modules/@eslint/eslintrc/node_modules/ajv": {
533
+
"version": "6.12.6",
534
+
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
535
+
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
536
+
"dev": true,
537
+
"license": "MIT",
538
+
"dependencies": {
539
+
"fast-deep-equal": "^3.1.1",
540
+
"fast-json-stable-stringify": "^2.0.0",
541
+
"json-schema-traverse": "^0.4.1",
542
+
"uri-js": "^4.2.2"
543
+
},
544
+
"funding": {
545
+
"type": "github",
546
+
"url": "https://github.com/sponsors/epoberezkin"
547
+
}
548
+
},
549
+
"node_modules/@eslint/eslintrc/node_modules/globals": {
550
+
"version": "14.0.0",
551
+
"dev": true,
552
+
"license": "MIT",
553
+
"engines": {
554
+
"node": ">=18"
555
+
},
556
+
"funding": {
557
+
"url": "https://github.com/sponsors/sindresorhus"
558
+
}
559
+
},
560
+
"node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": {
561
+
"version": "0.4.1",
562
+
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
563
+
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
564
+
"dev": true,
565
+
"license": "MIT"
566
+
},
567
+
"node_modules/@eslint/eslintrc/node_modules/minimatch": {
568
+
"version": "3.1.2",
569
+
"dev": true,
570
+
"license": "ISC",
571
+
"dependencies": {
572
+
"brace-expansion": "^1.1.7"
573
+
},
574
+
"engines": {
575
+
"node": "*"
576
+
}
577
+
},
578
+
"node_modules/@eslint/js": {
579
+
"version": "9.39.1",
580
+
"dev": true,
581
+
"license": "MIT",
582
+
"engines": {
583
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
584
+
},
585
+
"funding": {
586
+
"url": "https://eslint.org/donate"
587
+
}
588
+
},
589
+
"node_modules/@eslint/object-schema": {
590
+
"version": "2.1.7",
591
+
"dev": true,
592
+
"license": "Apache-2.0",
593
+
"engines": {
594
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
595
+
}
596
+
},
597
+
"node_modules/@eslint/plugin-kit": {
598
+
"version": "0.4.1",
599
+
"dev": true,
600
+
"license": "Apache-2.0",
601
+
"dependencies": {
602
+
"@eslint/core": "^0.17.0",
603
+
"levn": "^0.4.1"
604
+
},
605
+
"engines": {
606
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
607
+
}
608
+
},
609
+
"node_modules/@humanfs/core": {
610
+
"version": "0.19.1",
611
+
"dev": true,
612
+
"license": "Apache-2.0",
613
+
"engines": {
614
+
"node": ">=18.18.0"
615
+
}
616
+
},
617
+
"node_modules/@humanfs/node": {
618
+
"version": "0.16.7",
619
+
"dev": true,
620
+
"license": "Apache-2.0",
621
+
"dependencies": {
622
+
"@humanfs/core": "^0.19.1",
623
+
"@humanwhocodes/retry": "^0.4.0"
624
+
},
625
+
"engines": {
626
+
"node": ">=18.18.0"
627
+
}
628
+
},
629
+
"node_modules/@humanwhocodes/module-importer": {
630
+
"version": "1.0.1",
631
+
"dev": true,
632
+
"license": "Apache-2.0",
633
+
"engines": {
634
+
"node": ">=12.22"
635
+
},
636
+
"funding": {
637
+
"type": "github",
638
+
"url": "https://github.com/sponsors/nzakas"
639
+
}
640
+
},
641
+
"node_modules/@humanwhocodes/retry": {
642
+
"version": "0.4.3",
643
+
"dev": true,
644
+
"license": "Apache-2.0",
645
+
"engines": {
646
+
"node": ">=18.18"
647
+
},
648
+
"funding": {
649
+
"type": "github",
650
+
"url": "https://github.com/sponsors/nzakas"
651
+
}
652
+
},
653
+
"node_modules/@isaacs/balanced-match": {
654
+
"version": "4.0.1",
655
+
"dev": true,
656
+
"license": "MIT",
657
+
"engines": {
658
+
"node": "20 || >=22"
659
+
}
660
+
},
661
+
"node_modules/@isaacs/brace-expansion": {
662
+
"version": "5.0.0",
663
+
"dev": true,
664
+
"license": "MIT",
665
+
"dependencies": {
666
+
"@isaacs/balanced-match": "^4.0.1"
667
+
},
668
+
"engines": {
669
+
"node": "20 || >=22"
670
+
}
671
+
},
672
+
"node_modules/@jridgewell/gen-mapping": {
673
+
"version": "0.3.13",
674
+
"dev": true,
675
+
"license": "MIT",
676
+
"dependencies": {
677
+
"@jridgewell/sourcemap-codec": "^1.5.0",
678
+
"@jridgewell/trace-mapping": "^0.3.24"
679
+
}
680
+
},
681
+
"node_modules/@jridgewell/remapping": {
682
+
"version": "2.3.5",
683
+
"dev": true,
684
+
"license": "MIT",
685
+
"dependencies": {
686
+
"@jridgewell/gen-mapping": "^0.3.5",
687
+
"@jridgewell/trace-mapping": "^0.3.24"
688
+
}
689
+
},
690
+
"node_modules/@jridgewell/resolve-uri": {
691
+
"version": "3.1.2",
692
+
"dev": true,
693
+
"license": "MIT",
694
+
"engines": {
695
+
"node": ">=6.0.0"
696
+
}
697
+
},
698
+
"node_modules/@jridgewell/source-map": {
699
+
"version": "0.3.11",
700
+
"dev": true,
701
+
"license": "MIT",
702
+
"optional": true,
703
+
"dependencies": {
704
+
"@jridgewell/gen-mapping": "^0.3.5",
705
+
"@jridgewell/trace-mapping": "^0.3.25"
706
+
}
707
+
},
708
+
"node_modules/@jridgewell/sourcemap-codec": {
709
+
"version": "1.5.5",
710
+
"dev": true,
711
+
"license": "MIT"
712
+
},
713
+
"node_modules/@jridgewell/trace-mapping": {
714
+
"version": "0.3.31",
715
+
"dev": true,
716
+
"license": "MIT",
717
+
"dependencies": {
718
+
"@jridgewell/resolve-uri": "^3.1.0",
719
+
"@jridgewell/sourcemap-codec": "^1.4.14"
720
+
}
721
+
},
722
+
"node_modules/@microsoft/api-extractor": {
723
+
"version": "7.55.1",
724
+
"dev": true,
725
+
"license": "MIT",
726
+
"dependencies": {
727
+
"@microsoft/api-extractor-model": "7.32.1",
728
+
"@microsoft/tsdoc": "~0.16.0",
729
+
"@microsoft/tsdoc-config": "~0.18.0",
730
+
"@rushstack/node-core-library": "5.19.0",
731
+
"@rushstack/rig-package": "0.6.0",
732
+
"@rushstack/terminal": "0.19.4",
733
+
"@rushstack/ts-command-line": "5.1.4",
734
+
"diff": "~8.0.2",
735
+
"lodash": "~4.17.15",
736
+
"minimatch": "10.0.3",
737
+
"resolve": "~1.22.1",
738
+
"semver": "~7.5.4",
739
+
"source-map": "~0.6.1",
740
+
"typescript": "5.8.2"
741
+
},
742
+
"bin": {
743
+
"api-extractor": "bin/api-extractor"
744
+
}
745
+
},
746
+
"node_modules/@microsoft/api-extractor-model": {
747
+
"version": "7.32.1",
748
+
"dev": true,
749
+
"license": "MIT",
750
+
"dependencies": {
751
+
"@microsoft/tsdoc": "~0.16.0",
752
+
"@microsoft/tsdoc-config": "~0.18.0",
753
+
"@rushstack/node-core-library": "5.19.0"
754
+
}
755
+
},
756
+
"node_modules/@microsoft/api-extractor/node_modules/typescript": {
757
+
"version": "5.8.2",
758
+
"dev": true,
759
+
"license": "Apache-2.0",
760
+
"bin": {
761
+
"tsc": "bin/tsc",
762
+
"tsserver": "bin/tsserver"
763
+
},
764
+
"engines": {
765
+
"node": ">=14.17"
766
+
}
767
+
},
768
+
"node_modules/@microsoft/tsdoc": {
769
+
"version": "0.16.0",
770
+
"dev": true,
771
+
"license": "MIT"
772
+
},
773
+
"node_modules/@microsoft/tsdoc-config": {
774
+
"version": "0.18.0",
775
+
"dev": true,
776
+
"license": "MIT",
777
+
"dependencies": {
778
+
"@microsoft/tsdoc": "0.16.0",
779
+
"ajv": "~8.12.0",
780
+
"jju": "~1.4.0",
781
+
"resolve": "~1.22.2"
782
+
}
783
+
},
784
+
"node_modules/@microsoft/tsdoc-config/node_modules/ajv": {
785
+
"version": "8.12.0",
786
+
"dev": true,
787
+
"license": "MIT",
788
+
"dependencies": {
789
+
"fast-deep-equal": "^3.1.1",
790
+
"json-schema-traverse": "^1.0.0",
791
+
"require-from-string": "^2.0.2",
792
+
"uri-js": "^4.2.2"
793
+
},
794
+
"funding": {
795
+
"type": "github",
796
+
"url": "https://github.com/sponsors/epoberezkin"
797
+
}
798
+
},
799
+
"node_modules/@napi-rs/wasm-runtime": {
800
+
"version": "1.1.0",
801
+
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.0.tgz",
802
+
"integrity": "sha512-Fq6DJW+Bb5jaWE69/qOE0D1TUN9+6uWhCeZpdnSBk14pjLcCWR7Q8n49PTSPHazM37JqrsdpEthXy2xn6jWWiA==",
803
+
"dev": true,
804
+
"license": "MIT",
805
+
"optional": true,
806
+
"dependencies": {
807
+
"@emnapi/core": "^1.7.1",
808
+
"@emnapi/runtime": "^1.7.1",
809
+
"@tybys/wasm-util": "^0.10.1"
810
+
}
811
+
},
812
+
"node_modules/@oxc-project/runtime": {
813
+
"version": "0.92.0",
814
+
"dev": true,
815
+
"license": "MIT",
816
+
"engines": {
817
+
"node": "^20.19.0 || >=22.12.0"
818
+
}
819
+
},
820
+
"node_modules/@oxc-project/types": {
821
+
"version": "0.93.0",
822
+
"dev": true,
823
+
"license": "MIT",
824
+
"funding": {
825
+
"url": "https://github.com/sponsors/Boshen"
826
+
}
827
+
},
828
+
"node_modules/@rolldown/binding-android-arm64": {
829
+
"version": "1.0.0-beta.41",
830
+
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-beta.41.tgz",
831
+
"integrity": "sha512-Edflndd9lU7JVhVIvJlZhdCj5DkhYDJPIRn4Dx0RUdfc8asP9xHOI5gMd8MesDDx+BJpdIT/uAmVTearteU/mQ==",
832
+
"cpu": [
833
+
"arm64"
834
+
],
835
+
"dev": true,
836
+
"license": "MIT",
837
+
"optional": true,
838
+
"os": [
839
+
"android"
840
+
],
841
+
"engines": {
842
+
"node": "^20.19.0 || >=22.12.0"
843
+
}
844
+
},
845
+
"node_modules/@rolldown/binding-darwin-arm64": {
846
+
"version": "1.0.0-beta.41",
847
+
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-beta.41.tgz",
848
+
"integrity": "sha512-XGCzqfjdk7550PlyZRTBKbypXrB7ATtXhw/+bjtxnklLQs0mKP/XkQVOKyn9qGKSlvH8I56JLYryVxl0PCvSNw==",
849
+
"cpu": [
850
+
"arm64"
851
+
],
852
+
"dev": true,
853
+
"license": "MIT",
854
+
"optional": true,
855
+
"os": [
856
+
"darwin"
857
+
],
858
+
"engines": {
859
+
"node": "^20.19.0 || >=22.12.0"
860
+
}
861
+
},
862
+
"node_modules/@rolldown/binding-darwin-x64": {
863
+
"version": "1.0.0-beta.41",
864
+
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-beta.41.tgz",
865
+
"integrity": "sha512-Ho6lIwGJed98zub7n0xcRKuEtnZgbxevAmO4x3zn3C3N4GVXZD5xvCvTVxSMoeBJwTcIYzkVDRTIhylQNsTgLQ==",
866
+
"cpu": [
867
+
"x64"
868
+
],
869
+
"dev": true,
870
+
"license": "MIT",
871
+
"optional": true,
872
+
"os": [
873
+
"darwin"
874
+
],
875
+
"engines": {
876
+
"node": "^20.19.0 || >=22.12.0"
877
+
}
878
+
},
879
+
"node_modules/@rolldown/binding-freebsd-x64": {
880
+
"version": "1.0.0-beta.41",
881
+
"resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-beta.41.tgz",
882
+
"integrity": "sha512-ijAZETywvL+gACjbT4zBnCp5ez1JhTRs6OxRN4J+D6AzDRbU2zb01Esl51RP5/8ZOlvB37xxsRQ3X4YRVyYb3g==",
883
+
"cpu": [
884
+
"x64"
885
+
],
886
+
"dev": true,
887
+
"license": "MIT",
888
+
"optional": true,
889
+
"os": [
890
+
"freebsd"
891
+
],
892
+
"engines": {
893
+
"node": "^20.19.0 || >=22.12.0"
894
+
}
895
+
},
896
+
"node_modules/@rolldown/binding-linux-arm-gnueabihf": {
897
+
"version": "1.0.0-beta.41",
898
+
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-beta.41.tgz",
899
+
"integrity": "sha512-EgIOZt7UildXKFEFvaiLNBXm+4ggQyGe3E5Z1QP9uRcJJs9omihOnm897FwOBQdCuMvI49iBgjFrkhH+wMJ2MA==",
900
+
"cpu": [
901
+
"arm"
902
+
],
903
+
"dev": true,
904
+
"license": "MIT",
905
+
"optional": true,
906
+
"os": [
907
+
"linux"
908
+
],
909
+
"engines": {
910
+
"node": "^20.19.0 || >=22.12.0"
911
+
}
912
+
},
913
+
"node_modules/@rolldown/binding-linux-arm64-gnu": {
914
+
"version": "1.0.0-beta.41",
915
+
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-beta.41.tgz",
916
+
"integrity": "sha512-F8bUwJq8v/JAU8HSwgF4dztoqJ+FjdyjuvX4//3+Fbe2we9UktFeZ27U4lRMXF1vxWtdV4ey6oCSqI7yUrSEeg==",
917
+
"cpu": [
918
+
"arm64"
919
+
],
920
+
"dev": true,
921
+
"license": "MIT",
922
+
"optional": true,
923
+
"os": [
924
+
"linux"
925
+
],
926
+
"engines": {
927
+
"node": "^20.19.0 || >=22.12.0"
928
+
}
929
+
},
930
+
"node_modules/@rolldown/binding-linux-arm64-musl": {
931
+
"version": "1.0.0-beta.41",
932
+
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-beta.41.tgz",
933
+
"integrity": "sha512-MioXcCIX/wB1pBnBoJx8q4OGucUAfC1+/X1ilKFsjDK05VwbLZGRgOVD5OJJpUQPK86DhQciNBrfOKDiatxNmg==",
934
+
"cpu": [
935
+
"arm64"
936
+
],
937
+
"dev": true,
938
+
"license": "MIT",
939
+
"optional": true,
940
+
"os": [
941
+
"linux"
942
+
],
943
+
"engines": {
944
+
"node": "^20.19.0 || >=22.12.0"
945
+
}
946
+
},
947
+
"node_modules/@rolldown/binding-linux-x64-gnu": {
948
+
"version": "1.0.0-beta.41",
949
+
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-beta.41.tgz",
950
+
"integrity": "sha512-m66M61fizvRCwt5pOEiZQMiwBL9/y0bwU/+Kc4Ce/Pef6YfoEkR28y+DzN9rMdjo8Z28NXjsDPq9nH4mXnAP0g==",
951
+
"cpu": [
952
+
"x64"
953
+
],
954
+
"dev": true,
955
+
"license": "MIT",
956
+
"optional": true,
957
+
"os": [
958
+
"linux"
959
+
],
960
+
"engines": {
961
+
"node": "^20.19.0 || >=22.12.0"
962
+
}
963
+
},
964
+
"node_modules/@rolldown/binding-linux-x64-musl": {
965
+
"version": "1.0.0-beta.41",
966
+
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-beta.41.tgz",
967
+
"integrity": "sha512-yRxlSfBvWnnfrdtJfvi9lg8xfG5mPuyoSHm0X01oiE8ArmLRvoJGHUTJydCYz+wbK2esbq5J4B4Tq9WAsOlP1Q==",
968
+
"cpu": [
969
+
"x64"
970
+
],
971
+
"dev": true,
972
+
"license": "MIT",
973
+
"optional": true,
974
+
"os": [
975
+
"linux"
976
+
],
977
+
"engines": {
978
+
"node": "^20.19.0 || >=22.12.0"
979
+
}
980
+
},
981
+
"node_modules/@rolldown/binding-openharmony-arm64": {
982
+
"version": "1.0.0-beta.41",
983
+
"resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-beta.41.tgz",
984
+
"integrity": "sha512-PHVxYhBpi8UViS3/hcvQQb9RFqCtvFmFU1PvUoTRiUdBtgHA6fONNHU4x796lgzNlVSD3DO/MZNk1s5/ozSMQg==",
985
+
"cpu": [
986
+
"arm64"
987
+
],
988
+
"dev": true,
989
+
"license": "MIT",
990
+
"optional": true,
991
+
"os": [
992
+
"openharmony"
993
+
],
994
+
"engines": {
995
+
"node": "^20.19.0 || >=22.12.0"
996
+
}
997
+
},
998
+
"node_modules/@rolldown/binding-wasm32-wasi": {
999
+
"version": "1.0.0-beta.41",
1000
+
"resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-beta.41.tgz",
1001
+
"integrity": "sha512-OAfcO37ME6GGWmj9qTaDT7jY4rM0T2z0/8ujdQIJQ2x2nl+ztO32EIwURfmXOK0U1tzkyuaKYvE34Pug/ucXlQ==",
1002
+
"cpu": [
1003
+
"wasm32"
1004
+
],
1005
+
"dev": true,
1006
+
"license": "MIT",
1007
+
"optional": true,
1008
+
"dependencies": {
1009
+
"@napi-rs/wasm-runtime": "^1.0.5"
1010
+
},
1011
+
"engines": {
1012
+
"node": ">=14.0.0"
1013
+
}
1014
+
},
1015
+
"node_modules/@rolldown/binding-win32-arm64-msvc": {
1016
+
"version": "1.0.0-beta.41",
1017
+
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-beta.41.tgz",
1018
+
"integrity": "sha512-NIYGuCcuXaq5BC4Q3upbiMBvmZsTsEPG9k/8QKQdmrch+ocSy5Jv9tdpdmXJyighKqm182nh/zBt+tSJkYoNlg==",
1019
+
"cpu": [
1020
+
"arm64"
1021
+
],
1022
+
"dev": true,
1023
+
"license": "MIT",
1024
+
"optional": true,
1025
+
"os": [
1026
+
"win32"
1027
+
],
1028
+
"engines": {
1029
+
"node": "^20.19.0 || >=22.12.0"
1030
+
}
1031
+
},
1032
+
"node_modules/@rolldown/binding-win32-ia32-msvc": {
1033
+
"version": "1.0.0-beta.41",
1034
+
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.0.0-beta.41.tgz",
1035
+
"integrity": "sha512-kANdsDbE5FkEOb5NrCGBJBCaZ2Sabp3D7d4PRqMYJqyLljwh9mDyYyYSv5+QNvdAmifj+f3lviNEUUuUZPEFPw==",
1036
+
"cpu": [
1037
+
"ia32"
1038
+
],
1039
+
"dev": true,
1040
+
"license": "MIT",
1041
+
"optional": true,
1042
+
"os": [
1043
+
"win32"
1044
+
],
1045
+
"engines": {
1046
+
"node": "^20.19.0 || >=22.12.0"
1047
+
}
1048
+
},
1049
+
"node_modules/@rolldown/binding-win32-x64-msvc": {
1050
+
"version": "1.0.0-beta.41",
1051
+
"cpu": [
1052
+
"x64"
1053
+
],
1054
+
"dev": true,
1055
+
"license": "MIT",
1056
+
"optional": true,
1057
+
"os": [
1058
+
"win32"
1059
+
],
1060
+
"engines": {
1061
+
"node": "^20.19.0 || >=22.12.0"
1062
+
}
1063
+
},
1064
+
"node_modules/@rolldown/pluginutils": {
1065
+
"version": "1.0.0-beta.47",
1066
+
"dev": true,
1067
+
"license": "MIT"
1068
+
},
1069
+
"node_modules/@rollup/pluginutils": {
1070
+
"version": "4.2.1",
1071
+
"dev": true,
1072
+
"license": "MIT",
1073
+
"dependencies": {
1074
+
"estree-walker": "^2.0.1",
1075
+
"picomatch": "^2.2.2"
1076
+
},
1077
+
"engines": {
1078
+
"node": ">= 8.0.0"
1079
+
}
1080
+
},
1081
+
"node_modules/@rollup/pluginutils/node_modules/picomatch": {
1082
+
"version": "2.3.1",
1083
+
"dev": true,
1084
+
"license": "MIT",
1085
+
"engines": {
1086
+
"node": ">=8.6"
1087
+
},
1088
+
"funding": {
1089
+
"url": "https://github.com/sponsors/jonschlinkert"
1090
+
}
1091
+
},
1092
+
"node_modules/@rollup/rollup-android-arm-eabi": {
1093
+
"version": "4.53.3",
1094
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz",
1095
+
"integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==",
1096
+
"cpu": [
1097
+
"arm"
1098
+
],
1099
+
"dev": true,
1100
+
"license": "MIT",
1101
+
"optional": true,
1102
+
"os": [
1103
+
"android"
1104
+
]
1105
+
},
1106
+
"node_modules/@rollup/rollup-android-arm64": {
1107
+
"version": "4.53.3",
1108
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz",
1109
+
"integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==",
1110
+
"cpu": [
1111
+
"arm64"
1112
+
],
1113
+
"dev": true,
1114
+
"license": "MIT",
1115
+
"optional": true,
1116
+
"os": [
1117
+
"android"
1118
+
]
1119
+
},
1120
+
"node_modules/@rollup/rollup-darwin-arm64": {
1121
+
"version": "4.53.3",
1122
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz",
1123
+
"integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==",
1124
+
"cpu": [
1125
+
"arm64"
1126
+
],
1127
+
"dev": true,
1128
+
"license": "MIT",
1129
+
"optional": true,
1130
+
"os": [
1131
+
"darwin"
1132
+
]
1133
+
},
1134
+
"node_modules/@rollup/rollup-darwin-x64": {
1135
+
"version": "4.53.3",
1136
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz",
1137
+
"integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==",
1138
+
"cpu": [
1139
+
"x64"
1140
+
],
1141
+
"dev": true,
1142
+
"license": "MIT",
1143
+
"optional": true,
1144
+
"os": [
1145
+
"darwin"
1146
+
]
1147
+
},
1148
+
"node_modules/@rollup/rollup-freebsd-arm64": {
1149
+
"version": "4.53.3",
1150
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz",
1151
+
"integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==",
1152
+
"cpu": [
1153
+
"arm64"
1154
+
],
1155
+
"dev": true,
1156
+
"license": "MIT",
1157
+
"optional": true,
1158
+
"os": [
1159
+
"freebsd"
1160
+
]
1161
+
},
1162
+
"node_modules/@rollup/rollup-freebsd-x64": {
1163
+
"version": "4.53.3",
1164
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz",
1165
+
"integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==",
1166
+
"cpu": [
1167
+
"x64"
1168
+
],
1169
+
"dev": true,
1170
+
"license": "MIT",
1171
+
"optional": true,
1172
+
"os": [
1173
+
"freebsd"
1174
+
]
1175
+
},
1176
+
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
1177
+
"version": "4.53.3",
1178
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz",
1179
+
"integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==",
1180
+
"cpu": [
1181
+
"arm"
1182
+
],
1183
+
"dev": true,
1184
+
"license": "MIT",
1185
+
"optional": true,
1186
+
"os": [
1187
+
"linux"
1188
+
]
1189
+
},
1190
+
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
1191
+
"version": "4.53.3",
1192
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz",
1193
+
"integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==",
1194
+
"cpu": [
1195
+
"arm"
1196
+
],
1197
+
"dev": true,
1198
+
"license": "MIT",
1199
+
"optional": true,
1200
+
"os": [
1201
+
"linux"
1202
+
]
1203
+
},
1204
+
"node_modules/@rollup/rollup-linux-arm64-gnu": {
1205
+
"version": "4.53.3",
1206
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz",
1207
+
"integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==",
1208
+
"cpu": [
1209
+
"arm64"
1210
+
],
1211
+
"dev": true,
1212
+
"license": "MIT",
1213
+
"optional": true,
1214
+
"os": [
1215
+
"linux"
1216
+
]
1217
+
},
1218
+
"node_modules/@rollup/rollup-linux-arm64-musl": {
1219
+
"version": "4.53.3",
1220
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz",
1221
+
"integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==",
1222
+
"cpu": [
1223
+
"arm64"
1224
+
],
1225
+
"dev": true,
1226
+
"license": "MIT",
1227
+
"optional": true,
1228
+
"os": [
1229
+
"linux"
1230
+
]
1231
+
},
1232
+
"node_modules/@rollup/rollup-linux-loong64-gnu": {
1233
+
"version": "4.53.3",
1234
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz",
1235
+
"integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==",
1236
+
"cpu": [
1237
+
"loong64"
1238
+
],
1239
+
"dev": true,
1240
+
"license": "MIT",
1241
+
"optional": true,
1242
+
"os": [
1243
+
"linux"
1244
+
]
1245
+
},
1246
+
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
1247
+
"version": "4.53.3",
1248
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz",
1249
+
"integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==",
1250
+
"cpu": [
1251
+
"ppc64"
1252
+
],
1253
+
"dev": true,
1254
+
"license": "MIT",
1255
+
"optional": true,
1256
+
"os": [
1257
+
"linux"
1258
+
]
1259
+
},
1260
+
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
1261
+
"version": "4.53.3",
1262
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz",
1263
+
"integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==",
1264
+
"cpu": [
1265
+
"riscv64"
1266
+
],
1267
+
"dev": true,
1268
+
"license": "MIT",
1269
+
"optional": true,
1270
+
"os": [
1271
+
"linux"
1272
+
]
1273
+
},
1274
+
"node_modules/@rollup/rollup-linux-riscv64-musl": {
1275
+
"version": "4.53.3",
1276
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz",
1277
+
"integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==",
1278
+
"cpu": [
1279
+
"riscv64"
1280
+
],
1281
+
"dev": true,
1282
+
"license": "MIT",
1283
+
"optional": true,
1284
+
"os": [
1285
+
"linux"
1286
+
]
1287
+
},
1288
+
"node_modules/@rollup/rollup-linux-s390x-gnu": {
1289
+
"version": "4.53.3",
1290
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz",
1291
+
"integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==",
1292
+
"cpu": [
1293
+
"s390x"
1294
+
],
1295
+
"dev": true,
1296
+
"license": "MIT",
1297
+
"optional": true,
1298
+
"os": [
1299
+
"linux"
1300
+
]
1301
+
},
1302
+
"node_modules/@rollup/rollup-linux-x64-gnu": {
1303
+
"version": "4.53.3",
1304
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz",
1305
+
"integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==",
1306
+
"cpu": [
1307
+
"x64"
1308
+
],
1309
+
"dev": true,
1310
+
"license": "MIT",
1311
+
"optional": true,
1312
+
"os": [
1313
+
"linux"
1314
+
]
1315
+
},
1316
+
"node_modules/@rollup/rollup-linux-x64-musl": {
1317
+
"version": "4.53.3",
1318
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz",
1319
+
"integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==",
1320
+
"cpu": [
1321
+
"x64"
1322
+
],
1323
+
"dev": true,
1324
+
"license": "MIT",
1325
+
"optional": true,
1326
+
"os": [
1327
+
"linux"
1328
+
]
1329
+
},
1330
+
"node_modules/@rollup/rollup-openharmony-arm64": {
1331
+
"version": "4.53.3",
1332
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz",
1333
+
"integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==",
1334
+
"cpu": [
1335
+
"arm64"
1336
+
],
1337
+
"dev": true,
1338
+
"license": "MIT",
1339
+
"optional": true,
1340
+
"os": [
1341
+
"openharmony"
1342
+
]
1343
+
},
1344
+
"node_modules/@rollup/rollup-win32-arm64-msvc": {
1345
+
"version": "4.53.3",
1346
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz",
1347
+
"integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==",
1348
+
"cpu": [
1349
+
"arm64"
1350
+
],
1351
+
"dev": true,
1352
+
"license": "MIT",
1353
+
"optional": true,
1354
+
"os": [
1355
+
"win32"
1356
+
]
1357
+
},
1358
+
"node_modules/@rollup/rollup-win32-ia32-msvc": {
1359
+
"version": "4.53.3",
1360
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz",
1361
+
"integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==",
1362
+
"cpu": [
1363
+
"ia32"
1364
+
],
1365
+
"dev": true,
1366
+
"license": "MIT",
1367
+
"optional": true,
1368
+
"os": [
1369
+
"win32"
1370
+
]
1371
+
},
1372
+
"node_modules/@rollup/rollup-win32-x64-gnu": {
1373
+
"version": "4.53.3",
1374
+
"cpu": [
1375
+
"x64"
1376
+
],
1377
+
"dev": true,
1378
+
"license": "MIT",
1379
+
"optional": true,
1380
+
"os": [
1381
+
"win32"
1382
+
]
1383
+
},
1384
+
"node_modules/@rollup/rollup-win32-x64-msvc": {
1385
+
"version": "4.53.3",
1386
+
"cpu": [
1387
+
"x64"
1388
+
],
1389
+
"dev": true,
1390
+
"license": "MIT",
1391
+
"optional": true,
1392
+
"os": [
1393
+
"win32"
1394
+
]
1395
+
},
1396
+
"node_modules/@rushstack/node-core-library": {
1397
+
"version": "5.19.0",
1398
+
"dev": true,
1399
+
"license": "MIT",
1400
+
"dependencies": {
1401
+
"ajv": "~8.13.0",
1402
+
"ajv-draft-04": "~1.0.0",
1403
+
"ajv-formats": "~3.0.1",
1404
+
"fs-extra": "~11.3.0",
1405
+
"import-lazy": "~4.0.0",
1406
+
"jju": "~1.4.0",
1407
+
"resolve": "~1.22.1",
1408
+
"semver": "~7.5.4"
1409
+
},
1410
+
"peerDependencies": {
1411
+
"@types/node": "*"
1412
+
},
1413
+
"peerDependenciesMeta": {
1414
+
"@types/node": {
1415
+
"optional": true
1416
+
}
1417
+
}
1418
+
},
1419
+
"node_modules/@rushstack/node-core-library/node_modules/ajv": {
1420
+
"version": "8.13.0",
1421
+
"dev": true,
1422
+
"license": "MIT",
1423
+
"dependencies": {
1424
+
"fast-deep-equal": "^3.1.3",
1425
+
"json-schema-traverse": "^1.0.0",
1426
+
"require-from-string": "^2.0.2",
1427
+
"uri-js": "^4.4.1"
1428
+
},
1429
+
"funding": {
1430
+
"type": "github",
1431
+
"url": "https://github.com/sponsors/epoberezkin"
1432
+
}
1433
+
},
1434
+
"node_modules/@rushstack/node-core-library/node_modules/fs-extra": {
1435
+
"version": "11.3.2",
1436
+
"dev": true,
1437
+
"license": "MIT",
1438
+
"dependencies": {
1439
+
"graceful-fs": "^4.2.0",
1440
+
"jsonfile": "^6.0.1",
1441
+
"universalify": "^2.0.0"
1442
+
},
1443
+
"engines": {
1444
+
"node": ">=14.14"
1445
+
}
1446
+
},
1447
+
"node_modules/@rushstack/problem-matcher": {
1448
+
"version": "0.1.1",
1449
+
"dev": true,
1450
+
"license": "MIT",
1451
+
"peerDependencies": {
1452
+
"@types/node": "*"
1453
+
},
1454
+
"peerDependenciesMeta": {
1455
+
"@types/node": {
1456
+
"optional": true
1457
+
}
1458
+
}
1459
+
},
1460
+
"node_modules/@rushstack/rig-package": {
1461
+
"version": "0.6.0",
1462
+
"dev": true,
1463
+
"license": "MIT",
1464
+
"dependencies": {
1465
+
"resolve": "~1.22.1",
1466
+
"strip-json-comments": "~3.1.1"
1467
+
}
1468
+
},
1469
+
"node_modules/@rushstack/terminal": {
1470
+
"version": "0.19.4",
1471
+
"dev": true,
1472
+
"license": "MIT",
1473
+
"dependencies": {
1474
+
"@rushstack/node-core-library": "5.19.0",
1475
+
"@rushstack/problem-matcher": "0.1.1",
1476
+
"supports-color": "~8.1.1"
1477
+
},
1478
+
"peerDependencies": {
1479
+
"@types/node": "*"
1480
+
},
1481
+
"peerDependenciesMeta": {
1482
+
"@types/node": {
1483
+
"optional": true
1484
+
}
1485
+
}
1486
+
},
1487
+
"node_modules/@rushstack/ts-command-line": {
1488
+
"version": "5.1.4",
1489
+
"dev": true,
1490
+
"license": "MIT",
1491
+
"dependencies": {
1492
+
"@rushstack/terminal": "0.19.4",
1493
+
"@types/argparse": "1.0.38",
1494
+
"argparse": "~1.0.9",
1495
+
"string-argv": "~0.3.1"
1496
+
}
1497
+
},
1498
+
"node_modules/@standard-schema/spec": {
1499
+
"version": "1.0.0",
1500
+
"license": "MIT"
1501
+
},
1502
+
"node_modules/@tybys/wasm-util": {
1503
+
"version": "0.10.1",
1504
+
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
1505
+
"integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
1506
+
"dev": true,
1507
+
"license": "MIT",
1508
+
"optional": true,
1509
+
"dependencies": {
1510
+
"tslib": "^2.4.0"
1511
+
}
1512
+
},
1513
+
"node_modules/@types/argparse": {
1514
+
"version": "1.0.38",
1515
+
"dev": true,
1516
+
"license": "MIT"
1517
+
},
1518
+
"node_modules/@types/babel__core": {
1519
+
"version": "7.20.5",
1520
+
"dev": true,
1521
+
"license": "MIT",
1522
+
"dependencies": {
1523
+
"@babel/parser": "^7.20.7",
1524
+
"@babel/types": "^7.20.7",
1525
+
"@types/babel__generator": "*",
1526
+
"@types/babel__template": "*",
1527
+
"@types/babel__traverse": "*"
1528
+
}
1529
+
},
1530
+
"node_modules/@types/babel__generator": {
1531
+
"version": "7.27.0",
1532
+
"dev": true,
1533
+
"license": "MIT",
1534
+
"dependencies": {
1535
+
"@babel/types": "^7.0.0"
1536
+
}
1537
+
},
1538
+
"node_modules/@types/babel__template": {
1539
+
"version": "7.4.4",
1540
+
"dev": true,
1541
+
"license": "MIT",
1542
+
"dependencies": {
1543
+
"@babel/parser": "^7.1.0",
1544
+
"@babel/types": "^7.0.0"
1545
+
}
1546
+
},
1547
+
"node_modules/@types/babel__traverse": {
1548
+
"version": "7.28.0",
1549
+
"dev": true,
1550
+
"license": "MIT",
1551
+
"dependencies": {
1552
+
"@babel/types": "^7.28.2"
1553
+
}
1554
+
},
1555
+
"node_modules/@types/estree": {
1556
+
"version": "1.0.8",
1557
+
"dev": true,
1558
+
"license": "MIT"
1559
+
},
1560
+
"node_modules/@types/json-schema": {
1561
+
"version": "7.0.15",
1562
+
"dev": true,
1563
+
"license": "MIT"
1564
+
},
1565
+
"node_modules/@types/node": {
1566
+
"version": "24.10.1",
1567
+
"dev": true,
1568
+
"license": "MIT",
1569
+
"peer": true,
1570
+
"dependencies": {
1571
+
"undici-types": "~7.16.0"
1572
+
}
1573
+
},
1574
+
"node_modules/@types/react": {
1575
+
"version": "19.2.7",
1576
+
"dev": true,
1577
+
"license": "MIT",
1578
+
"peer": true,
1579
+
"dependencies": {
1580
+
"csstype": "^3.2.2"
1581
+
}
1582
+
},
1583
+
"node_modules/@types/react-dom": {
1584
+
"version": "19.2.3",
1585
+
"dev": true,
1586
+
"license": "MIT",
1587
+
"peerDependencies": {
1588
+
"@types/react": "^19.2.0"
1589
+
}
1590
+
},
1591
+
"node_modules/@typescript-eslint/eslint-plugin": {
1592
+
"version": "8.48.1",
1593
+
"dev": true,
1594
+
"license": "MIT",
1595
+
"dependencies": {
1596
+
"@eslint-community/regexpp": "^4.10.0",
1597
+
"@typescript-eslint/scope-manager": "8.48.1",
1598
+
"@typescript-eslint/type-utils": "8.48.1",
1599
+
"@typescript-eslint/utils": "8.48.1",
1600
+
"@typescript-eslint/visitor-keys": "8.48.1",
1601
+
"graphemer": "^1.4.0",
1602
+
"ignore": "^7.0.0",
1603
+
"natural-compare": "^1.4.0",
1604
+
"ts-api-utils": "^2.1.0"
1605
+
},
1606
+
"engines": {
1607
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1608
+
},
1609
+
"funding": {
1610
+
"type": "opencollective",
1611
+
"url": "https://opencollective.com/typescript-eslint"
1612
+
},
1613
+
"peerDependencies": {
1614
+
"@typescript-eslint/parser": "^8.48.1",
1615
+
"eslint": "^8.57.0 || ^9.0.0",
1616
+
"typescript": ">=4.8.4 <6.0.0"
1617
+
}
1618
+
},
1619
+
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
1620
+
"version": "7.0.5",
1621
+
"dev": true,
1622
+
"license": "MIT",
1623
+
"engines": {
1624
+
"node": ">= 4"
1625
+
}
1626
+
},
1627
+
"node_modules/@typescript-eslint/parser": {
1628
+
"version": "8.48.1",
1629
+
"dev": true,
1630
+
"license": "MIT",
1631
+
"peer": true,
1632
+
"dependencies": {
1633
+
"@typescript-eslint/scope-manager": "8.48.1",
1634
+
"@typescript-eslint/types": "8.48.1",
1635
+
"@typescript-eslint/typescript-estree": "8.48.1",
1636
+
"@typescript-eslint/visitor-keys": "8.48.1",
1637
+
"debug": "^4.3.4"
1638
+
},
1639
+
"engines": {
1640
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1641
+
},
1642
+
"funding": {
1643
+
"type": "opencollective",
1644
+
"url": "https://opencollective.com/typescript-eslint"
1645
+
},
1646
+
"peerDependencies": {
1647
+
"eslint": "^8.57.0 || ^9.0.0",
1648
+
"typescript": ">=4.8.4 <6.0.0"
1649
+
}
1650
+
},
1651
+
"node_modules/@typescript-eslint/project-service": {
1652
+
"version": "8.48.1",
1653
+
"dev": true,
1654
+
"license": "MIT",
1655
+
"dependencies": {
1656
+
"@typescript-eslint/tsconfig-utils": "^8.48.1",
1657
+
"@typescript-eslint/types": "^8.48.1",
1658
+
"debug": "^4.3.4"
1659
+
},
1660
+
"engines": {
1661
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1662
+
},
1663
+
"funding": {
1664
+
"type": "opencollective",
1665
+
"url": "https://opencollective.com/typescript-eslint"
1666
+
},
1667
+
"peerDependencies": {
1668
+
"typescript": ">=4.8.4 <6.0.0"
1669
+
}
1670
+
},
1671
+
"node_modules/@typescript-eslint/scope-manager": {
1672
+
"version": "8.48.1",
1673
+
"dev": true,
1674
+
"license": "MIT",
1675
+
"dependencies": {
1676
+
"@typescript-eslint/types": "8.48.1",
1677
+
"@typescript-eslint/visitor-keys": "8.48.1"
1678
+
},
1679
+
"engines": {
1680
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1681
+
},
1682
+
"funding": {
1683
+
"type": "opencollective",
1684
+
"url": "https://opencollective.com/typescript-eslint"
1685
+
}
1686
+
},
1687
+
"node_modules/@typescript-eslint/tsconfig-utils": {
1688
+
"version": "8.48.1",
1689
+
"dev": true,
1690
+
"license": "MIT",
1691
+
"engines": {
1692
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1693
+
},
1694
+
"funding": {
1695
+
"type": "opencollective",
1696
+
"url": "https://opencollective.com/typescript-eslint"
1697
+
},
1698
+
"peerDependencies": {
1699
+
"typescript": ">=4.8.4 <6.0.0"
1700
+
}
1701
+
},
1702
+
"node_modules/@typescript-eslint/type-utils": {
1703
+
"version": "8.48.1",
1704
+
"dev": true,
1705
+
"license": "MIT",
1706
+
"dependencies": {
1707
+
"@typescript-eslint/types": "8.48.1",
1708
+
"@typescript-eslint/typescript-estree": "8.48.1",
1709
+
"@typescript-eslint/utils": "8.48.1",
1710
+
"debug": "^4.3.4",
1711
+
"ts-api-utils": "^2.1.0"
1712
+
},
1713
+
"engines": {
1714
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1715
+
},
1716
+
"funding": {
1717
+
"type": "opencollective",
1718
+
"url": "https://opencollective.com/typescript-eslint"
1719
+
},
1720
+
"peerDependencies": {
1721
+
"eslint": "^8.57.0 || ^9.0.0",
1722
+
"typescript": ">=4.8.4 <6.0.0"
1723
+
}
1724
+
},
1725
+
"node_modules/@typescript-eslint/types": {
1726
+
"version": "8.48.1",
1727
+
"dev": true,
1728
+
"license": "MIT",
1729
+
"engines": {
1730
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1731
+
},
1732
+
"funding": {
1733
+
"type": "opencollective",
1734
+
"url": "https://opencollective.com/typescript-eslint"
1735
+
}
1736
+
},
1737
+
"node_modules/@typescript-eslint/typescript-estree": {
1738
+
"version": "8.48.1",
1739
+
"dev": true,
1740
+
"license": "MIT",
1741
+
"dependencies": {
1742
+
"@typescript-eslint/project-service": "8.48.1",
1743
+
"@typescript-eslint/tsconfig-utils": "8.48.1",
1744
+
"@typescript-eslint/types": "8.48.1",
1745
+
"@typescript-eslint/visitor-keys": "8.48.1",
1746
+
"debug": "^4.3.4",
1747
+
"minimatch": "^9.0.4",
1748
+
"semver": "^7.6.0",
1749
+
"tinyglobby": "^0.2.15",
1750
+
"ts-api-utils": "^2.1.0"
1751
+
},
1752
+
"engines": {
1753
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1754
+
},
1755
+
"funding": {
1756
+
"type": "opencollective",
1757
+
"url": "https://opencollective.com/typescript-eslint"
1758
+
},
1759
+
"peerDependencies": {
1760
+
"typescript": ">=4.8.4 <6.0.0"
1761
+
}
1762
+
},
1763
+
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
1764
+
"version": "9.0.5",
1765
+
"dev": true,
1766
+
"license": "ISC",
1767
+
"dependencies": {
1768
+
"brace-expansion": "^2.0.1"
1769
+
},
1770
+
"engines": {
1771
+
"node": ">=16 || 14 >=14.17"
1772
+
},
1773
+
"funding": {
1774
+
"url": "https://github.com/sponsors/isaacs"
1775
+
}
1776
+
},
1777
+
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch/node_modules/brace-expansion": {
1778
+
"version": "2.0.2",
1779
+
"dev": true,
1780
+
"license": "MIT",
1781
+
"dependencies": {
1782
+
"balanced-match": "^1.0.0"
1783
+
}
1784
+
},
1785
+
"node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
1786
+
"version": "7.7.3",
1787
+
"dev": true,
1788
+
"license": "ISC",
1789
+
"bin": {
1790
+
"semver": "bin/semver.js"
1791
+
},
1792
+
"engines": {
1793
+
"node": ">=10"
1794
+
}
1795
+
},
1796
+
"node_modules/@typescript-eslint/utils": {
1797
+
"version": "8.48.1",
1798
+
"dev": true,
1799
+
"license": "MIT",
1800
+
"dependencies": {
1801
+
"@eslint-community/eslint-utils": "^4.7.0",
1802
+
"@typescript-eslint/scope-manager": "8.48.1",
1803
+
"@typescript-eslint/types": "8.48.1",
1804
+
"@typescript-eslint/typescript-estree": "8.48.1"
1805
+
},
1806
+
"engines": {
1807
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1808
+
},
1809
+
"funding": {
1810
+
"type": "opencollective",
1811
+
"url": "https://opencollective.com/typescript-eslint"
1812
+
},
1813
+
"peerDependencies": {
1814
+
"eslint": "^8.57.0 || ^9.0.0",
1815
+
"typescript": ">=4.8.4 <6.0.0"
1816
+
}
1817
+
},
1818
+
"node_modules/@typescript-eslint/visitor-keys": {
1819
+
"version": "8.48.1",
1820
+
"dev": true,
1821
+
"license": "MIT",
1822
+
"dependencies": {
1823
+
"@typescript-eslint/types": "8.48.1",
1824
+
"eslint-visitor-keys": "^4.2.1"
1825
+
},
1826
+
"engines": {
1827
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1828
+
},
1829
+
"funding": {
1830
+
"type": "opencollective",
1831
+
"url": "https://opencollective.com/typescript-eslint"
1832
+
}
1833
+
},
1834
+
"node_modules/@vitejs/plugin-react": {
1835
+
"version": "5.1.1",
1836
+
"dev": true,
1837
+
"license": "MIT",
1838
+
"dependencies": {
1839
+
"@babel/core": "^7.28.5",
1840
+
"@babel/plugin-transform-react-jsx-self": "^7.27.1",
1841
+
"@babel/plugin-transform-react-jsx-source": "^7.27.1",
1842
+
"@rolldown/pluginutils": "1.0.0-beta.47",
1843
+
"@types/babel__core": "^7.20.5",
1844
+
"react-refresh": "^0.18.0"
1845
+
},
1846
+
"engines": {
1847
+
"node": "^20.19.0 || >=22.12.0"
1848
+
},
1849
+
"peerDependencies": {
1850
+
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
1851
+
}
1852
+
},
1853
+
"node_modules/@volar/language-core": {
1854
+
"version": "2.4.26",
1855
+
"dev": true,
1856
+
"license": "MIT",
1857
+
"dependencies": {
1858
+
"@volar/source-map": "2.4.26"
1859
+
}
1860
+
},
1861
+
"node_modules/@volar/source-map": {
1862
+
"version": "2.4.26",
1863
+
"dev": true,
1864
+
"license": "MIT"
1865
+
},
1866
+
"node_modules/@volar/typescript": {
1867
+
"version": "2.4.26",
1868
+
"dev": true,
1869
+
"license": "MIT",
1870
+
"dependencies": {
1871
+
"@volar/language-core": "2.4.26",
1872
+
"path-browserify": "^1.0.1",
1873
+
"vscode-uri": "^3.0.8"
1874
+
}
1875
+
},
1876
+
"node_modules/acorn": {
1877
+
"version": "8.15.0",
1878
+
"dev": true,
1879
+
"license": "MIT",
1880
+
"peer": true,
1881
+
"bin": {
1882
+
"acorn": "bin/acorn"
1883
+
},
1884
+
"engines": {
1885
+
"node": ">=0.4.0"
1886
+
}
1887
+
},
1888
+
"node_modules/acorn-jsx": {
1889
+
"version": "5.3.2",
1890
+
"dev": true,
1891
+
"license": "MIT",
1892
+
"peerDependencies": {
1893
+
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
1894
+
}
1895
+
},
1896
+
"node_modules/ajv": {
1897
+
"version": "8.17.1",
1898
+
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
1899
+
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
1900
+
"dev": true,
1901
+
"license": "MIT",
1902
+
"peer": true,
1903
+
"dependencies": {
1904
+
"fast-deep-equal": "^3.1.3",
1905
+
"fast-uri": "^3.0.1",
1906
+
"json-schema-traverse": "^1.0.0",
1907
+
"require-from-string": "^2.0.2"
1908
+
},
1909
+
"funding": {
1910
+
"type": "github",
1911
+
"url": "https://github.com/sponsors/epoberezkin"
1912
+
}
1913
+
},
1914
+
"node_modules/ajv-draft-04": {
1915
+
"version": "1.0.0",
1916
+
"dev": true,
1917
+
"license": "MIT",
1918
+
"peerDependencies": {
1919
+
"ajv": "^8.5.0"
1920
+
},
1921
+
"peerDependenciesMeta": {
1922
+
"ajv": {
1923
+
"optional": true
1924
+
}
1925
+
}
1926
+
},
1927
+
"node_modules/ajv-formats": {
1928
+
"version": "3.0.1",
1929
+
"dev": true,
1930
+
"license": "MIT",
1931
+
"dependencies": {
1932
+
"ajv": "^8.0.0"
1933
+
},
1934
+
"peerDependencies": {
1935
+
"ajv": "^8.0.0"
1936
+
},
1937
+
"peerDependenciesMeta": {
1938
+
"ajv": {
1939
+
"optional": true
1940
+
}
1941
+
}
1942
+
},
1943
+
"node_modules/ansi-styles": {
1944
+
"version": "4.3.0",
1945
+
"dev": true,
1946
+
"license": "MIT",
1947
+
"dependencies": {
1948
+
"color-convert": "^2.0.1"
1949
+
},
1950
+
"engines": {
1951
+
"node": ">=8"
1952
+
},
1953
+
"funding": {
1954
+
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
1955
+
}
1956
+
},
1957
+
"node_modules/ansis": {
1958
+
"version": "4.2.0",
1959
+
"dev": true,
1960
+
"license": "ISC",
1961
+
"engines": {
1962
+
"node": ">=14"
1963
+
}
1964
+
},
1965
+
"node_modules/argparse": {
1966
+
"version": "1.0.10",
1967
+
"dev": true,
1968
+
"license": "MIT",
1969
+
"dependencies": {
1970
+
"sprintf-js": "~1.0.2"
1971
+
}
1972
+
},
1973
+
"node_modules/balanced-match": {
1974
+
"version": "1.0.2",
1975
+
"dev": true,
1976
+
"license": "MIT"
1977
+
},
1978
+
"node_modules/baseline-browser-mapping": {
1979
+
"version": "2.8.32",
1980
+
"dev": true,
1981
+
"license": "Apache-2.0",
1982
+
"bin": {
1983
+
"baseline-browser-mapping": "dist/cli.js"
1984
+
}
1985
+
},
1986
+
"node_modules/brace-expansion": {
1987
+
"version": "1.1.12",
1988
+
"dev": true,
1989
+
"license": "MIT",
1990
+
"dependencies": {
1991
+
"balanced-match": "^1.0.0",
1992
+
"concat-map": "0.0.1"
1993
+
}
1994
+
},
1995
+
"node_modules/browserslist": {
1996
+
"version": "4.28.0",
1997
+
"dev": true,
1998
+
"funding": [
1999
+
{
2000
+
"type": "opencollective",
2001
+
"url": "https://opencollective.com/browserslist"
2002
+
},
2003
+
{
2004
+
"type": "tidelift",
2005
+
"url": "https://tidelift.com/funding/github/npm/browserslist"
2006
+
},
2007
+
{
2008
+
"type": "github",
2009
+
"url": "https://github.com/sponsors/ai"
2010
+
}
2011
+
],
2012
+
"license": "MIT",
2013
+
"peer": true,
2014
+
"dependencies": {
2015
+
"baseline-browser-mapping": "^2.8.25",
2016
+
"caniuse-lite": "^1.0.30001754",
2017
+
"electron-to-chromium": "^1.5.249",
2018
+
"node-releases": "^2.0.27",
2019
+
"update-browserslist-db": "^1.1.4"
2020
+
},
2021
+
"bin": {
2022
+
"browserslist": "cli.js"
2023
+
},
2024
+
"engines": {
2025
+
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
2026
+
}
2027
+
},
2028
+
"node_modules/buffer-from": {
2029
+
"version": "1.1.2",
2030
+
"dev": true,
2031
+
"license": "MIT",
2032
+
"optional": true
2033
+
},
2034
+
"node_modules/callsites": {
2035
+
"version": "3.1.0",
2036
+
"dev": true,
2037
+
"license": "MIT",
2038
+
"engines": {
2039
+
"node": ">=6"
2040
+
}
2041
+
},
2042
+
"node_modules/caniuse-lite": {
2043
+
"version": "1.0.30001759",
2044
+
"dev": true,
2045
+
"funding": [
2046
+
{
2047
+
"type": "opencollective",
2048
+
"url": "https://opencollective.com/browserslist"
2049
+
},
2050
+
{
2051
+
"type": "tidelift",
2052
+
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
2053
+
},
2054
+
{
2055
+
"type": "github",
2056
+
"url": "https://github.com/sponsors/ai"
2057
+
}
2058
+
],
2059
+
"license": "CC-BY-4.0"
2060
+
},
2061
+
"node_modules/chalk": {
2062
+
"version": "4.1.2",
2063
+
"dev": true,
2064
+
"license": "MIT",
2065
+
"dependencies": {
2066
+
"ansi-styles": "^4.1.0",
2067
+
"supports-color": "^7.1.0"
2068
+
},
2069
+
"engines": {
2070
+
"node": ">=10"
2071
+
},
2072
+
"funding": {
2073
+
"url": "https://github.com/chalk/chalk?sponsor=1"
2074
+
}
2075
+
},
2076
+
"node_modules/chalk/node_modules/supports-color": {
2077
+
"version": "7.2.0",
2078
+
"dev": true,
2079
+
"license": "MIT",
2080
+
"dependencies": {
2081
+
"has-flag": "^4.0.0"
2082
+
},
2083
+
"engines": {
2084
+
"node": ">=8"
2085
+
}
2086
+
},
2087
+
"node_modules/color-convert": {
2088
+
"version": "2.0.1",
2089
+
"dev": true,
2090
+
"license": "MIT",
2091
+
"dependencies": {
2092
+
"color-name": "~1.1.4"
2093
+
},
2094
+
"engines": {
2095
+
"node": ">=7.0.0"
2096
+
}
2097
+
},
2098
+
"node_modules/color-name": {
2099
+
"version": "1.1.4",
2100
+
"dev": true,
2101
+
"license": "MIT"
2102
+
},
2103
+
"node_modules/commander": {
2104
+
"version": "2.20.3",
2105
+
"dev": true,
2106
+
"license": "MIT",
2107
+
"optional": true
2108
+
},
2109
+
"node_modules/commondir": {
2110
+
"version": "1.0.1",
2111
+
"dev": true,
2112
+
"license": "MIT"
2113
+
},
2114
+
"node_modules/compare-versions": {
2115
+
"version": "6.1.1",
2116
+
"dev": true,
2117
+
"license": "MIT"
2118
+
},
2119
+
"node_modules/concat-map": {
2120
+
"version": "0.0.1",
2121
+
"dev": true,
2122
+
"license": "MIT"
2123
+
},
2124
+
"node_modules/confbox": {
2125
+
"version": "0.2.2",
2126
+
"dev": true,
2127
+
"license": "MIT"
2128
+
},
2129
+
"node_modules/convert-source-map": {
2130
+
"version": "2.0.0",
2131
+
"dev": true,
2132
+
"license": "MIT"
2133
+
},
2134
+
"node_modules/cross-spawn": {
2135
+
"version": "7.0.6",
2136
+
"dev": true,
2137
+
"license": "MIT",
2138
+
"dependencies": {
2139
+
"path-key": "^3.1.0",
2140
+
"shebang-command": "^2.0.0",
2141
+
"which": "^2.0.1"
2142
+
},
2143
+
"engines": {
2144
+
"node": ">= 8"
2145
+
}
2146
+
},
2147
+
"node_modules/csstype": {
2148
+
"version": "3.2.3",
2149
+
"dev": true,
2150
+
"license": "MIT"
2151
+
},
2152
+
"node_modules/debug": {
2153
+
"version": "4.4.3",
2154
+
"dev": true,
2155
+
"license": "MIT",
2156
+
"dependencies": {
2157
+
"ms": "^2.1.3"
2158
+
},
2159
+
"engines": {
2160
+
"node": ">=6.0"
2161
+
},
2162
+
"peerDependenciesMeta": {
2163
+
"supports-color": {
2164
+
"optional": true
2165
+
}
2166
+
}
2167
+
},
2168
+
"node_modules/deep-is": {
2169
+
"version": "0.1.4",
2170
+
"dev": true,
2171
+
"license": "MIT"
2172
+
},
2173
+
"node_modules/detect-libc": {
2174
+
"version": "2.1.2",
2175
+
"dev": true,
2176
+
"license": "Apache-2.0",
2177
+
"engines": {
2178
+
"node": ">=8"
2179
+
}
2180
+
},
2181
+
"node_modules/diff": {
2182
+
"version": "8.0.2",
2183
+
"dev": true,
2184
+
"license": "BSD-3-Clause",
2185
+
"engines": {
2186
+
"node": ">=0.3.1"
2187
+
}
2188
+
},
2189
+
"node_modules/electron-to-chromium": {
2190
+
"version": "1.5.263",
2191
+
"dev": true,
2192
+
"license": "ISC"
2193
+
},
2194
+
"node_modules/escalade": {
2195
+
"version": "3.2.0",
2196
+
"dev": true,
2197
+
"license": "MIT",
2198
+
"engines": {
2199
+
"node": ">=6"
2200
+
}
2201
+
},
2202
+
"node_modules/escape-string-regexp": {
2203
+
"version": "4.0.0",
2204
+
"dev": true,
2205
+
"license": "MIT",
2206
+
"engines": {
2207
+
"node": ">=10"
2208
+
},
2209
+
"funding": {
2210
+
"url": "https://github.com/sponsors/sindresorhus"
2211
+
}
2212
+
},
2213
+
"node_modules/eslint": {
2214
+
"version": "9.39.1",
2215
+
"dev": true,
2216
+
"license": "MIT",
2217
+
"peer": true,
2218
+
"dependencies": {
2219
+
"@eslint-community/eslint-utils": "^4.8.0",
2220
+
"@eslint-community/regexpp": "^4.12.1",
2221
+
"@eslint/config-array": "^0.21.1",
2222
+
"@eslint/config-helpers": "^0.4.2",
2223
+
"@eslint/core": "^0.17.0",
2224
+
"@eslint/eslintrc": "^3.3.1",
2225
+
"@eslint/js": "9.39.1",
2226
+
"@eslint/plugin-kit": "^0.4.1",
2227
+
"@humanfs/node": "^0.16.6",
2228
+
"@humanwhocodes/module-importer": "^1.0.1",
2229
+
"@humanwhocodes/retry": "^0.4.2",
2230
+
"@types/estree": "^1.0.6",
2231
+
"ajv": "^6.12.4",
2232
+
"chalk": "^4.0.0",
2233
+
"cross-spawn": "^7.0.6",
2234
+
"debug": "^4.3.2",
2235
+
"escape-string-regexp": "^4.0.0",
2236
+
"eslint-scope": "^8.4.0",
2237
+
"eslint-visitor-keys": "^4.2.1",
2238
+
"espree": "^10.4.0",
2239
+
"esquery": "^1.5.0",
2240
+
"esutils": "^2.0.2",
2241
+
"fast-deep-equal": "^3.1.3",
2242
+
"file-entry-cache": "^8.0.0",
2243
+
"find-up": "^5.0.0",
2244
+
"glob-parent": "^6.0.2",
2245
+
"ignore": "^5.2.0",
2246
+
"imurmurhash": "^0.1.4",
2247
+
"is-glob": "^4.0.0",
2248
+
"json-stable-stringify-without-jsonify": "^1.0.1",
2249
+
"lodash.merge": "^4.6.2",
2250
+
"minimatch": "^3.1.2",
2251
+
"natural-compare": "^1.4.0",
2252
+
"optionator": "^0.9.3"
2253
+
},
2254
+
"bin": {
2255
+
"eslint": "bin/eslint.js"
2256
+
},
2257
+
"engines": {
2258
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
2259
+
},
2260
+
"funding": {
2261
+
"url": "https://eslint.org/donate"
2262
+
},
2263
+
"peerDependencies": {
2264
+
"jiti": "*"
2265
+
},
2266
+
"peerDependenciesMeta": {
2267
+
"jiti": {
2268
+
"optional": true
2269
+
}
2270
+
}
2271
+
},
2272
+
"node_modules/eslint-plugin-react-hooks": {
2273
+
"version": "5.2.0",
2274
+
"dev": true,
2275
+
"license": "MIT",
2276
+
"engines": {
2277
+
"node": ">=10"
2278
+
},
2279
+
"peerDependencies": {
2280
+
"eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
2281
+
}
2282
+
},
2283
+
"node_modules/eslint-plugin-react-refresh": {
2284
+
"version": "0.4.24",
2285
+
"dev": true,
2286
+
"license": "MIT",
2287
+
"peerDependencies": {
2288
+
"eslint": ">=8.40"
2289
+
}
2290
+
},
2291
+
"node_modules/eslint-scope": {
2292
+
"version": "8.4.0",
2293
+
"dev": true,
2294
+
"license": "BSD-2-Clause",
2295
+
"dependencies": {
2296
+
"esrecurse": "^4.3.0",
2297
+
"estraverse": "^5.2.0"
2298
+
},
2299
+
"engines": {
2300
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
2301
+
},
2302
+
"funding": {
2303
+
"url": "https://opencollective.com/eslint"
2304
+
}
2305
+
},
2306
+
"node_modules/eslint-visitor-keys": {
2307
+
"version": "4.2.1",
2308
+
"dev": true,
2309
+
"license": "Apache-2.0",
2310
+
"engines": {
2311
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
2312
+
},
2313
+
"funding": {
2314
+
"url": "https://opencollective.com/eslint"
2315
+
}
2316
+
},
2317
+
"node_modules/eslint/node_modules/ajv": {
2318
+
"version": "6.12.6",
2319
+
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
2320
+
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
2321
+
"dev": true,
2322
+
"license": "MIT",
2323
+
"dependencies": {
2324
+
"fast-deep-equal": "^3.1.1",
2325
+
"fast-json-stable-stringify": "^2.0.0",
2326
+
"json-schema-traverse": "^0.4.1",
2327
+
"uri-js": "^4.2.2"
2328
+
},
2329
+
"funding": {
2330
+
"type": "github",
2331
+
"url": "https://github.com/sponsors/epoberezkin"
2332
+
}
2333
+
},
2334
+
"node_modules/eslint/node_modules/json-schema-traverse": {
2335
+
"version": "0.4.1",
2336
+
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
2337
+
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
2338
+
"dev": true,
2339
+
"license": "MIT"
2340
+
},
2341
+
"node_modules/eslint/node_modules/minimatch": {
2342
+
"version": "3.1.2",
2343
+
"dev": true,
2344
+
"license": "ISC",
2345
+
"dependencies": {
2346
+
"brace-expansion": "^1.1.7"
2347
+
},
2348
+
"engines": {
2349
+
"node": "*"
2350
+
}
2351
+
},
2352
+
"node_modules/esm-env": {
2353
+
"version": "1.2.2",
2354
+
"license": "MIT"
2355
+
},
2356
+
"node_modules/espree": {
2357
+
"version": "10.4.0",
2358
+
"dev": true,
2359
+
"license": "BSD-2-Clause",
2360
+
"dependencies": {
2361
+
"acorn": "^8.15.0",
2362
+
"acorn-jsx": "^5.3.2",
2363
+
"eslint-visitor-keys": "^4.2.1"
2364
+
},
2365
+
"engines": {
2366
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
2367
+
},
2368
+
"funding": {
2369
+
"url": "https://opencollective.com/eslint"
2370
+
}
2371
+
},
2372
+
"node_modules/esquery": {
2373
+
"version": "1.6.0",
2374
+
"dev": true,
2375
+
"license": "BSD-3-Clause",
2376
+
"dependencies": {
2377
+
"estraverse": "^5.1.0"
2378
+
},
2379
+
"engines": {
2380
+
"node": ">=0.10"
2381
+
}
2382
+
},
2383
+
"node_modules/esrecurse": {
2384
+
"version": "4.3.0",
2385
+
"dev": true,
2386
+
"license": "BSD-2-Clause",
2387
+
"dependencies": {
2388
+
"estraverse": "^5.2.0"
2389
+
},
2390
+
"engines": {
2391
+
"node": ">=4.0"
2392
+
}
2393
+
},
2394
+
"node_modules/estraverse": {
2395
+
"version": "5.3.0",
2396
+
"dev": true,
2397
+
"license": "BSD-2-Clause",
2398
+
"engines": {
2399
+
"node": ">=4.0"
2400
+
}
2401
+
},
2402
+
"node_modules/estree-walker": {
2403
+
"version": "2.0.2",
2404
+
"dev": true,
2405
+
"license": "MIT"
2406
+
},
2407
+
"node_modules/esutils": {
2408
+
"version": "2.0.3",
2409
+
"dev": true,
2410
+
"license": "BSD-2-Clause",
2411
+
"engines": {
2412
+
"node": ">=0.10.0"
2413
+
}
2414
+
},
2415
+
"node_modules/exsolve": {
2416
+
"version": "1.0.8",
2417
+
"dev": true,
2418
+
"license": "MIT"
2419
+
},
2420
+
"node_modules/fast-deep-equal": {
2421
+
"version": "3.1.3",
2422
+
"dev": true,
2423
+
"license": "MIT"
2424
+
},
2425
+
"node_modules/fast-json-stable-stringify": {
2426
+
"version": "2.1.0",
2427
+
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
2428
+
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
2429
+
"dev": true,
2430
+
"license": "MIT"
2431
+
},
2432
+
"node_modules/fast-levenshtein": {
2433
+
"version": "2.0.6",
2434
+
"dev": true,
2435
+
"license": "MIT"
2436
+
},
2437
+
"node_modules/fast-uri": {
2438
+
"version": "3.1.0",
2439
+
"dev": true,
2440
+
"funding": [
2441
+
{
2442
+
"type": "github",
2443
+
"url": "https://github.com/sponsors/fastify"
2444
+
},
2445
+
{
2446
+
"type": "opencollective",
2447
+
"url": "https://opencollective.com/fastify"
2448
+
}
2449
+
],
2450
+
"license": "BSD-3-Clause"
2451
+
},
2452
+
"node_modules/fdir": {
2453
+
"version": "6.5.0",
2454
+
"dev": true,
2455
+
"license": "MIT",
2456
+
"engines": {
2457
+
"node": ">=12.0.0"
2458
+
},
2459
+
"peerDependencies": {
2460
+
"picomatch": "^3 || ^4"
2461
+
},
2462
+
"peerDependenciesMeta": {
2463
+
"picomatch": {
2464
+
"optional": true
2465
+
}
2466
+
}
2467
+
},
2468
+
"node_modules/file-entry-cache": {
2469
+
"version": "8.0.0",
2470
+
"dev": true,
2471
+
"license": "MIT",
2472
+
"dependencies": {
2473
+
"flat-cache": "^4.0.0"
2474
+
},
2475
+
"engines": {
2476
+
"node": ">=16.0.0"
2477
+
}
2478
+
},
2479
+
"node_modules/find-cache-dir": {
2480
+
"version": "3.3.2",
2481
+
"dev": true,
2482
+
"license": "MIT",
2483
+
"dependencies": {
2484
+
"commondir": "^1.0.1",
2485
+
"make-dir": "^3.0.2",
2486
+
"pkg-dir": "^4.1.0"
2487
+
},
2488
+
"engines": {
2489
+
"node": ">=8"
2490
+
},
2491
+
"funding": {
2492
+
"url": "https://github.com/avajs/find-cache-dir?sponsor=1"
2493
+
}
2494
+
},
2495
+
"node_modules/find-up": {
2496
+
"version": "5.0.0",
2497
+
"dev": true,
2498
+
"license": "MIT",
2499
+
"dependencies": {
2500
+
"locate-path": "^6.0.0",
2501
+
"path-exists": "^4.0.0"
2502
+
},
2503
+
"engines": {
2504
+
"node": ">=10"
2505
+
},
2506
+
"funding": {
2507
+
"url": "https://github.com/sponsors/sindresorhus"
2508
+
}
2509
+
},
2510
+
"node_modules/flat-cache": {
2511
+
"version": "4.0.1",
2512
+
"dev": true,
2513
+
"license": "MIT",
2514
+
"dependencies": {
2515
+
"flatted": "^3.2.9",
2516
+
"keyv": "^4.5.4"
2517
+
},
2518
+
"engines": {
2519
+
"node": ">=16"
2520
+
}
2521
+
},
2522
+
"node_modules/flatted": {
2523
+
"version": "3.3.3",
2524
+
"dev": true,
2525
+
"license": "ISC"
2526
+
},
2527
+
"node_modules/fs-extra": {
2528
+
"version": "10.1.0",
2529
+
"dev": true,
2530
+
"license": "MIT",
2531
+
"dependencies": {
2532
+
"graceful-fs": "^4.2.0",
2533
+
"jsonfile": "^6.0.1",
2534
+
"universalify": "^2.0.0"
2535
+
},
2536
+
"engines": {
2537
+
"node": ">=12"
2538
+
}
2539
+
},
2540
+
"node_modules/fsevents": {
2541
+
"version": "2.3.3",
2542
+
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
2543
+
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
2544
+
"dev": true,
2545
+
"hasInstallScript": true,
2546
+
"license": "MIT",
2547
+
"optional": true,
2548
+
"os": [
2549
+
"darwin"
2550
+
],
2551
+
"engines": {
2552
+
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
2553
+
}
2554
+
},
2555
+
"node_modules/function-bind": {
2556
+
"version": "1.1.2",
2557
+
"dev": true,
2558
+
"license": "MIT",
2559
+
"funding": {
2560
+
"url": "https://github.com/sponsors/ljharb"
2561
+
}
2562
+
},
2563
+
"node_modules/gensync": {
2564
+
"version": "1.0.0-beta.2",
2565
+
"dev": true,
2566
+
"license": "MIT",
2567
+
"engines": {
2568
+
"node": ">=6.9.0"
2569
+
}
2570
+
},
2571
+
"node_modules/glob-parent": {
2572
+
"version": "6.0.2",
2573
+
"dev": true,
2574
+
"license": "ISC",
2575
+
"dependencies": {
2576
+
"is-glob": "^4.0.3"
2577
+
},
2578
+
"engines": {
2579
+
"node": ">=10.13.0"
2580
+
}
2581
+
},
2582
+
"node_modules/globals": {
2583
+
"version": "16.5.0",
2584
+
"dev": true,
2585
+
"license": "MIT",
2586
+
"engines": {
2587
+
"node": ">=18"
2588
+
},
2589
+
"funding": {
2590
+
"url": "https://github.com/sponsors/sindresorhus"
2591
+
}
2592
+
},
2593
+
"node_modules/graceful-fs": {
2594
+
"version": "4.2.11",
2595
+
"dev": true,
2596
+
"license": "ISC"
2597
+
},
2598
+
"node_modules/graphemer": {
2599
+
"version": "1.4.0",
2600
+
"dev": true,
2601
+
"license": "MIT"
2602
+
},
2603
+
"node_modules/has-flag": {
2604
+
"version": "4.0.0",
2605
+
"dev": true,
2606
+
"license": "MIT",
2607
+
"engines": {
2608
+
"node": ">=8"
2609
+
}
2610
+
},
2611
+
"node_modules/hasown": {
2612
+
"version": "2.0.2",
2613
+
"dev": true,
2614
+
"license": "MIT",
2615
+
"dependencies": {
2616
+
"function-bind": "^1.1.2"
2617
+
},
2618
+
"engines": {
2619
+
"node": ">= 0.4"
2620
+
}
2621
+
},
2622
+
"node_modules/ignore": {
2623
+
"version": "5.3.2",
2624
+
"dev": true,
2625
+
"license": "MIT",
2626
+
"engines": {
2627
+
"node": ">= 4"
2628
+
}
2629
+
},
2630
+
"node_modules/import-fresh": {
2631
+
"version": "3.3.1",
2632
+
"dev": true,
2633
+
"license": "MIT",
2634
+
"dependencies": {
2635
+
"parent-module": "^1.0.0",
2636
+
"resolve-from": "^4.0.0"
2637
+
},
2638
+
"engines": {
2639
+
"node": ">=6"
2640
+
},
2641
+
"funding": {
2642
+
"url": "https://github.com/sponsors/sindresorhus"
2643
+
}
2644
+
},
2645
+
"node_modules/import-lazy": {
2646
+
"version": "4.0.0",
2647
+
"dev": true,
2648
+
"license": "MIT",
2649
+
"engines": {
2650
+
"node": ">=8"
2651
+
}
2652
+
},
2653
+
"node_modules/imurmurhash": {
2654
+
"version": "0.1.4",
2655
+
"dev": true,
2656
+
"license": "MIT",
2657
+
"engines": {
2658
+
"node": ">=0.8.19"
2659
+
}
2660
+
},
2661
+
"node_modules/is-core-module": {
2662
+
"version": "2.16.1",
2663
+
"dev": true,
2664
+
"license": "MIT",
2665
+
"dependencies": {
2666
+
"hasown": "^2.0.2"
2667
+
},
2668
+
"engines": {
2669
+
"node": ">= 0.4"
2670
+
},
2671
+
"funding": {
2672
+
"url": "https://github.com/sponsors/ljharb"
2673
+
}
2674
+
},
2675
+
"node_modules/is-extglob": {
2676
+
"version": "2.1.1",
2677
+
"dev": true,
2678
+
"license": "MIT",
2679
+
"engines": {
2680
+
"node": ">=0.10.0"
2681
+
}
2682
+
},
2683
+
"node_modules/is-glob": {
2684
+
"version": "4.0.3",
2685
+
"dev": true,
2686
+
"license": "MIT",
2687
+
"dependencies": {
2688
+
"is-extglob": "^2.1.1"
2689
+
},
2690
+
"engines": {
2691
+
"node": ">=0.10.0"
2692
+
}
2693
+
},
2694
+
"node_modules/isexe": {
2695
+
"version": "2.0.0",
2696
+
"dev": true,
2697
+
"license": "ISC"
2698
+
},
2699
+
"node_modules/jju": {
2700
+
"version": "1.4.0",
2701
+
"dev": true,
2702
+
"license": "MIT"
2703
+
},
2704
+
"node_modules/js-tokens": {
2705
+
"version": "4.0.0",
2706
+
"dev": true,
2707
+
"license": "MIT"
2708
+
},
2709
+
"node_modules/js-yaml": {
2710
+
"version": "4.1.1",
2711
+
"dev": true,
2712
+
"license": "MIT",
2713
+
"dependencies": {
2714
+
"argparse": "^2.0.1"
2715
+
},
2716
+
"bin": {
2717
+
"js-yaml": "bin/js-yaml.js"
2718
+
}
2719
+
},
2720
+
"node_modules/js-yaml/node_modules/argparse": {
2721
+
"version": "2.0.1",
2722
+
"dev": true,
2723
+
"license": "Python-2.0"
2724
+
},
2725
+
"node_modules/jsesc": {
2726
+
"version": "3.1.0",
2727
+
"dev": true,
2728
+
"license": "MIT",
2729
+
"bin": {
2730
+
"jsesc": "bin/jsesc"
2731
+
},
2732
+
"engines": {
2733
+
"node": ">=6"
2734
+
}
2735
+
},
2736
+
"node_modules/json-buffer": {
2737
+
"version": "3.0.1",
2738
+
"dev": true,
2739
+
"license": "MIT"
2740
+
},
2741
+
"node_modules/json-schema-traverse": {
2742
+
"version": "1.0.0",
2743
+
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
2744
+
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
2745
+
"dev": true,
2746
+
"license": "MIT"
2747
+
},
2748
+
"node_modules/json-stable-stringify-without-jsonify": {
2749
+
"version": "1.0.1",
2750
+
"dev": true,
2751
+
"license": "MIT"
2752
+
},
2753
+
"node_modules/json5": {
2754
+
"version": "2.2.3",
2755
+
"dev": true,
2756
+
"license": "MIT",
2757
+
"bin": {
2758
+
"json5": "lib/cli.js"
2759
+
},
2760
+
"engines": {
2761
+
"node": ">=6"
2762
+
}
2763
+
},
2764
+
"node_modules/jsonfile": {
2765
+
"version": "6.2.0",
2766
+
"dev": true,
2767
+
"license": "MIT",
2768
+
"dependencies": {
2769
+
"universalify": "^2.0.0"
2770
+
},
2771
+
"optionalDependencies": {
2772
+
"graceful-fs": "^4.1.6"
2773
+
}
2774
+
},
2775
+
"node_modules/keyv": {
2776
+
"version": "4.5.4",
2777
+
"dev": true,
2778
+
"license": "MIT",
2779
+
"dependencies": {
2780
+
"json-buffer": "3.0.1"
2781
+
}
2782
+
},
2783
+
"node_modules/kolorist": {
2784
+
"version": "1.8.0",
2785
+
"dev": true,
2786
+
"license": "MIT"
2787
+
},
2788
+
"node_modules/levn": {
2789
+
"version": "0.4.1",
2790
+
"dev": true,
2791
+
"license": "MIT",
2792
+
"dependencies": {
2793
+
"prelude-ls": "^1.2.1",
2794
+
"type-check": "~0.4.0"
2795
+
},
2796
+
"engines": {
2797
+
"node": ">= 0.8.0"
2798
+
}
2799
+
},
2800
+
"node_modules/lightningcss": {
2801
+
"version": "1.30.2",
2802
+
"dev": true,
2803
+
"license": "MPL-2.0",
2804
+
"dependencies": {
2805
+
"detect-libc": "^2.0.3"
2806
+
},
2807
+
"engines": {
2808
+
"node": ">= 12.0.0"
2809
+
},
2810
+
"funding": {
2811
+
"type": "opencollective",
2812
+
"url": "https://opencollective.com/parcel"
2813
+
},
2814
+
"optionalDependencies": {
2815
+
"lightningcss-android-arm64": "1.30.2",
2816
+
"lightningcss-darwin-arm64": "1.30.2",
2817
+
"lightningcss-darwin-x64": "1.30.2",
2818
+
"lightningcss-freebsd-x64": "1.30.2",
2819
+
"lightningcss-linux-arm-gnueabihf": "1.30.2",
2820
+
"lightningcss-linux-arm64-gnu": "1.30.2",
2821
+
"lightningcss-linux-arm64-musl": "1.30.2",
2822
+
"lightningcss-linux-x64-gnu": "1.30.2",
2823
+
"lightningcss-linux-x64-musl": "1.30.2",
2824
+
"lightningcss-win32-arm64-msvc": "1.30.2",
2825
+
"lightningcss-win32-x64-msvc": "1.30.2"
2826
+
}
2827
+
},
2828
+
"node_modules/lightningcss-android-arm64": {
2829
+
"version": "1.30.2",
2830
+
"resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz",
2831
+
"integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==",
2832
+
"cpu": [
2833
+
"arm64"
2834
+
],
2835
+
"dev": true,
2836
+
"license": "MPL-2.0",
2837
+
"optional": true,
2838
+
"os": [
2839
+
"android"
2840
+
],
2841
+
"engines": {
2842
+
"node": ">= 12.0.0"
2843
+
},
2844
+
"funding": {
2845
+
"type": "opencollective",
2846
+
"url": "https://opencollective.com/parcel"
2847
+
}
2848
+
},
2849
+
"node_modules/lightningcss-darwin-arm64": {
2850
+
"version": "1.30.2",
2851
+
"resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz",
2852
+
"integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==",
2853
+
"cpu": [
2854
+
"arm64"
2855
+
],
2856
+
"dev": true,
2857
+
"license": "MPL-2.0",
2858
+
"optional": true,
2859
+
"os": [
2860
+
"darwin"
2861
+
],
2862
+
"engines": {
2863
+
"node": ">= 12.0.0"
2864
+
},
2865
+
"funding": {
2866
+
"type": "opencollective",
2867
+
"url": "https://opencollective.com/parcel"
2868
+
}
2869
+
},
2870
+
"node_modules/lightningcss-darwin-x64": {
2871
+
"version": "1.30.2",
2872
+
"resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz",
2873
+
"integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==",
2874
+
"cpu": [
2875
+
"x64"
2876
+
],
2877
+
"dev": true,
2878
+
"license": "MPL-2.0",
2879
+
"optional": true,
2880
+
"os": [
2881
+
"darwin"
2882
+
],
2883
+
"engines": {
2884
+
"node": ">= 12.0.0"
2885
+
},
2886
+
"funding": {
2887
+
"type": "opencollective",
2888
+
"url": "https://opencollective.com/parcel"
2889
+
}
2890
+
},
2891
+
"node_modules/lightningcss-freebsd-x64": {
2892
+
"version": "1.30.2",
2893
+
"resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz",
2894
+
"integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==",
2895
+
"cpu": [
2896
+
"x64"
2897
+
],
2898
+
"dev": true,
2899
+
"license": "MPL-2.0",
2900
+
"optional": true,
2901
+
"os": [
2902
+
"freebsd"
2903
+
],
2904
+
"engines": {
2905
+
"node": ">= 12.0.0"
2906
+
},
2907
+
"funding": {
2908
+
"type": "opencollective",
2909
+
"url": "https://opencollective.com/parcel"
2910
+
}
2911
+
},
2912
+
"node_modules/lightningcss-linux-arm-gnueabihf": {
2913
+
"version": "1.30.2",
2914
+
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz",
2915
+
"integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==",
2916
+
"cpu": [
2917
+
"arm"
2918
+
],
2919
+
"dev": true,
2920
+
"license": "MPL-2.0",
2921
+
"optional": true,
2922
+
"os": [
2923
+
"linux"
2924
+
],
2925
+
"engines": {
2926
+
"node": ">= 12.0.0"
2927
+
},
2928
+
"funding": {
2929
+
"type": "opencollective",
2930
+
"url": "https://opencollective.com/parcel"
2931
+
}
2932
+
},
2933
+
"node_modules/lightningcss-linux-arm64-gnu": {
2934
+
"version": "1.30.2",
2935
+
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz",
2936
+
"integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==",
2937
+
"cpu": [
2938
+
"arm64"
2939
+
],
2940
+
"dev": true,
2941
+
"license": "MPL-2.0",
2942
+
"optional": true,
2943
+
"os": [
2944
+
"linux"
2945
+
],
2946
+
"engines": {
2947
+
"node": ">= 12.0.0"
2948
+
},
2949
+
"funding": {
2950
+
"type": "opencollective",
2951
+
"url": "https://opencollective.com/parcel"
2952
+
}
2953
+
},
2954
+
"node_modules/lightningcss-linux-arm64-musl": {
2955
+
"version": "1.30.2",
2956
+
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz",
2957
+
"integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==",
2958
+
"cpu": [
2959
+
"arm64"
2960
+
],
2961
+
"dev": true,
2962
+
"license": "MPL-2.0",
2963
+
"optional": true,
2964
+
"os": [
2965
+
"linux"
2966
+
],
2967
+
"engines": {
2968
+
"node": ">= 12.0.0"
2969
+
},
2970
+
"funding": {
2971
+
"type": "opencollective",
2972
+
"url": "https://opencollective.com/parcel"
2973
+
}
2974
+
},
2975
+
"node_modules/lightningcss-linux-x64-gnu": {
2976
+
"version": "1.30.2",
2977
+
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz",
2978
+
"integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==",
2979
+
"cpu": [
2980
+
"x64"
2981
+
],
2982
+
"dev": true,
2983
+
"license": "MPL-2.0",
2984
+
"optional": true,
2985
+
"os": [
2986
+
"linux"
2987
+
],
2988
+
"engines": {
2989
+
"node": ">= 12.0.0"
2990
+
},
2991
+
"funding": {
2992
+
"type": "opencollective",
2993
+
"url": "https://opencollective.com/parcel"
2994
+
}
2995
+
},
2996
+
"node_modules/lightningcss-linux-x64-musl": {
2997
+
"version": "1.30.2",
2998
+
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz",
2999
+
"integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==",
3000
+
"cpu": [
3001
+
"x64"
3002
+
],
3003
+
"dev": true,
3004
+
"license": "MPL-2.0",
3005
+
"optional": true,
3006
+
"os": [
3007
+
"linux"
3008
+
],
3009
+
"engines": {
3010
+
"node": ">= 12.0.0"
3011
+
},
3012
+
"funding": {
3013
+
"type": "opencollective",
3014
+
"url": "https://opencollective.com/parcel"
3015
+
}
3016
+
},
3017
+
"node_modules/lightningcss-win32-arm64-msvc": {
3018
+
"version": "1.30.2",
3019
+
"resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz",
3020
+
"integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==",
3021
+
"cpu": [
3022
+
"arm64"
3023
+
],
3024
+
"dev": true,
3025
+
"license": "MPL-2.0",
3026
+
"optional": true,
3027
+
"os": [
3028
+
"win32"
3029
+
],
3030
+
"engines": {
3031
+
"node": ">= 12.0.0"
3032
+
},
3033
+
"funding": {
3034
+
"type": "opencollective",
3035
+
"url": "https://opencollective.com/parcel"
3036
+
}
3037
+
},
3038
+
"node_modules/lightningcss-win32-x64-msvc": {
3039
+
"version": "1.30.2",
3040
+
"cpu": [
3041
+
"x64"
3042
+
],
3043
+
"dev": true,
3044
+
"license": "MPL-2.0",
3045
+
"optional": true,
3046
+
"os": [
3047
+
"win32"
3048
+
],
3049
+
"engines": {
3050
+
"node": ">= 12.0.0"
3051
+
},
3052
+
"funding": {
3053
+
"type": "opencollective",
3054
+
"url": "https://opencollective.com/parcel"
3055
+
}
3056
+
},
3057
+
"node_modules/local-pkg": {
3058
+
"version": "1.1.2",
3059
+
"dev": true,
3060
+
"license": "MIT",
3061
+
"dependencies": {
3062
+
"mlly": "^1.7.4",
3063
+
"pkg-types": "^2.3.0",
3064
+
"quansync": "^0.2.11"
3065
+
},
3066
+
"engines": {
3067
+
"node": ">=14"
3068
+
},
3069
+
"funding": {
3070
+
"url": "https://github.com/sponsors/antfu"
3071
+
}
3072
+
},
3073
+
"node_modules/locate-path": {
3074
+
"version": "6.0.0",
3075
+
"dev": true,
3076
+
"license": "MIT",
3077
+
"dependencies": {
3078
+
"p-locate": "^5.0.0"
3079
+
},
3080
+
"engines": {
3081
+
"node": ">=10"
3082
+
},
3083
+
"funding": {
3084
+
"url": "https://github.com/sponsors/sindresorhus"
3085
+
}
3086
+
},
3087
+
"node_modules/lodash": {
3088
+
"version": "4.17.21",
3089
+
"dev": true,
3090
+
"license": "MIT"
3091
+
},
3092
+
"node_modules/lodash.merge": {
3093
+
"version": "4.6.2",
3094
+
"dev": true,
3095
+
"license": "MIT"
3096
+
},
3097
+
"node_modules/lru-cache": {
3098
+
"version": "6.0.0",
3099
+
"dev": true,
3100
+
"license": "ISC",
3101
+
"dependencies": {
3102
+
"yallist": "^4.0.0"
3103
+
},
3104
+
"engines": {
3105
+
"node": ">=10"
3106
+
}
3107
+
},
3108
+
"node_modules/magic-string": {
3109
+
"version": "0.30.21",
3110
+
"dev": true,
3111
+
"license": "MIT",
3112
+
"dependencies": {
3113
+
"@jridgewell/sourcemap-codec": "^1.5.5"
3114
+
}
3115
+
},
3116
+
"node_modules/make-dir": {
3117
+
"version": "3.1.0",
3118
+
"dev": true,
3119
+
"license": "MIT",
3120
+
"dependencies": {
3121
+
"semver": "^6.0.0"
3122
+
},
3123
+
"engines": {
3124
+
"node": ">=8"
3125
+
},
3126
+
"funding": {
3127
+
"url": "https://github.com/sponsors/sindresorhus"
3128
+
}
3129
+
},
3130
+
"node_modules/make-dir/node_modules/semver": {
3131
+
"version": "6.3.1",
3132
+
"dev": true,
3133
+
"license": "ISC",
3134
+
"bin": {
3135
+
"semver": "bin/semver.js"
3136
+
}
3137
+
},
3138
+
"node_modules/minimatch": {
3139
+
"version": "10.0.3",
3140
+
"dev": true,
3141
+
"license": "ISC",
3142
+
"dependencies": {
3143
+
"@isaacs/brace-expansion": "^5.0.0"
3144
+
},
3145
+
"engines": {
3146
+
"node": "20 || >=22"
3147
+
},
3148
+
"funding": {
3149
+
"url": "https://github.com/sponsors/isaacs"
3150
+
}
3151
+
},
3152
+
"node_modules/mlly": {
3153
+
"version": "1.8.0",
3154
+
"dev": true,
3155
+
"license": "MIT",
3156
+
"dependencies": {
3157
+
"acorn": "^8.15.0",
3158
+
"pathe": "^2.0.3",
3159
+
"pkg-types": "^1.3.1",
3160
+
"ufo": "^1.6.1"
3161
+
}
3162
+
},
3163
+
"node_modules/mlly/node_modules/pkg-types": {
3164
+
"version": "1.3.1",
3165
+
"dev": true,
3166
+
"license": "MIT",
3167
+
"dependencies": {
3168
+
"confbox": "^0.1.8",
3169
+
"mlly": "^1.7.4",
3170
+
"pathe": "^2.0.1"
3171
+
}
3172
+
},
3173
+
"node_modules/mlly/node_modules/pkg-types/node_modules/confbox": {
3174
+
"version": "0.1.8",
3175
+
"dev": true,
3176
+
"license": "MIT"
3177
+
},
3178
+
"node_modules/ms": {
3179
+
"version": "2.1.3",
3180
+
"dev": true,
3181
+
"license": "MIT"
3182
+
},
3183
+
"node_modules/nanoid": {
3184
+
"version": "3.3.11",
3185
+
"dev": true,
3186
+
"funding": [
3187
+
{
3188
+
"type": "github",
3189
+
"url": "https://github.com/sponsors/ai"
3190
+
}
3191
+
],
3192
+
"license": "MIT",
3193
+
"bin": {
3194
+
"nanoid": "bin/nanoid.cjs"
3195
+
},
3196
+
"engines": {
3197
+
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
3198
+
}
3199
+
},
3200
+
"node_modules/natural-compare": {
3201
+
"version": "1.4.0",
3202
+
"dev": true,
3203
+
"license": "MIT"
3204
+
},
3205
+
"node_modules/node-releases": {
3206
+
"version": "2.0.27",
3207
+
"dev": true,
3208
+
"license": "MIT"
3209
+
},
3210
+
"node_modules/optionator": {
3211
+
"version": "0.9.4",
3212
+
"dev": true,
3213
+
"license": "MIT",
3214
+
"dependencies": {
3215
+
"deep-is": "^0.1.3",
3216
+
"fast-levenshtein": "^2.0.6",
3217
+
"levn": "^0.4.1",
3218
+
"prelude-ls": "^1.2.1",
3219
+
"type-check": "^0.4.0",
3220
+
"word-wrap": "^1.2.5"
3221
+
},
3222
+
"engines": {
3223
+
"node": ">= 0.8.0"
3224
+
}
3225
+
},
3226
+
"node_modules/p-limit": {
3227
+
"version": "3.1.0",
3228
+
"dev": true,
3229
+
"license": "MIT",
3230
+
"dependencies": {
3231
+
"yocto-queue": "^0.1.0"
3232
+
},
3233
+
"engines": {
3234
+
"node": ">=10"
3235
+
},
3236
+
"funding": {
3237
+
"url": "https://github.com/sponsors/sindresorhus"
3238
+
}
3239
+
},
3240
+
"node_modules/p-locate": {
3241
+
"version": "5.0.0",
3242
+
"dev": true,
3243
+
"license": "MIT",
3244
+
"dependencies": {
3245
+
"p-limit": "^3.0.2"
3246
+
},
3247
+
"engines": {
3248
+
"node": ">=10"
3249
+
},
3250
+
"funding": {
3251
+
"url": "https://github.com/sponsors/sindresorhus"
3252
+
}
3253
+
},
3254
+
"node_modules/p-try": {
3255
+
"version": "2.2.0",
3256
+
"dev": true,
3257
+
"license": "MIT",
3258
+
"engines": {
3259
+
"node": ">=6"
3260
+
}
3261
+
},
3262
+
"node_modules/parent-module": {
3263
+
"version": "1.0.1",
3264
+
"dev": true,
3265
+
"license": "MIT",
3266
+
"dependencies": {
3267
+
"callsites": "^3.0.0"
3268
+
},
3269
+
"engines": {
3270
+
"node": ">=6"
3271
+
}
3272
+
},
3273
+
"node_modules/path-browserify": {
3274
+
"version": "1.0.1",
3275
+
"dev": true,
3276
+
"license": "MIT"
3277
+
},
3278
+
"node_modules/path-exists": {
3279
+
"version": "4.0.0",
3280
+
"dev": true,
3281
+
"license": "MIT",
3282
+
"engines": {
3283
+
"node": ">=8"
3284
+
}
3285
+
},
3286
+
"node_modules/path-key": {
3287
+
"version": "3.1.1",
3288
+
"dev": true,
3289
+
"license": "MIT",
3290
+
"engines": {
3291
+
"node": ">=8"
3292
+
}
3293
+
},
3294
+
"node_modules/path-parse": {
3295
+
"version": "1.0.7",
3296
+
"dev": true,
3297
+
"license": "MIT"
3298
+
},
3299
+
"node_modules/pathe": {
3300
+
"version": "2.0.3",
3301
+
"dev": true,
3302
+
"license": "MIT"
3303
+
},
3304
+
"node_modules/picocolors": {
3305
+
"version": "1.1.1",
3306
+
"dev": true,
3307
+
"license": "ISC"
3308
+
},
3309
+
"node_modules/picomatch": {
3310
+
"version": "4.0.3",
3311
+
"dev": true,
3312
+
"license": "MIT",
3313
+
"engines": {
3314
+
"node": ">=12"
3315
+
},
3316
+
"funding": {
3317
+
"url": "https://github.com/sponsors/jonschlinkert"
3318
+
}
3319
+
},
3320
+
"node_modules/pkg-dir": {
3321
+
"version": "4.2.0",
3322
+
"dev": true,
3323
+
"license": "MIT",
3324
+
"dependencies": {
3325
+
"find-up": "^4.0.0"
3326
+
},
3327
+
"engines": {
3328
+
"node": ">=8"
3329
+
}
3330
+
},
3331
+
"node_modules/pkg-dir/node_modules/find-up": {
3332
+
"version": "4.1.0",
3333
+
"dev": true,
3334
+
"license": "MIT",
3335
+
"dependencies": {
3336
+
"locate-path": "^5.0.0",
3337
+
"path-exists": "^4.0.0"
3338
+
},
3339
+
"engines": {
3340
+
"node": ">=8"
3341
+
}
3342
+
},
3343
+
"node_modules/pkg-dir/node_modules/find-up/node_modules/locate-path": {
3344
+
"version": "5.0.0",
3345
+
"dev": true,
3346
+
"license": "MIT",
3347
+
"dependencies": {
3348
+
"p-locate": "^4.1.0"
3349
+
},
3350
+
"engines": {
3351
+
"node": ">=8"
3352
+
}
3353
+
},
3354
+
"node_modules/pkg-dir/node_modules/find-up/node_modules/locate-path/node_modules/p-locate": {
3355
+
"version": "4.1.0",
3356
+
"dev": true,
3357
+
"license": "MIT",
3358
+
"dependencies": {
3359
+
"p-limit": "^2.2.0"
3360
+
},
3361
+
"engines": {
3362
+
"node": ">=8"
3363
+
}
3364
+
},
3365
+
"node_modules/pkg-dir/node_modules/find-up/node_modules/locate-path/node_modules/p-locate/node_modules/p-limit": {
3366
+
"version": "2.3.0",
3367
+
"dev": true,
3368
+
"license": "MIT",
3369
+
"dependencies": {
3370
+
"p-try": "^2.0.0"
3371
+
},
3372
+
"engines": {
3373
+
"node": ">=6"
3374
+
},
3375
+
"funding": {
3376
+
"url": "https://github.com/sponsors/sindresorhus"
3377
+
}
3378
+
},
3379
+
"node_modules/pkg-types": {
3380
+
"version": "2.3.0",
3381
+
"dev": true,
3382
+
"license": "MIT",
3383
+
"dependencies": {
3384
+
"confbox": "^0.2.2",
3385
+
"exsolve": "^1.0.7",
3386
+
"pathe": "^2.0.3"
3387
+
}
3388
+
},
3389
+
"node_modules/postcss": {
3390
+
"version": "8.5.6",
3391
+
"dev": true,
3392
+
"funding": [
3393
+
{
3394
+
"type": "opencollective",
3395
+
"url": "https://opencollective.com/postcss/"
3396
+
},
3397
+
{
3398
+
"type": "tidelift",
3399
+
"url": "https://tidelift.com/funding/github/npm/postcss"
3400
+
},
3401
+
{
3402
+
"type": "github",
3403
+
"url": "https://github.com/sponsors/ai"
3404
+
}
3405
+
],
3406
+
"license": "MIT",
3407
+
"dependencies": {
3408
+
"nanoid": "^3.3.11",
3409
+
"picocolors": "^1.1.1",
3410
+
"source-map-js": "^1.2.1"
3411
+
},
3412
+
"engines": {
3413
+
"node": "^10 || ^12 || >=14"
3414
+
}
3415
+
},
3416
+
"node_modules/prelude-ls": {
3417
+
"version": "1.2.1",
3418
+
"dev": true,
3419
+
"license": "MIT",
3420
+
"engines": {
3421
+
"node": ">= 0.8.0"
3422
+
}
3423
+
},
3424
+
"node_modules/punycode": {
3425
+
"version": "2.3.1",
3426
+
"dev": true,
3427
+
"license": "MIT",
3428
+
"engines": {
3429
+
"node": ">=6"
3430
+
}
3431
+
},
3432
+
"node_modules/quansync": {
3433
+
"version": "0.2.11",
3434
+
"dev": true,
3435
+
"funding": [
3436
+
{
3437
+
"type": "individual",
3438
+
"url": "https://github.com/sponsors/antfu"
3439
+
},
3440
+
{
3441
+
"type": "individual",
3442
+
"url": "https://github.com/sponsors/sxzz"
3443
+
}
3444
+
],
3445
+
"license": "MIT"
3446
+
},
3447
+
"node_modules/react": {
3448
+
"version": "19.2.0",
3449
+
"dev": true,
3450
+
"license": "MIT",
3451
+
"peer": true,
3452
+
"engines": {
3453
+
"node": ">=0.10.0"
3454
+
}
3455
+
},
3456
+
"node_modules/react-dom": {
3457
+
"version": "19.2.0",
3458
+
"dev": true,
3459
+
"license": "MIT",
3460
+
"dependencies": {
3461
+
"scheduler": "^0.27.0"
3462
+
},
3463
+
"peerDependencies": {
3464
+
"react": "^19.2.0"
3465
+
}
3466
+
},
3467
+
"node_modules/react-refresh": {
3468
+
"version": "0.18.0",
3469
+
"dev": true,
3470
+
"license": "MIT",
3471
+
"engines": {
3472
+
"node": ">=0.10.0"
3473
+
}
3474
+
},
3475
+
"node_modules/require-from-string": {
3476
+
"version": "2.0.2",
3477
+
"dev": true,
3478
+
"license": "MIT",
3479
+
"engines": {
3480
+
"node": ">=0.10.0"
3481
+
}
3482
+
},
3483
+
"node_modules/resolve": {
3484
+
"version": "1.22.11",
3485
+
"dev": true,
3486
+
"license": "MIT",
3487
+
"dependencies": {
3488
+
"is-core-module": "^2.16.1",
3489
+
"path-parse": "^1.0.7",
3490
+
"supports-preserve-symlinks-flag": "^1.0.0"
3491
+
},
3492
+
"bin": {
3493
+
"resolve": "bin/resolve"
3494
+
},
3495
+
"engines": {
3496
+
"node": ">= 0.4"
3497
+
},
3498
+
"funding": {
3499
+
"url": "https://github.com/sponsors/ljharb"
3500
+
}
3501
+
},
3502
+
"node_modules/resolve-from": {
3503
+
"version": "4.0.0",
3504
+
"dev": true,
3505
+
"license": "MIT",
3506
+
"engines": {
3507
+
"node": ">=4"
3508
+
}
3509
+
},
3510
+
"node_modules/rolldown": {
3511
+
"version": "1.0.0-beta.41",
3512
+
"dev": true,
3513
+
"license": "MIT",
3514
+
"peer": true,
3515
+
"dependencies": {
3516
+
"@oxc-project/types": "=0.93.0",
3517
+
"@rolldown/pluginutils": "1.0.0-beta.41",
3518
+
"ansis": "=4.2.0"
3519
+
},
3520
+
"bin": {
3521
+
"rolldown": "bin/cli.mjs"
3522
+
},
3523
+
"engines": {
3524
+
"node": "^20.19.0 || >=22.12.0"
3525
+
},
3526
+
"optionalDependencies": {
3527
+
"@rolldown/binding-android-arm64": "1.0.0-beta.41",
3528
+
"@rolldown/binding-darwin-arm64": "1.0.0-beta.41",
3529
+
"@rolldown/binding-darwin-x64": "1.0.0-beta.41",
3530
+
"@rolldown/binding-freebsd-x64": "1.0.0-beta.41",
3531
+
"@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.41",
3532
+
"@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.41",
3533
+
"@rolldown/binding-linux-arm64-musl": "1.0.0-beta.41",
3534
+
"@rolldown/binding-linux-x64-gnu": "1.0.0-beta.41",
3535
+
"@rolldown/binding-linux-x64-musl": "1.0.0-beta.41",
3536
+
"@rolldown/binding-openharmony-arm64": "1.0.0-beta.41",
3537
+
"@rolldown/binding-wasm32-wasi": "1.0.0-beta.41",
3538
+
"@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.41",
3539
+
"@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.41",
3540
+
"@rolldown/binding-win32-x64-msvc": "1.0.0-beta.41"
3541
+
}
3542
+
},
3543
+
"node_modules/rolldown/node_modules/@rolldown/pluginutils": {
3544
+
"version": "1.0.0-beta.41",
3545
+
"dev": true,
3546
+
"license": "MIT"
3547
+
},
3548
+
"node_modules/rollup": {
3549
+
"version": "4.53.3",
3550
+
"dev": true,
3551
+
"license": "MIT",
3552
+
"peer": true,
3553
+
"dependencies": {
3554
+
"@types/estree": "1.0.8"
3555
+
},
3556
+
"bin": {
3557
+
"rollup": "dist/bin/rollup"
3558
+
},
3559
+
"engines": {
3560
+
"node": ">=18.0.0",
3561
+
"npm": ">=8.0.0"
3562
+
},
3563
+
"optionalDependencies": {
3564
+
"@rollup/rollup-android-arm-eabi": "4.53.3",
3565
+
"@rollup/rollup-android-arm64": "4.53.3",
3566
+
"@rollup/rollup-darwin-arm64": "4.53.3",
3567
+
"@rollup/rollup-darwin-x64": "4.53.3",
3568
+
"@rollup/rollup-freebsd-arm64": "4.53.3",
3569
+
"@rollup/rollup-freebsd-x64": "4.53.3",
3570
+
"@rollup/rollup-linux-arm-gnueabihf": "4.53.3",
3571
+
"@rollup/rollup-linux-arm-musleabihf": "4.53.3",
3572
+
"@rollup/rollup-linux-arm64-gnu": "4.53.3",
3573
+
"@rollup/rollup-linux-arm64-musl": "4.53.3",
3574
+
"@rollup/rollup-linux-loong64-gnu": "4.53.3",
3575
+
"@rollup/rollup-linux-ppc64-gnu": "4.53.3",
3576
+
"@rollup/rollup-linux-riscv64-gnu": "4.53.3",
3577
+
"@rollup/rollup-linux-riscv64-musl": "4.53.3",
3578
+
"@rollup/rollup-linux-s390x-gnu": "4.53.3",
3579
+
"@rollup/rollup-linux-x64-gnu": "4.53.3",
3580
+
"@rollup/rollup-linux-x64-musl": "4.53.3",
3581
+
"@rollup/rollup-openharmony-arm64": "4.53.3",
3582
+
"@rollup/rollup-win32-arm64-msvc": "4.53.3",
3583
+
"@rollup/rollup-win32-ia32-msvc": "4.53.3",
3584
+
"@rollup/rollup-win32-x64-gnu": "4.53.3",
3585
+
"@rollup/rollup-win32-x64-msvc": "4.53.3",
3586
+
"fsevents": "~2.3.2"
3587
+
}
3588
+
},
3589
+
"node_modules/rollup-plugin-typescript2": {
3590
+
"version": "0.36.0",
3591
+
"dev": true,
3592
+
"license": "MIT",
3593
+
"dependencies": {
3594
+
"@rollup/pluginutils": "^4.1.2",
3595
+
"find-cache-dir": "^3.3.2",
3596
+
"fs-extra": "^10.0.0",
3597
+
"semver": "^7.5.4",
3598
+
"tslib": "^2.6.2"
3599
+
},
3600
+
"peerDependencies": {
3601
+
"rollup": ">=1.26.3",
3602
+
"typescript": ">=2.4.0"
3603
+
}
3604
+
},
3605
+
"node_modules/rollup-plugin-typescript2/node_modules/semver": {
3606
+
"version": "7.7.3",
3607
+
"dev": true,
3608
+
"license": "ISC",
3609
+
"bin": {
3610
+
"semver": "bin/semver.js"
3611
+
},
3612
+
"engines": {
3613
+
"node": ">=10"
3614
+
}
3615
+
},
3616
+
"node_modules/scheduler": {
3617
+
"version": "0.27.0",
3618
+
"dev": true,
3619
+
"license": "MIT"
3620
+
},
3621
+
"node_modules/semver": {
3622
+
"version": "7.5.4",
3623
+
"dev": true,
3624
+
"license": "ISC",
3625
+
"dependencies": {
3626
+
"lru-cache": "^6.0.0"
3627
+
},
3628
+
"bin": {
3629
+
"semver": "bin/semver.js"
3630
+
},
3631
+
"engines": {
3632
+
"node": ">=10"
3633
+
}
3634
+
},
3635
+
"node_modules/shebang-command": {
3636
+
"version": "2.0.0",
3637
+
"dev": true,
3638
+
"license": "MIT",
3639
+
"dependencies": {
3640
+
"shebang-regex": "^3.0.0"
3641
+
},
3642
+
"engines": {
3643
+
"node": ">=8"
3644
+
}
3645
+
},
3646
+
"node_modules/shebang-regex": {
3647
+
"version": "3.0.0",
3648
+
"dev": true,
3649
+
"license": "MIT",
3650
+
"engines": {
3651
+
"node": ">=8"
3652
+
}
3653
+
},
3654
+
"node_modules/source-map": {
3655
+
"version": "0.6.1",
3656
+
"dev": true,
3657
+
"license": "BSD-3-Clause",
3658
+
"engines": {
3659
+
"node": ">=0.10.0"
3660
+
}
3661
+
},
3662
+
"node_modules/source-map-js": {
3663
+
"version": "1.2.1",
3664
+
"dev": true,
3665
+
"license": "BSD-3-Clause",
3666
+
"engines": {
3667
+
"node": ">=0.10.0"
3668
+
}
3669
+
},
3670
+
"node_modules/source-map-support": {
3671
+
"version": "0.5.21",
3672
+
"dev": true,
3673
+
"license": "MIT",
3674
+
"optional": true,
3675
+
"dependencies": {
3676
+
"buffer-from": "^1.0.0",
3677
+
"source-map": "^0.6.0"
3678
+
}
3679
+
},
3680
+
"node_modules/sprintf-js": {
3681
+
"version": "1.0.3",
3682
+
"dev": true,
3683
+
"license": "BSD-3-Clause"
3684
+
},
3685
+
"node_modules/string-argv": {
3686
+
"version": "0.3.2",
3687
+
"dev": true,
3688
+
"license": "MIT",
3689
+
"engines": {
3690
+
"node": ">=0.6.19"
3691
+
}
3692
+
},
3693
+
"node_modules/strip-json-comments": {
3694
+
"version": "3.1.1",
3695
+
"dev": true,
3696
+
"license": "MIT",
3697
+
"engines": {
3698
+
"node": ">=8"
3699
+
},
3700
+
"funding": {
3701
+
"url": "https://github.com/sponsors/sindresorhus"
3702
+
}
3703
+
},
3704
+
"node_modules/supports-color": {
3705
+
"version": "8.1.1",
3706
+
"dev": true,
3707
+
"license": "MIT",
3708
+
"dependencies": {
3709
+
"has-flag": "^4.0.0"
3710
+
},
3711
+
"engines": {
3712
+
"node": ">=10"
3713
+
},
3714
+
"funding": {
3715
+
"url": "https://github.com/chalk/supports-color?sponsor=1"
3716
+
}
3717
+
},
3718
+
"node_modules/supports-preserve-symlinks-flag": {
3719
+
"version": "1.0.0",
3720
+
"dev": true,
3721
+
"license": "MIT",
3722
+
"engines": {
3723
+
"node": ">= 0.4"
3724
+
},
3725
+
"funding": {
3726
+
"url": "https://github.com/sponsors/ljharb"
3727
+
}
3728
+
},
3729
+
"node_modules/tinyglobby": {
3730
+
"version": "0.2.15",
3731
+
"dev": true,
3732
+
"license": "MIT",
3733
+
"dependencies": {
3734
+
"fdir": "^6.5.0",
3735
+
"picomatch": "^4.0.3"
3736
+
},
3737
+
"engines": {
3738
+
"node": ">=12.0.0"
3739
+
},
3740
+
"funding": {
3741
+
"url": "https://github.com/sponsors/SuperchupuDev"
3742
+
}
3743
+
},
3744
+
"node_modules/ts-api-utils": {
3745
+
"version": "2.1.0",
3746
+
"dev": true,
3747
+
"license": "MIT",
3748
+
"engines": {
3749
+
"node": ">=18.12"
3750
+
},
3751
+
"peerDependencies": {
3752
+
"typescript": ">=4.8.4"
3753
+
}
3754
+
},
3755
+
"node_modules/tslib": {
3756
+
"version": "2.8.1",
3757
+
"dev": true,
3758
+
"license": "0BSD"
3759
+
},
3760
+
"node_modules/type-check": {
3761
+
"version": "0.4.0",
3762
+
"dev": true,
3763
+
"license": "MIT",
3764
+
"dependencies": {
3765
+
"prelude-ls": "^1.2.1"
3766
+
},
3767
+
"engines": {
3768
+
"node": ">= 0.8.0"
3769
+
}
3770
+
},
3771
+
"node_modules/typescript": {
3772
+
"version": "5.9.3",
3773
+
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
3774
+
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
3775
+
"dev": true,
3776
+
"license": "Apache-2.0",
3777
+
"peer": true,
3778
+
"bin": {
3779
+
"tsc": "bin/tsc",
3780
+
"tsserver": "bin/tsserver"
3781
+
},
3782
+
"engines": {
3783
+
"node": ">=14.17"
3784
+
}
3785
+
},
3786
+
"node_modules/typescript-eslint": {
3787
+
"version": "8.48.1",
3788
+
"dev": true,
3789
+
"license": "MIT",
3790
+
"dependencies": {
3791
+
"@typescript-eslint/eslint-plugin": "8.48.1",
3792
+
"@typescript-eslint/parser": "8.48.1",
3793
+
"@typescript-eslint/typescript-estree": "8.48.1",
3794
+
"@typescript-eslint/utils": "8.48.1"
3795
+
},
3796
+
"engines": {
3797
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
3798
+
},
3799
+
"funding": {
3800
+
"type": "opencollective",
3801
+
"url": "https://opencollective.com/typescript-eslint"
3802
+
},
3803
+
"peerDependencies": {
3804
+
"eslint": "^8.57.0 || ^9.0.0",
3805
+
"typescript": ">=4.8.4 <6.0.0"
3806
+
}
3807
+
},
3808
+
"node_modules/ufo": {
3809
+
"version": "1.6.1",
3810
+
"dev": true,
3811
+
"license": "MIT"
3812
+
},
3813
+
"node_modules/undici-types": {
3814
+
"version": "7.16.0",
3815
+
"dev": true,
3816
+
"license": "MIT"
3817
+
},
3818
+
"node_modules/universalify": {
3819
+
"version": "2.0.1",
3820
+
"dev": true,
3821
+
"license": "MIT",
3822
+
"engines": {
3823
+
"node": ">= 10.0.0"
3824
+
}
3825
+
},
3826
+
"node_modules/unplugin": {
3827
+
"version": "2.3.11",
3828
+
"dev": true,
3829
+
"license": "MIT",
3830
+
"dependencies": {
3831
+
"@jridgewell/remapping": "^2.3.5",
3832
+
"acorn": "^8.15.0",
3833
+
"picomatch": "^4.0.3",
3834
+
"webpack-virtual-modules": "^0.6.2"
3835
+
},
3836
+
"engines": {
3837
+
"node": ">=18.12.0"
3838
+
}
3839
+
},
3840
+
"node_modules/unplugin-dts": {
3841
+
"version": "1.0.0-beta.6",
3842
+
"dev": true,
3843
+
"license": "MIT",
3844
+
"dependencies": {
3845
+
"@rollup/pluginutils": "^5.1.4",
3846
+
"@volar/typescript": "^2.4.17",
3847
+
"compare-versions": "^6.1.1",
3848
+
"debug": "^4.4.0",
3849
+
"kolorist": "^1.8.0",
3850
+
"local-pkg": "^1.1.1",
3851
+
"magic-string": "^0.30.17",
3852
+
"unplugin": "^2.3.2"
3853
+
},
3854
+
"peerDependencies": {
3855
+
"@microsoft/api-extractor": ">=7",
3856
+
"@rspack/core": "^1",
3857
+
"@vue/language-core": "~3.0.1",
3858
+
"esbuild": "*",
3859
+
"rolldown": "*",
3860
+
"rollup": ">=3",
3861
+
"typescript": ">=4",
3862
+
"vite": ">=3",
3863
+
"webpack": "^4 || ^5"
3864
+
},
3865
+
"peerDependenciesMeta": {
3866
+
"@microsoft/api-extractor": {
3867
+
"optional": true
3868
+
},
3869
+
"@rspack/core": {
3870
+
"optional": true
3871
+
},
3872
+
"@vue/language-core": {
3873
+
"optional": true
3874
+
},
3875
+
"esbuild": {
3876
+
"optional": true
3877
+
},
3878
+
"rolldown": {
3879
+
"optional": true
3880
+
},
3881
+
"rollup": {
3882
+
"optional": true
3883
+
},
3884
+
"vite": {
3885
+
"optional": true
3886
+
},
3887
+
"webpack": {
3888
+
"optional": true
3889
+
}
3890
+
}
3891
+
},
3892
+
"node_modules/unplugin-dts/node_modules/@rollup/pluginutils": {
3893
+
"version": "5.3.0",
3894
+
"dev": true,
3895
+
"license": "MIT",
3896
+
"dependencies": {
3897
+
"@types/estree": "^1.0.0",
3898
+
"estree-walker": "^2.0.2",
3899
+
"picomatch": "^4.0.2"
3900
+
},
3901
+
"engines": {
3902
+
"node": ">=14.0.0"
3903
+
},
3904
+
"peerDependencies": {
3905
+
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
3906
+
},
3907
+
"peerDependenciesMeta": {
3908
+
"rollup": {
3909
+
"optional": true
3910
+
}
3911
+
}
3912
+
},
3913
+
"node_modules/update-browserslist-db": {
3914
+
"version": "1.1.4",
3915
+
"dev": true,
3916
+
"funding": [
3917
+
{
3918
+
"type": "opencollective",
3919
+
"url": "https://opencollective.com/browserslist"
3920
+
},
3921
+
{
3922
+
"type": "tidelift",
3923
+
"url": "https://tidelift.com/funding/github/npm/browserslist"
3924
+
},
3925
+
{
3926
+
"type": "github",
3927
+
"url": "https://github.com/sponsors/ai"
3928
+
}
3929
+
],
3930
+
"license": "MIT",
3931
+
"dependencies": {
3932
+
"escalade": "^3.2.0",
3933
+
"picocolors": "^1.1.1"
3934
+
},
3935
+
"bin": {
3936
+
"update-browserslist-db": "cli.js"
3937
+
},
3938
+
"peerDependencies": {
3939
+
"browserslist": ">= 4.21.0"
3940
+
}
3941
+
},
3942
+
"node_modules/uri-js": {
3943
+
"version": "4.4.1",
3944
+
"dev": true,
3945
+
"license": "BSD-2-Clause",
3946
+
"dependencies": {
3947
+
"punycode": "^2.1.0"
3948
+
}
3949
+
},
3950
+
"node_modules/vite": {
3951
+
"name": "rolldown-vite",
3952
+
"version": "7.1.14",
3953
+
"dev": true,
3954
+
"license": "MIT",
3955
+
"peer": true,
3956
+
"dependencies": {
3957
+
"@oxc-project/runtime": "0.92.0",
3958
+
"fdir": "^6.5.0",
3959
+
"lightningcss": "^1.30.1",
3960
+
"picomatch": "^4.0.3",
3961
+
"postcss": "^8.5.6",
3962
+
"rolldown": "1.0.0-beta.41",
3963
+
"tinyglobby": "^0.2.15"
3964
+
},
3965
+
"bin": {
3966
+
"vite": "bin/vite.js"
3967
+
},
3968
+
"engines": {
3969
+
"node": "^20.19.0 || >=22.12.0"
3970
+
},
3971
+
"funding": {
3972
+
"url": "https://github.com/vitejs/vite?sponsor=1"
3973
+
},
3974
+
"optionalDependencies": {
3975
+
"fsevents": "~2.3.3"
3976
+
},
3977
+
"peerDependencies": {
3978
+
"@types/node": "^20.19.0 || >=22.12.0",
3979
+
"esbuild": "^0.25.0",
3980
+
"jiti": ">=1.21.0",
3981
+
"less": "^4.0.0",
3982
+
"sass": "^1.70.0",
3983
+
"sass-embedded": "^1.70.0",
3984
+
"stylus": ">=0.54.8",
3985
+
"sugarss": "^5.0.0",
3986
+
"terser": "^5.16.0",
3987
+
"tsx": "^4.8.1",
3988
+
"yaml": "^2.4.2"
3989
+
},
3990
+
"peerDependenciesMeta": {
3991
+
"@types/node": {
3992
+
"optional": true
3993
+
},
3994
+
"esbuild": {
3995
+
"optional": true
3996
+
},
3997
+
"jiti": {
3998
+
"optional": true
3999
+
},
4000
+
"less": {
4001
+
"optional": true
4002
+
},
4003
+
"sass": {
4004
+
"optional": true
4005
+
},
4006
+
"sass-embedded": {
4007
+
"optional": true
4008
+
},
4009
+
"stylus": {
4010
+
"optional": true
4011
+
},
4012
+
"sugarss": {
4013
+
"optional": true
4014
+
},
4015
+
"terser": {
4016
+
"optional": true
4017
+
},
4018
+
"tsx": {
4019
+
"optional": true
4020
+
},
4021
+
"yaml": {
4022
+
"optional": true
4023
+
}
4024
+
}
4025
+
},
4026
+
"node_modules/vscode-uri": {
4027
+
"version": "3.1.0",
4028
+
"dev": true,
4029
+
"license": "MIT"
4030
+
},
4031
+
"node_modules/webpack-virtual-modules": {
4032
+
"version": "0.6.2",
4033
+
"dev": true,
4034
+
"license": "MIT"
4035
+
},
4036
+
"node_modules/which": {
4037
+
"version": "2.0.2",
4038
+
"dev": true,
4039
+
"license": "ISC",
4040
+
"dependencies": {
4041
+
"isexe": "^2.0.0"
4042
+
},
4043
+
"bin": {
4044
+
"node-which": "bin/node-which"
4045
+
},
4046
+
"engines": {
4047
+
"node": ">= 8"
4048
+
}
4049
+
},
4050
+
"node_modules/word-wrap": {
4051
+
"version": "1.2.5",
4052
+
"dev": true,
4053
+
"license": "MIT",
4054
+
"engines": {
4055
+
"node": ">=0.10.0"
4056
+
}
4057
+
},
4058
+
"node_modules/yallist": {
4059
+
"version": "4.0.0",
4060
+
"dev": true,
4061
+
"license": "ISC"
4062
+
},
4063
+
"node_modules/yocto-queue": {
4064
+
"version": "0.1.0",
4065
+
"dev": true,
4066
+
"license": "MIT",
4067
+
"engines": {
4068
+
"node": ">=10"
4069
+
},
4070
+
"funding": {
4071
+
"url": "https://github.com/sponsors/sindresorhus"
4072
+
}
4073
+
}
4074
+
}
2863
4075
}
+65
-91
package.json
+65
-91
package.json
···
1
1
{
2
-
"name": "atproto-ui",
3
-
"version": "0.3.1-1",
4
-
"type": "module",
5
-
"description": "React components and hooks for rendering AT Protocol records.",
6
-
"main": "./lib-dist/index.js",
7
-
"module": "./lib-dist/index.js",
8
-
"types": "./lib-dist/index.d.ts",
9
-
"exports": {
10
-
".": {
11
-
"types": "./lib-dist/index.d.ts",
12
-
"import": "./lib-dist/index.js",
13
-
"default": "./lib-dist/index.js"
14
-
},
15
-
"./components/*": {
16
-
"types": "./lib-dist/components/*.d.ts",
17
-
"import": "./lib-dist/components/*.js",
18
-
"default": "./lib-dist/components/*.js"
19
-
},
20
-
"./hooks/*": {
21
-
"types": "./lib-dist/hooks/*.d.ts",
22
-
"import": "./lib-dist/hooks/*.js",
23
-
"default": "./lib-dist/hooks/*.js"
24
-
},
25
-
"./renderers/*": {
26
-
"types": "./lib-dist/renderers/*.d.ts",
27
-
"import": "./lib-dist/renderers/*.js",
28
-
"default": "./lib-dist/renderers/*.js"
29
-
},
30
-
"./providers/*": {
31
-
"types": "./lib-dist/providers/*.d.ts",
32
-
"import": "./lib-dist/providers/*.js",
33
-
"default": "./lib-dist/providers/*.js"
34
-
},
35
-
"./utils/*": {
36
-
"types": "./lib-dist/utils/*.d.ts",
37
-
"import": "./lib-dist/utils/*.js",
38
-
"default": "./lib-dist/utils/*.js"
39
-
},
40
-
"./types/*": {
41
-
"types": "./lib-dist/types/*.d.ts",
42
-
"import": "./lib-dist/types/*.js",
43
-
"default": "./lib-dist/types/*.js"
44
-
}
45
-
},
46
-
"files": [
47
-
"lib-dist",
48
-
"README.md"
49
-
],
50
-
"sideEffects": false,
51
-
"scripts": {
52
-
"dev": "vite",
53
-
"build": "tsc -b && vite build",
54
-
"lint": "eslint .",
55
-
"preview": "vite preview",
56
-
"prepublishOnly": "npm run build"
57
-
},
58
-
"peerDependencies": {
59
-
"react": "^18.2.0 || ^19.0.0",
60
-
"react-dom": "^18.2.0 || ^19.0.0"
61
-
},
62
-
"peerDependenciesMeta": {
63
-
"react-dom": {
64
-
"optional": true
65
-
}
66
-
},
67
-
"dependencies": {
68
-
"@atcute/atproto": "^3.1.7",
69
-
"@atcute/bluesky": "^3.2.3",
70
-
"@atcute/client": "^4.0.3",
71
-
"@atcute/identity-resolver": "^1.1.3",
72
-
"@atcute/tangled": "^1.0.6"
73
-
},
74
-
"devDependencies": {
75
-
"@eslint/js": "^9.36.0",
76
-
"@types/node": "^24.6.0",
77
-
"@types/react": "^19.1.16",
78
-
"@types/react-dom": "^19.1.9",
79
-
"@vitejs/plugin-react": "^5.0.4",
80
-
"eslint": "^9.36.0",
81
-
"eslint-plugin-react-hooks": "^5.2.0",
82
-
"eslint-plugin-react-refresh": "^0.4.22",
83
-
"globals": "^16.4.0",
84
-
"react": "^19.1.1",
85
-
"react-dom": "^19.1.1",
86
-
"typescript": "~5.9.3",
87
-
"typescript-eslint": "^8.45.0",
88
-
"vite": "npm:rolldown-vite@7.1.14"
89
-
},
90
-
"overrides": {
91
-
"vite": "npm:rolldown-vite@7.1.14"
92
-
}
2
+
"name": "atproto-ui",
3
+
"version": "0.12.0",
4
+
"type": "module",
5
+
"description": "React components and hooks for rendering AT Protocol records.",
6
+
"main": "./lib-dist/index.js",
7
+
"module": "./lib-dist/index.js",
8
+
"types": "./lib-dist/index.d.ts",
9
+
"exports": {
10
+
".": {
11
+
"import": "./lib-dist/index.js",
12
+
"require": "./lib-dist/index.js"
13
+
},
14
+
"./styles.css": "./lib-dist/styles.css"
15
+
},
16
+
"files": [
17
+
"lib-dist",
18
+
"README.md"
19
+
],
20
+
"sideEffects": [
21
+
"./lib-dist/styles.css"
22
+
],
23
+
"scripts": {
24
+
"dev": "vite",
25
+
"build": "vite build && tsc -b",
26
+
"build:demo": "BUILD_TARGET=demo vite build",
27
+
"build:all": "npm run build && npm run build:demo",
28
+
"lint": "eslint .",
29
+
"preview": "vite preview",
30
+
"prepublishOnly": "npm run build"
31
+
},
32
+
"peerDependencies": {
33
+
"react": "^18.2.0 || ^19.0.0",
34
+
"react-dom": "^18.2.0 || ^19.0.0"
35
+
},
36
+
"peerDependenciesMeta": {
37
+
"react-dom": {
38
+
"optional": true
39
+
}
40
+
},
41
+
"dependencies": {
42
+
"@atcute/atproto": "^3.1.7",
43
+
"@atcute/bluesky": "^3.2.3",
44
+
"@atcute/client": "^4.0.3",
45
+
"@atcute/identity-resolver": "^1.1.3",
46
+
"@atcute/tangled": "^1.0.10"
47
+
},
48
+
"devDependencies": {
49
+
"@eslint/js": "^9.36.0",
50
+
"@microsoft/api-extractor": "^7.53.1",
51
+
"@types/node": "^24.6.0",
52
+
"@types/react": "^19.1.16",
53
+
"@types/react-dom": "^19.1.9",
54
+
"@vitejs/plugin-react": "^5.0.4",
55
+
"eslint": "^9.36.0",
56
+
"eslint-plugin-react-hooks": "^5.2.0",
57
+
"eslint-plugin-react-refresh": "^0.4.22",
58
+
"globals": "^16.4.0",
59
+
"react": "^19.1.1",
60
+
"react-dom": "^19.1.1",
61
+
"rollup-plugin-typescript2": "^0.36.0",
62
+
"typescript": "~5.9.3",
63
+
"typescript-eslint": "^8.45.0",
64
+
"unplugin-dts": "^1.0.0-beta.6",
65
+
"vite": "npm:rolldown-vite@7.1.14"
66
+
}
93
67
}
+59
src/App.css
+59
src/App.css
···
1
+
/**
2
+
* Demo app styles - separate from atproto-ui component styles
3
+
* This demonstrates that atproto-ui components work well within
4
+
* apps that have their own theming system.
5
+
*/
6
+
7
+
/* Root styles for the demo app */
8
+
body {
9
+
margin: 0;
10
+
padding: 0;
11
+
background: var(--demo-bg);
12
+
color: var(--demo-text);
13
+
transition: background-color 200ms ease, color 200ms ease;
14
+
}
15
+
16
+
:root {
17
+
/* Light theme for demo app */
18
+
--demo-bg: #eeeeee;
19
+
--demo-text: #1a1a1a;
20
+
--demo-text-secondary: #666;
21
+
--demo-border: #ddd;
22
+
--demo-input-bg: #fff;
23
+
--demo-button-bg: #0066cc;
24
+
--demo-button-text: #fff;
25
+
--demo-code-bg: #f5f5f5;
26
+
--demo-code-border: #e0e0e0;
27
+
--demo-hr: #e0e0e0;
28
+
}
29
+
30
+
/* Dark theme for demo app */
31
+
[data-theme="dark"] {
32
+
--demo-bg: #1a1a1a;
33
+
--demo-text: #e0e0e0;
34
+
--demo-text-secondary: #999;
35
+
--demo-border: #444;
36
+
--demo-input-bg: #2a2a2a;
37
+
--demo-button-bg: #0066cc;
38
+
--demo-button-text: #fff;
39
+
--demo-code-bg: #2a2a2a;
40
+
--demo-code-border: #444;
41
+
--demo-hr: #444;
42
+
}
43
+
44
+
/* System preference dark mode */
45
+
@media (prefers-color-scheme: dark) {
46
+
:root:not([data-theme]),
47
+
:root[data-theme="system"] {
48
+
--demo-bg: #1a1a1a;
49
+
--demo-text: #e0e0e0;
50
+
--demo-text-secondary: #999;
51
+
--demo-border: #444;
52
+
--demo-input-bg: #2a2a2a;
53
+
--demo-button-bg: #0066cc;
54
+
--demo-button-text: #fff;
55
+
--demo-code-bg: #2a2a2a;
56
+
--demo-code-border: #444;
57
+
--demo-hr: #444;
58
+
}
59
+
}
+385
-348
src/App.tsx
+385
-348
src/App.tsx
···
1
-
import React, {
2
-
useState,
3
-
useCallback,
4
-
useEffect,
5
-
useMemo,
6
-
useRef,
7
-
} from "react";
8
-
import { AtProtoProvider } from "../lib/providers/AtProtoProvider";
9
-
import { AtProtoRecord } from "../lib/core/AtProtoRecord";
1
+
import React, { useState, useCallback, useRef } from "react";
2
+
import { AtProtoProvider, TangledRepo } from "../lib";
3
+
import "../lib/styles.css";
4
+
import "./App.css";
5
+
10
6
import { TangledString } from "../lib/components/TangledString";
11
7
import { LeafletDocument } from "../lib/components/LeafletDocument";
12
8
import { BlueskyProfile } from "../lib/components/BlueskyProfile";
···
16
12
} from "../lib/components/BlueskyPost";
17
13
import { BlueskyPostList } from "../lib/components/BlueskyPostList";
18
14
import { BlueskyQuotePost } from "../lib/components/BlueskyQuotePost";
15
+
import { GrainGallery } from "../lib/components/GrainGallery";
16
+
import { CurrentlyPlaying } from "../lib/components/CurrentlyPlaying";
17
+
import { LastPlayed } from "../lib/components/LastPlayed";
18
+
import { SongHistoryList } from "../lib/components/SongHistoryList";
19
19
import { useDidResolution } from "../lib/hooks/useDidResolution";
20
20
import { useLatestRecord } from "../lib/hooks/useLatestRecord";
21
-
import { ColorSchemeToggle } from "../lib/components/ColorSchemeToggle.tsx";
22
-
import {
23
-
useColorScheme,
24
-
type ColorSchemePreference,
25
-
} from "../lib/hooks/useColorScheme";
26
21
import type { FeedPostRecord } from "../lib/types/bluesky";
27
22
28
-
const COLOR_SCHEME_STORAGE_KEY = "atproto-ui-color-scheme";
29
-
30
23
const basicUsageSnippet = `import { AtProtoProvider, BlueskyPost } from 'atproto-ui';
31
24
32
25
export function App() {
···
37
30
);
38
31
}`;
39
32
40
-
const customComponentSnippet = `import { useLatestRecord, useColorScheme, AtProtoRecord } from 'atproto-ui';
33
+
const prefetchedDataSnippet = `import { BlueskyPost, useLatestRecord } from 'atproto-ui';
41
34
import type { FeedPostRecord } from 'atproto-ui';
42
35
43
-
const LatestPostSummary: React.FC<{ did: string }> = ({ did }) => {
44
-
const scheme = useColorScheme('system');
45
-
const { rkey, loading, error } = useLatestRecord<FeedPostRecord>(did, 'app.bsky.feed.post');
36
+
const LatestPostWithPrefetch: React.FC<{ did: string }> = ({ did }) => {
37
+
// Fetch once with the hook
38
+
const { record, rkey, loading } = useLatestRecord<FeedPostRecord>(
39
+
did,
40
+
'app.bsky.feed.post'
41
+
);
46
42
47
43
if (loading) return <span>Loadingโฆ</span>;
48
-
if (error || !rkey) return <span>No post yet.</span>;
44
+
if (!record || !rkey) return <span>No posts yet.</span>;
49
45
50
-
return (
51
-
<AtProtoRecord<FeedPostRecord>
52
-
did={did}
53
-
collection="app.bsky.feed.post"
54
-
rkey={rkey}
55
-
renderer={({ record }) => (
56
-
<article data-color-scheme={scheme}>
57
-
<strong>{record?.text ?? 'Empty post'}</strong>
58
-
</article>
59
-
)}
60
-
/>
61
-
);
46
+
// Pass prefetched recordโBlueskyPost won't re-fetch it
47
+
return <BlueskyPost did={did} rkey={rkey} record={record} />;
62
48
};`;
63
49
50
+
const atcuteUsageSnippet = `import { Client, simpleFetchHandler, ok } from '@atcute/client';
51
+
import type { AppBskyFeedPost } from '@atcute/bluesky';
52
+
import { BlueskyPost } from 'atproto-ui';
53
+
54
+
// Create atcute client
55
+
const client = new Client({
56
+
handler: simpleFetchHandler({ service: 'https://public.api.bsky.app' })
57
+
});
58
+
59
+
// Fetch a record
60
+
const data = await ok(
61
+
client.get('com.atproto.repo.getRecord', {
62
+
params: {
63
+
repo: 'did:plc:ttdrpj45ibqunmfhdsb4zdwq',
64
+
collection: 'app.bsky.feed.post',
65
+
rkey: '3m45rq4sjes2h'
66
+
}
67
+
})
68
+
);
69
+
70
+
const record = data.value as AppBskyFeedPost.Main;
71
+
72
+
// Pass atcute record directly to component!
73
+
<BlueskyPost
74
+
did="did:plc:ttdrpj45ibqunmfhdsb4zdwq"
75
+
rkey="3m45rq4sjes2h"
76
+
record={record}
77
+
/>`;
78
+
64
79
const codeBlockBase: React.CSSProperties = {
65
80
fontFamily: 'Menlo, Consolas, "SFMono-Regular", ui-monospace, monospace',
66
81
fontSize: 12,
···
71
86
lineHeight: 1.6,
72
87
};
73
88
89
+
const ThemeSwitcher: React.FC = () => {
90
+
const [theme, setTheme] = useState<"light" | "dark" | "system">("system");
91
+
92
+
const toggle = () => {
93
+
const schemes: ("light" | "dark" | "system")[] = [
94
+
"light",
95
+
"dark",
96
+
"system",
97
+
];
98
+
const currentIndex = schemes.indexOf(theme);
99
+
const nextIndex = (currentIndex + 1) % schemes.length;
100
+
const nextTheme = schemes[nextIndex];
101
+
setTheme(nextTheme);
102
+
103
+
// Update the data-theme attribute on the document element
104
+
if (nextTheme === "system") {
105
+
document.documentElement.removeAttribute("data-theme");
106
+
} else {
107
+
document.documentElement.setAttribute("data-theme", nextTheme);
108
+
}
109
+
};
110
+
111
+
return (
112
+
<button
113
+
onClick={toggle}
114
+
style={{
115
+
padding: "8px 12px",
116
+
borderRadius: 8,
117
+
border: "1px solid var(--demo-border)",
118
+
background: "var(--demo-input-bg)",
119
+
color: "var(--demo-text)",
120
+
cursor: "pointer",
121
+
}}
122
+
>
123
+
Theme: {theme}
124
+
</button>
125
+
);
126
+
};
127
+
74
128
const FullDemo: React.FC = () => {
75
129
const handleInputRef = useRef<HTMLInputElement | null>(null);
76
130
const [submitted, setSubmitted] = useState<string | null>(null);
77
-
const [colorSchemePreference, setColorSchemePreference] =
78
-
useState<ColorSchemePreference>(() => {
79
-
if (typeof window === "undefined") return "system";
80
-
try {
81
-
const stored = window.localStorage.getItem(
82
-
COLOR_SCHEME_STORAGE_KEY,
83
-
);
84
-
if (
85
-
stored === "light" ||
86
-
stored === "dark" ||
87
-
stored === "system"
88
-
)
89
-
return stored;
90
-
} catch {
91
-
/* ignore */
92
-
}
93
-
return "system";
94
-
});
95
-
const scheme = useColorScheme(colorSchemePreference);
131
+
96
132
const { did, loading: resolvingDid } = useDidResolution(
97
133
submitted ?? undefined,
98
134
);
···
107
143
setSubmitted(nextValue);
108
144
}, []);
109
145
110
-
useEffect(() => {
111
-
if (typeof window === "undefined") return;
112
-
try {
113
-
window.localStorage.setItem(
114
-
COLOR_SCHEME_STORAGE_KEY,
115
-
colorSchemePreference,
116
-
);
117
-
} catch {
118
-
/* ignore */
119
-
}
120
-
}, [colorSchemePreference]);
121
-
122
-
useEffect(() => {
123
-
if (typeof document === "undefined") return;
124
-
const root = document.documentElement;
125
-
const body = document.body;
126
-
const prevScheme = root.dataset.colorScheme;
127
-
const prevBg = body.style.backgroundColor;
128
-
const prevColor = body.style.color;
129
-
root.dataset.colorScheme = scheme;
130
-
body.style.backgroundColor = scheme === "dark" ? "#020617" : "#f8fafc";
131
-
body.style.color = scheme === "dark" ? "#e2e8f0" : "#0f172a";
132
-
return () => {
133
-
root.dataset.colorScheme = prevScheme ?? "";
134
-
body.style.backgroundColor = prevBg;
135
-
body.style.color = prevColor;
136
-
};
137
-
}, [scheme]);
138
-
139
146
const showHandle =
140
147
submitted && !submitted.startsWith("did:") ? submitted : undefined;
141
148
142
-
const mutedTextColor = useMemo(
143
-
() => (scheme === "dark" ? "#94a3b8" : "#555"),
144
-
[scheme],
145
-
);
146
-
const panelStyle = useMemo<React.CSSProperties>(
147
-
() => ({
148
-
display: "flex",
149
-
flexDirection: "column",
150
-
gap: 8,
151
-
padding: 10,
152
-
borderRadius: 12,
153
-
borderColor: scheme === "dark" ? "#1e293b" : "#e2e8f0",
154
-
}),
155
-
[scheme],
156
-
);
157
-
const baseTextColor = useMemo(
158
-
() => (scheme === "dark" ? "#e2e8f0" : "#0f172a"),
159
-
[scheme],
160
-
);
161
-
const gistPanelStyle = useMemo<React.CSSProperties>(
162
-
() => ({
163
-
...panelStyle,
164
-
padding: 0,
165
-
border: "none",
166
-
background: "transparent",
167
-
backdropFilter: "none",
168
-
marginTop: 32,
169
-
}),
170
-
[panelStyle],
171
-
);
172
-
const leafletPanelStyle = useMemo<React.CSSProperties>(
173
-
() => ({
174
-
...panelStyle,
175
-
padding: 0,
176
-
border: "none",
177
-
background: "transparent",
178
-
backdropFilter: "none",
179
-
marginTop: 32,
180
-
alignItems: "center",
181
-
}),
182
-
[panelStyle],
183
-
);
184
-
const primaryGridStyle = useMemo<React.CSSProperties>(
185
-
() => ({
186
-
display: "grid",
187
-
gap: 32,
188
-
gridTemplateColumns: "repeat(auto-fit, minmax(320px, 1fr))",
189
-
}),
190
-
[],
191
-
);
192
-
const columnStackStyle = useMemo<React.CSSProperties>(
193
-
() => ({
194
-
display: "flex",
195
-
flexDirection: "column",
196
-
gap: 32,
197
-
}),
198
-
[],
199
-
);
200
-
const codeBlockStyle = useMemo<React.CSSProperties>(
201
-
() => ({
202
-
...codeBlockBase,
203
-
background: scheme === "dark" ? "#0b1120" : "#f1f5f9",
204
-
border: `1px solid ${scheme === "dark" ? "#1e293b" : "#e2e8f0"}`,
205
-
}),
206
-
[scheme],
207
-
);
208
-
const codeTextStyle = useMemo<React.CSSProperties>(
209
-
() => ({
210
-
margin: 0,
211
-
display: "block",
212
-
fontFamily: codeBlockBase.fontFamily,
213
-
fontSize: 12,
214
-
lineHeight: 1.6,
215
-
whiteSpace: "pre",
216
-
}),
217
-
[],
218
-
);
149
+
const panelStyle: React.CSSProperties = {
150
+
display: "flex",
151
+
flexDirection: "column",
152
+
gap: 8,
153
+
padding: 10,
154
+
borderRadius: 12,
155
+
border: `1px solid var(--demo-border)`,
156
+
};
157
+
158
+
const gistPanelStyle: React.CSSProperties = {
159
+
...panelStyle,
160
+
padding: 0,
161
+
border: "none",
162
+
background: "transparent",
163
+
backdropFilter: "none",
164
+
marginTop: 32,
165
+
};
166
+
const leafletPanelStyle: React.CSSProperties = {
167
+
...panelStyle,
168
+
padding: 0,
169
+
border: "none",
170
+
background: "transparent",
171
+
backdropFilter: "none",
172
+
marginTop: 32,
173
+
alignItems: "center",
174
+
};
175
+
const primaryGridStyle: React.CSSProperties = {
176
+
display: "grid",
177
+
gap: 32,
178
+
gridTemplateColumns: "repeat(auto-fit, minmax(320px, 1fr))",
179
+
};
180
+
const columnStackStyle: React.CSSProperties = {
181
+
display: "flex",
182
+
flexDirection: "column",
183
+
gap: 32,
184
+
};
185
+
const codeBlockStyle: React.CSSProperties = {
186
+
...codeBlockBase,
187
+
background: `var(--demo-code-bg)`,
188
+
border: `1px solid var(--demo-code-border)`,
189
+
color: `var(--demo-text)`,
190
+
};
191
+
const codeTextStyle: React.CSSProperties = {
192
+
margin: 0,
193
+
display: "block",
194
+
fontFamily: codeBlockBase.fontFamily,
195
+
fontSize: 12,
196
+
lineHeight: 1.6,
197
+
whiteSpace: "pre",
198
+
};
219
199
const basicCodeRef = useRef<HTMLElement | null>(null);
220
200
const customCodeRef = useRef<HTMLElement | null>(null);
221
201
222
-
// Latest Bluesky post
202
+
// Latest Bluesky post - fetch with record for prefetch demo
223
203
const {
204
+
record: latestPostRecord,
224
205
rkey: latestPostRkey,
225
206
loading: loadingLatestPost,
226
207
empty: noPosts,
227
208
error: latestPostError,
228
-
} = useLatestRecord<unknown>(did, BLUESKY_POST_COLLECTION);
209
+
} = useLatestRecord<FeedPostRecord>(did, BLUESKY_POST_COLLECTION);
229
210
230
211
const quoteSampleDid = "did:plc:ttdrpj45ibqunmfhdsb4zdwq";
231
212
const quoteSampleRkey = "3m2prlq6xxc2v";
···
236
217
display: "flex",
237
218
flexDirection: "column",
238
219
gap: 20,
239
-
color: baseTextColor,
240
220
}}
241
221
>
242
222
<div
···
264
244
flex: "1 1 260px",
265
245
padding: "6px 8px",
266
246
borderRadius: 8,
267
-
border: "1px solid",
268
-
borderColor:
269
-
scheme === "dark" ? "#1e293b" : "#cbd5f5",
270
-
background: scheme === "dark" ? "#0b1120" : "#fff",
271
-
color: scheme === "dark" ? "#e2e8f0" : "#0f172a",
247
+
border: `1px solid var(--demo-border)`,
248
+
background: `var(--demo-input-bg)`,
249
+
color: `var(--demo-text)`,
272
250
}}
273
251
/>
274
252
<button
···
277
255
padding: "6px 16px",
278
256
borderRadius: 8,
279
257
border: "none",
280
-
background: "#2563eb",
281
-
color: "#fff",
258
+
background: `var(--demo-button-bg)`,
259
+
color: `var(--demo-button-text)`,
282
260
cursor: "pointer",
283
261
}}
284
262
>
285
263
Load
286
264
</button>
287
265
</form>
288
-
<ColorSchemeToggle
289
-
value={colorSchemePreference}
290
-
onChange={setColorSchemePreference}
291
-
scheme={scheme}
292
-
/>
266
+
<ThemeSwitcher />
293
267
</div>
294
268
{!submitted && (
295
-
<p style={{ color: mutedTextColor }}>
269
+
<p style={{ color: `var(--demo-text-secondary)` }}>
296
270
Enter a handle to fetch your profile, latest Bluesky post, a
297
271
Tangled string, and a Leaflet document.
298
272
</p>
299
273
)}
300
274
{submitted && resolvingDid && (
301
-
<p style={{ color: mutedTextColor }}>Resolving DIDโฆ</p>
275
+
<p style={{ color: `var(--demo-text-secondary)` }}>
276
+
Resolving DIDโฆ
277
+
</p>
302
278
)}
303
279
{did && (
304
280
<>
···
306
282
<div style={columnStackStyle}>
307
283
<section style={panelStyle}>
308
284
<h3 style={sectionHeaderStyle}>Profile</h3>
309
-
<BlueskyProfile
310
-
did={did}
311
-
handle={showHandle}
312
-
colorScheme={colorSchemePreference}
313
-
/>
285
+
<BlueskyProfile did={did} handle={showHandle} />
314
286
</section>
315
287
<section style={panelStyle}>
316
288
<h3 style={sectionHeaderStyle}>Recent Posts</h3>
317
-
<BlueskyPostList
318
-
did={did}
319
-
colorScheme={colorSchemePreference}
289
+
<BlueskyPostList did={did} />
290
+
</section>
291
+
<section style={panelStyle}>
292
+
<h3 style={sectionHeaderStyle}>
293
+
grain.social Gallery Demo
294
+
</h3>
295
+
<p
296
+
style={{
297
+
fontSize: 12,
298
+
color: `var(--demo-text-secondary)`,
299
+
margin: "0 0 8px",
300
+
}}
301
+
>
302
+
Instagram-style photo gallery from grain.social
303
+
</p>
304
+
<GrainGallery
305
+
did="kat.meangirls.online"
306
+
rkey="3m2e2qikseq2f"
320
307
/>
321
308
</section>
309
+
<section style={panelStyle}>
310
+
<h3 style={sectionHeaderStyle}>
311
+
teal.fm Currently Playing
312
+
</h3>
313
+
<p
314
+
style={{
315
+
fontSize: 12,
316
+
color: `var(--demo-text-secondary)`,
317
+
margin: "0 0 8px",
318
+
}}
319
+
>
320
+
Currently playing track from teal.fm (refreshes every 15s)
321
+
</p>
322
+
<CurrentlyPlaying did="nekomimi.pet" />
323
+
</section>
324
+
<section style={panelStyle}>
325
+
<h3 style={sectionHeaderStyle}>
326
+
teal.fm Last Played
327
+
</h3>
328
+
<p
329
+
style={{
330
+
fontSize: 12,
331
+
color: `var(--demo-text-secondary)`,
332
+
margin: "0 0 8px",
333
+
}}
334
+
>
335
+
Most recent play from teal.fm feed
336
+
</p>
337
+
<LastPlayed did="nekomimi.pet" />
338
+
</section>
339
+
<section style={panelStyle}>
340
+
<h3 style={sectionHeaderStyle}>
341
+
teal.fm Song History
342
+
</h3>
343
+
<p
344
+
style={{
345
+
fontSize: 12,
346
+
color: `var(--demo-text-secondary)`,
347
+
margin: "0 0 8px",
348
+
}}
349
+
>
350
+
Listening history with album art focus
351
+
</p>
352
+
<SongHistoryList did="nekomimi.pet" limit={6} />
353
+
</section>
322
354
</div>
323
355
<div style={columnStackStyle}>
324
356
<section style={panelStyle}>
325
357
<h3 style={sectionHeaderStyle}>
326
-
Latest Bluesky Post
358
+
Latest Post (Prefetched Data)
327
359
</h3>
360
+
<p
361
+
style={{
362
+
fontSize: 12,
363
+
color: `var(--demo-text-secondary)`,
364
+
margin: "0 0 8px",
365
+
}}
366
+
>
367
+
Using{" "}
368
+
<code
369
+
style={{
370
+
background: `var(--demo-code-bg)`,
371
+
padding: "2px 4px",
372
+
borderRadius: 3,
373
+
color: "var(--demo-text)",
374
+
}}
375
+
>
376
+
useLatestRecord
377
+
</code>{" "}
378
+
to fetch once, then passing{" "}
379
+
<code
380
+
style={{
381
+
background: `var(--demo-code-bg)`,
382
+
padding: "2px 4px",
383
+
borderRadius: 3,
384
+
color: "var(--demo-text)",
385
+
}}
386
+
>
387
+
record
388
+
</code>{" "}
389
+
propโno re-fetch!
390
+
</p>
328
391
{loadingLatestPost && (
329
392
<div style={loadingBox}>
330
393
Loading latest postโฆ
···
336
399
</div>
337
400
)}
338
401
{noPosts && (
339
-
<div
340
-
style={{
341
-
...infoBox,
342
-
color: mutedTextColor,
343
-
}}
344
-
>
345
-
No posts found.
346
-
</div>
402
+
<div style={infoBox}>No posts found.</div>
347
403
)}
348
-
{!loadingLatestPost && latestPostRkey && (
349
-
<BlueskyPost
350
-
did={did}
351
-
rkey={latestPostRkey}
352
-
colorScheme={colorSchemePreference}
353
-
/>
354
-
)}
404
+
{!loadingLatestPost &&
405
+
latestPostRkey &&
406
+
latestPostRecord && (
407
+
<BlueskyPost
408
+
did={did}
409
+
rkey={latestPostRkey}
410
+
record={latestPostRecord}
411
+
/>
412
+
)}
355
413
</section>
356
414
<section style={panelStyle}>
357
415
<h3 style={sectionHeaderStyle}>
···
360
418
<BlueskyQuotePost
361
419
did={quoteSampleDid}
362
420
rkey={quoteSampleRkey}
363
-
colorScheme={colorSchemePreference}
421
+
/>
422
+
</section>
423
+
<section style={panelStyle}>
424
+
<h3 style={sectionHeaderStyle}>
425
+
Reply Post Demo
426
+
</h3>
427
+
<BlueskyPost
428
+
did="did:plc:xwhsmuozq3mlsp56dyd7copv"
429
+
rkey="3m3je5ydg4s2o"
430
+
showParent={true}
431
+
recursiveParent={true}
364
432
/>
365
433
</section>
434
+
<section style={panelStyle}>
435
+
<h3 style={sectionHeaderStyle}>
436
+
Rich Text Facets Demo
437
+
</h3>
438
+
<p
439
+
style={{
440
+
fontSize: 12,
441
+
color: `var(--demo-text-secondary)`,
442
+
margin: "0 0 8px",
443
+
}}
444
+
>
445
+
Post with mentions, links, and hashtags
446
+
</p>
447
+
<BlueskyPost
448
+
did="nekomimi.pet"
449
+
rkey="3m45s553cys22"
450
+
showParent={false}
451
+
/>
452
+
</section>
453
+
<section style={panelStyle}>
454
+
<TangledRepo
455
+
did="did:plc:ttdrpj45ibqunmfhdsb4zdwq"
456
+
rkey="3m2sx5zpxzs22"
457
+
/>
458
+
</section>
459
+
<section style={panelStyle}>
460
+
<h3 style={sectionHeaderStyle}>
461
+
Custom Themed Post
462
+
</h3>
463
+
<p
464
+
style={{
465
+
fontSize: 12,
466
+
color: `var(--demo-text-secondary)`,
467
+
margin: "0 0 8px",
468
+
}}
469
+
>
470
+
Wrapping a component in a div with custom
471
+
CSS variables to override the theme!
472
+
</p>
473
+
<div
474
+
style={
475
+
{
476
+
"--atproto-color-bg":
477
+
"var(--demo-secondary-bg)",
478
+
"--atproto-color-bg-elevated":
479
+
"var(--demo-input-bg)",
480
+
"--atproto-color-bg-secondary":
481
+
"var(--demo-code-bg)",
482
+
"--atproto-color-text":
483
+
"var(--demo-text)",
484
+
"--atproto-color-text-secondary":
485
+
"var(--demo-text-secondary)",
486
+
"--atproto-color-text-muted":
487
+
"var(--demo-text-secondary)",
488
+
"--atproto-color-border":
489
+
"var(--demo-border)",
490
+
"--atproto-color-border-subtle":
491
+
"var(--demo-border)",
492
+
"--atproto-color-link":
493
+
"var(--demo-button-bg)",
494
+
} as React.CSSProperties
495
+
}
496
+
>
497
+
<BlueskyPost
498
+
did="nekomimi.pet"
499
+
rkey="3m2dgvyws7k27"
500
+
/>
501
+
</div>
502
+
</section>
366
503
</div>
367
504
</div>
368
505
<section style={gistPanelStyle}>
···
370
507
<TangledString
371
508
did="nekomimi.pet"
372
509
rkey="3m2p4gjptg522"
373
-
colorScheme={colorSchemePreference}
374
510
/>
375
511
</section>
376
512
<section style={leafletPanelStyle}>
···
385
521
<LeafletDocument
386
522
did={"did:plc:ttdrpj45ibqunmfhdsb4zdwq"}
387
523
rkey={"3m2seagm2222c"}
388
-
colorScheme={colorSchemePreference}
389
524
/>
390
525
</div>
391
526
</section>
392
527
</>
393
528
)}
394
529
<section style={{ ...panelStyle, marginTop: 32 }}>
395
-
<h3 style={sectionHeaderStyle}>Build your own component</h3>
396
-
<p style={{ color: mutedTextColor, margin: "4px 0 8px" }}>
530
+
<h3 style={sectionHeaderStyle}>Code Examples</h3>
531
+
<p
532
+
style={{
533
+
color: `var(--demo-text-secondary)`,
534
+
margin: "4px 0 8px",
535
+
}}
536
+
>
397
537
Wrap your app with the provider once and drop the ready-made
398
538
components wherever you need them.
399
539
</p>
···
406
546
{basicUsageSnippet}
407
547
</code>
408
548
</pre>
409
-
<p style={{ color: mutedTextColor, margin: "16px 0 8px" }}>
410
-
Need to make your own component? Compose your own renderer
411
-
with the hooks and utilities that ship with the library.
549
+
<p
550
+
style={{
551
+
color: `var(--demo-text-secondary)`,
552
+
margin: "16px 0 8px",
553
+
}}
554
+
>
555
+
Pass prefetched data to components to skip API callsโperfect
556
+
for SSR or caching.
412
557
</p>
413
558
<pre style={codeBlockStyle}>
414
559
<code
···
416
561
className="language-tsx"
417
562
style={codeTextStyle}
418
563
>
419
-
{customComponentSnippet}
564
+
{prefetchedDataSnippet}
420
565
</code>
421
566
</pre>
422
-
{did && (
423
-
<div
424
-
style={{
425
-
marginTop: 16,
426
-
display: "flex",
427
-
flexDirection: "column",
428
-
gap: 12,
429
-
}}
430
-
>
431
-
<p style={{ color: mutedTextColor, margin: 0 }}>
432
-
Live example with your handle:
433
-
</p>
434
-
<LatestPostSummary
435
-
did={did}
436
-
handle={showHandle}
437
-
colorScheme={colorSchemePreference}
438
-
/>
439
-
</div>
440
-
)}
567
+
<p
568
+
style={{
569
+
color: `var(--demo-text-secondary)`,
570
+
margin: "16px 0 8px",
571
+
}}
572
+
>
573
+
Use atcute directly to construct records and pass them to
574
+
componentsโfully compatible!
575
+
</p>
576
+
<pre style={codeBlockStyle}>
577
+
<code className="language-tsx" style={codeTextStyle}>
578
+
{atcuteUsageSnippet}
579
+
</code>
580
+
</pre>
441
581
</section>
442
582
</div>
443
583
);
444
584
};
445
585
446
-
const LatestPostSummary: React.FC<{
447
-
did: string;
448
-
handle?: string;
449
-
colorScheme: ColorSchemePreference;
450
-
}> = ({ did, colorScheme }) => {
451
-
const { record, rkey, loading, error } = useLatestRecord<FeedPostRecord>(
452
-
did,
453
-
BLUESKY_POST_COLLECTION,
454
-
);
455
-
const scheme = useColorScheme(colorScheme);
456
-
const palette =
457
-
scheme === "dark"
458
-
? latestSummaryPalette.dark
459
-
: latestSummaryPalette.light;
460
-
461
-
if (loading) return <div style={palette.muted}>Loading summaryโฆ</div>;
462
-
if (error)
463
-
return <div style={palette.error}>Failed to load the latest post.</div>;
464
-
if (!rkey) return <div style={palette.muted}>No posts published yet.</div>;
465
-
466
-
const atProtoProps = record
467
-
? { record }
468
-
: { did, collection: "app.bsky.feed.post", rkey };
469
-
470
-
return (
471
-
<AtProtoRecord<FeedPostRecord>
472
-
{...atProtoProps}
473
-
renderer={({ record: resolvedRecord }) => (
474
-
<article data-color-scheme={scheme}>
475
-
<strong>{resolvedRecord?.text ?? "Empty post"}</strong>
476
-
</article>
477
-
)}
478
-
/>
479
-
);
480
-
};
481
-
482
586
const sectionHeaderStyle: React.CSSProperties = {
483
587
margin: "4px 0",
484
588
fontSize: 16,
589
+
color: "var(--demo-text)",
485
590
};
486
591
const loadingBox: React.CSSProperties = { padding: 8 };
487
592
const errorBox: React.CSSProperties = { padding: 8, color: "crimson" };
488
-
const infoBox: React.CSSProperties = { padding: 8, color: "#555" };
489
-
490
-
const latestSummaryPalette = {
491
-
light: {
492
-
card: {
493
-
border: "1px solid #e2e8f0",
494
-
background: "#ffffff",
495
-
borderRadius: 12,
496
-
padding: 12,
497
-
display: "flex",
498
-
flexDirection: "column",
499
-
gap: 8,
500
-
} satisfies React.CSSProperties,
501
-
header: {
502
-
display: "flex",
503
-
alignItems: "baseline",
504
-
justifyContent: "space-between",
505
-
gap: 12,
506
-
color: "#0f172a",
507
-
} satisfies React.CSSProperties,
508
-
time: {
509
-
fontSize: 12,
510
-
color: "#64748b",
511
-
} satisfies React.CSSProperties,
512
-
text: {
513
-
margin: 0,
514
-
color: "#1f2937",
515
-
whiteSpace: "pre-wrap",
516
-
} satisfies React.CSSProperties,
517
-
link: {
518
-
color: "#2563eb",
519
-
fontWeight: 600,
520
-
fontSize: 12,
521
-
textDecoration: "none",
522
-
} satisfies React.CSSProperties,
523
-
muted: {
524
-
color: "#64748b",
525
-
} satisfies React.CSSProperties,
526
-
error: {
527
-
color: "crimson",
528
-
} satisfies React.CSSProperties,
529
-
},
530
-
dark: {
531
-
card: {
532
-
border: "1px solid #1e293b",
533
-
background: "#0f172a",
534
-
borderRadius: 12,
535
-
padding: 12,
536
-
display: "flex",
537
-
flexDirection: "column",
538
-
gap: 8,
539
-
} satisfies React.CSSProperties,
540
-
header: {
541
-
display: "flex",
542
-
alignItems: "baseline",
543
-
justifyContent: "space-between",
544
-
gap: 12,
545
-
color: "#e2e8f0",
546
-
} satisfies React.CSSProperties,
547
-
time: {
548
-
fontSize: 12,
549
-
color: "#cbd5f5",
550
-
} satisfies React.CSSProperties,
551
-
text: {
552
-
margin: 0,
553
-
color: "#e2e8f0",
554
-
whiteSpace: "pre-wrap",
555
-
} satisfies React.CSSProperties,
556
-
link: {
557
-
color: "#38bdf8",
558
-
fontWeight: 600,
559
-
fontSize: 12,
560
-
textDecoration: "none",
561
-
} satisfies React.CSSProperties,
562
-
muted: {
563
-
color: "#94a3b8",
564
-
} satisfies React.CSSProperties,
565
-
error: {
566
-
color: "#f472b6",
567
-
} satisfies React.CSSProperties,
568
-
},
569
-
} as const;
593
+
const infoBox: React.CSSProperties = {
594
+
padding: 8,
595
+
color: "var(--demo-text-secondary)",
596
+
};
570
597
571
598
export const App: React.FC = () => {
572
599
return (
···
577
604
margin: "40px auto",
578
605
padding: "0 20px",
579
606
fontFamily: "system-ui, sans-serif",
607
+
minHeight: "100vh",
580
608
}}
581
609
>
582
-
<h1 style={{ marginTop: 0 }}>atproto-ui Demo</h1>
583
-
<p style={{ lineHeight: 1.4 }}>
610
+
<h1 style={{ marginTop: 0, color: "var(--demo-text)" }}>
611
+
atproto-ui Demo
612
+
</h1>
613
+
<p
614
+
style={{
615
+
lineHeight: 1.4,
616
+
color: "var(--demo-text-secondary)",
617
+
}}
618
+
>
584
619
A component library for rendering common AT Protocol records
585
620
for applications such as Bluesky and Tangled.
586
621
</p>
587
-
<hr style={{ margin: "32px 0" }} />
622
+
<hr
623
+
style={{ margin: "32px 0", borderColor: "var(--demo-hr)" }}
624
+
/>
588
625
<FullDemo />
589
626
</div>
590
627
</AtProtoProvider>
+3
tsconfig.app.json
+3
tsconfig.app.json
+6
-4
tsconfig.lib.json
+6
-4
tsconfig.lib.json
···
12
12
"allowSyntheticDefaultImports": true,
13
13
"esModuleInterop": true,
14
14
"resolveJsonModule": true,
15
+
"noEmit": true,
16
+
"emitDeclarationOnly": true,
15
17
"declaration": true,
16
-
"declarationMap": true,
17
-
"emitDeclarationOnly": true,
18
-
"sourceMap": false,
18
+
"declarationDir": "dist-lib",
19
+
"sourceMap": true,
19
20
"outDir": "./lib-dist",
20
-
"rootDir": "./lib"
21
+
"rootDir": "./lib",
22
+
"types": ["@atcute/bluesky", "@atcute/tangled"]
21
23
},
22
24
"include": ["lib/**/*.ts", "lib/**/*.tsx"]
23
25
}
-1
tsconfig.lib.tsbuildinfo
-1
tsconfig.lib.tsbuildinfo
···
1
-
{"fileNames":["./node_modules/typescript/lib/lib.es5.d.ts","./node_modules/typescript/lib/lib.es2015.d.ts","./node_modules/typescript/lib/lib.es2016.d.ts","./node_modules/typescript/lib/lib.es2017.d.ts","./node_modules/typescript/lib/lib.es2018.d.ts","./node_modules/typescript/lib/lib.es2019.d.ts","./node_modules/typescript/lib/lib.es2020.d.ts","./node_modules/typescript/lib/lib.dom.d.ts","./node_modules/typescript/lib/lib.dom.iterable.d.ts","./node_modules/typescript/lib/lib.es2015.core.d.ts","./node_modules/typescript/lib/lib.es2015.collection.d.ts","./node_modules/typescript/lib/lib.es2015.generator.d.ts","./node_modules/typescript/lib/lib.es2015.iterable.d.ts","./node_modules/typescript/lib/lib.es2015.promise.d.ts","./node_modules/typescript/lib/lib.es2015.proxy.d.ts","./node_modules/typescript/lib/lib.es2015.reflect.d.ts","./node_modules/typescript/lib/lib.es2015.symbol.d.ts","./node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","./node_modules/typescript/lib/lib.es2016.array.include.d.ts","./node_modules/typescript/lib/lib.es2016.intl.d.ts","./node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","./node_modules/typescript/lib/lib.es2017.date.d.ts","./node_modules/typescript/lib/lib.es2017.object.d.ts","./node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","./node_modules/typescript/lib/lib.es2017.string.d.ts","./node_modules/typescript/lib/lib.es2017.intl.d.ts","./node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","./node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","./node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","./node_modules/typescript/lib/lib.es2018.intl.d.ts","./node_modules/typescript/lib/lib.es2018.promise.d.ts","./node_modules/typescript/lib/lib.es2018.regexp.d.ts","./node_modules/typescript/lib/lib.es2019.array.d.ts","./node_modules/typescript/lib/lib.es2019.object.d.ts","./node_modules/typescript/lib/lib.es2019.string.d.ts","./node_modules/typescript/lib/lib.es2019.symbol.d.ts","./node_modules/typescript/lib/lib.es2019.intl.d.ts","./node_modules/typescript/lib/lib.es2020.bigint.d.ts","./node_modules/typescript/lib/lib.es2020.date.d.ts","./node_modules/typescript/lib/lib.es2020.promise.d.ts","./node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","./node_modules/typescript/lib/lib.es2020.string.d.ts","./node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","./node_modules/typescript/lib/lib.es2020.intl.d.ts","./node_modules/typescript/lib/lib.es2020.number.d.ts","./node_modules/typescript/lib/lib.esnext.disposable.d.ts","./node_modules/typescript/lib/lib.esnext.float16.d.ts","./node_modules/typescript/lib/lib.decorators.d.ts","./node_modules/typescript/lib/lib.decorators.legacy.d.ts","./node_modules/@types/react/global.d.ts","./node_modules/csstype/index.d.ts","./node_modules/@types/react/index.d.ts","./node_modules/@types/react/jsx-runtime.d.ts","./node_modules/@atcute/lexicons/dist/syntax/did.d.ts","./node_modules/@atcute/lexicons/dist/syntax/handle.d.ts","./node_modules/@atcute/lexicons/dist/syntax/at-identifier.d.ts","./node_modules/@atcute/lexicons/dist/syntax/nsid.d.ts","./node_modules/@atcute/lexicons/dist/syntax/record-key.d.ts","./node_modules/@atcute/lexicons/dist/utils.d.ts","./node_modules/@atcute/lexicons/dist/syntax/at-uri.d.ts","./node_modules/@atcute/lexicons/dist/syntax/cid.d.ts","./node_modules/@atcute/lexicons/dist/syntax/datetime.d.ts","./node_modules/@atcute/lexicons/dist/syntax/language.d.ts","./node_modules/@atcute/lexicons/dist/syntax/tid.d.ts","./node_modules/@atcute/lexicons/dist/syntax/uri.d.ts","./node_modules/@atcute/lexicons/dist/interfaces/cid-link.d.ts","./node_modules/@atcute/lexicons/dist/interfaces/blob.d.ts","./node_modules/@atcute/lexicons/dist/interfaces/bytes.d.ts","./node_modules/@atcute/lexicons/dist/types/brand.d.ts","./node_modules/@standard-schema/spec/dist/index.d.ts","./node_modules/@atcute/lexicons/dist/syntax/index.d.ts","./node_modules/@atcute/lexicons/dist/interfaces/index.d.ts","./node_modules/@atcute/lexicons/dist/validations/index.d.ts","./node_modules/@atcute/lexicons/dist/index.d.ts","./node_modules/@atcute/lexicons/dist/ambient.d.ts","./node_modules/@atcute/client/dist/fetch-handler.d.ts","./node_modules/@atcute/client/dist/client.d.ts","./node_modules/@atcute/client/dist/credential-manager.d.ts","./node_modules/@atcute/client/dist/index.d.ts","./node_modules/@badrap/valita/dist/mjs/index.d.mts","./node_modules/@atcute/identity/dist/types.d.ts","./node_modules/@atcute/identity/dist/typedefs.d.ts","./node_modules/@atcute/identity/dist/utils.d.ts","./node_modules/@atcute/identity/dist/did.d.ts","./node_modules/@atcute/identity/dist/methods/key.d.ts","./node_modules/@atcute/identity/dist/methods/plc.d.ts","./node_modules/@atcute/identity/dist/methods/web.d.ts","./node_modules/@atcute/identity/dist/index.d.ts","./node_modules/@atcute/identity-resolver/dist/types.d.ts","./node_modules/@atcute/identity-resolver/dist/did/composite.d.ts","./node_modules/@atcute/identity-resolver/dist/did/methods/plc.d.ts","./node_modules/@atcute/identity-resolver/dist/did/methods/web.d.ts","./node_modules/@atcute/identity-resolver/dist/did/methods/xrpc.d.ts","./node_modules/@atcute/identity-resolver/dist/handle/composite.d.ts","./node_modules/@atcute/identity-resolver/dist/handle/methods/doh-json.d.ts","./node_modules/@atcute/identity-resolver/dist/handle/methods/well-known.d.ts","./node_modules/@atcute/identity-resolver/dist/handle/methods/xrpc.d.ts","./node_modules/@atcute/identity-resolver/dist/errors.d.ts","./node_modules/@atcute/identity-resolver/dist/index.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/actor/profile.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/feed/reaction.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/feed/star.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/git/refupdate.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/graph/follow.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/knot.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/knot/listkeys.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/knot/member.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/knot/version.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/owner.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/pipeline.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/pipeline/status.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/publickey.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/addsecret.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/archive.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/artifact.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/blob.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/branch.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/branches.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/collaborator.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/compare.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/create.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/delete.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/diff.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/forkstatus.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/forksync.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/getdefaultbranch.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/hiddenref.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/issue.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/issue/comment.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/issue/state.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/issue/state/closed.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/issue/state/open.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/languages.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/listsecrets.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/log.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/merge.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/mergecheck.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/pull.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/pull/comment.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/pull/status.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/pull/status/closed.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/pull/status/merged.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/pull/status/open.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/removesecret.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/setdefaultbranch.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/tags.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/repo/tree.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/spindle.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/spindle/member.d.ts","./node_modules/@atcute/tangled/dist/lexicons/types/sh/tangled/string.d.ts","./node_modules/@atcute/tangled/dist/lexicons/index.d.ts","./node_modules/@atcute/tangled/dist/index.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/defs.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/admin/defs.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/admin/deleteaccount.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/admin/disableaccountinvites.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/admin/disableinvitecodes.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/admin/enableaccountinvites.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/admin/getaccountinfo.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/admin/getaccountinfos.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/admin/getinvitecodes.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/repo/strongref.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/admin/getsubjectstatus.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/admin/searchaccounts.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/admin/sendemail.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/admin/updateaccountemail.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/admin/updateaccounthandle.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/admin/updateaccountpassword.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/admin/updateaccountsigningkey.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/admin/updatesubjectstatus.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/identity/defs.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/identity/getrecommendeddidcredentials.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/identity/refreshidentity.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/identity/requestplcoperationsignature.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/identity/resolvedid.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/identity/resolvehandle.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/identity/resolveidentity.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/identity/signplcoperation.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/identity/submitplcoperation.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/identity/updatehandle.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/label/defs.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/label/querylabels.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/label/subscribelabels.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/lexicon/schema.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/moderation/defs.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/moderation/createreport.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/repo/defs.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/repo/applywrites.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/repo/createrecord.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/repo/deleterecord.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/repo/describerepo.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/repo/getrecord.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/repo/importrepo.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/repo/listmissingblobs.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/repo/listrecords.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/repo/putrecord.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/repo/uploadblob.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/activateaccount.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/checkaccountstatus.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/confirmemail.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/createaccount.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/createapppassword.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/createinvitecode.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/createinvitecodes.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/createsession.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/deactivateaccount.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/deleteaccount.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/deletesession.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/describeserver.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/getaccountinvitecodes.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/getserviceauth.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/getsession.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/listapppasswords.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/refreshsession.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/requestaccountdelete.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/requestemailconfirmation.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/requestemailupdate.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/requestpasswordreset.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/reservesigningkey.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/resetpassword.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/revokeapppassword.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/server/updateemail.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/sync/defs.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/sync/getblob.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/sync/getblocks.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/sync/getcheckout.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/sync/gethead.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/sync/gethoststatus.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/sync/getlatestcommit.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/sync/getrecord.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/sync/getrepo.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/sync/getrepostatus.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/sync/listblobs.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/sync/listhosts.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/sync/listrepos.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/sync/listreposbycollection.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/sync/notifyofupdate.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/sync/requestcrawl.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/sync/subscriberepos.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/temp/addreservedhandle.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/temp/checkhandleavailability.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/temp/checksignupqueue.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/temp/dereferencescope.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/temp/fetchlabels.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/temp/requestphoneverification.d.ts","./node_modules/@atcute/atproto/dist/lexicons/types/com/atproto/temp/revokeaccountcredentials.d.ts","./node_modules/@atcute/atproto/dist/lexicons/index.d.ts","./node_modules/@atcute/atproto/dist/index.d.ts","./lib/utils/atproto-client.ts","./lib/utils/cache.ts","./lib/providers/atprotoprovider.tsx","./lib/hooks/usedidresolution.ts","./lib/hooks/usepdsendpoint.ts","./lib/hooks/useatprotorecord.ts","./lib/core/atprotorecord.tsx","./lib/components/blueskyicon.tsx","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/embed/external.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/postgate.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/threadgate.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/embed/defs.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/embed/images.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/embed/video.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/embed/recordwithmedia.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/labeler/defs.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/embed/record.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/richtext/facet.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/defs.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/defs.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/notification/defs.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/actor/defs.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/actor/getpreferences.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/actor/getprofile.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/actor/getprofiles.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/actor/getsuggestions.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/actor/profile.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/actor/putpreferences.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/actor/searchactors.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/actor/searchactorstypeahead.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/actor/status.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/bookmark/createbookmark.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/bookmark/defs.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/bookmark/deletebookmark.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/bookmark/getbookmarks.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/describefeedgenerator.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/generator.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/getactorfeeds.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/getactorlikes.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/getauthorfeed.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/getfeed.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/getfeedgenerator.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/getfeedgenerators.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/getfeedskeleton.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/getlikes.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/getlistfeed.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/getpostthread.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/getposts.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/getquotes.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/getrepostedby.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/getsuggestedfeeds.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/gettimeline.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/like.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/post.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/repost.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/searchposts.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/feed/sendinteractions.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/block.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/follow.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/getactorstarterpacks.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/getblocks.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/getfollowers.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/getfollows.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/getknownfollowers.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/getlist.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/getlistblocks.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/getlistmutes.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/getlists.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/getlistswithmembership.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/getmutes.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/getrelationships.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/getstarterpack.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/getstarterpacks.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/getstarterpackswithmembership.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/getsuggestedfollowsbyactor.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/list.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/listblock.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/listitem.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/muteactor.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/muteactorlist.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/mutethread.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/searchstarterpacks.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/starterpack.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/unmuteactor.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/unmuteactorlist.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/unmutethread.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/graph/verification.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/labeler/getservices.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/labeler/service.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/notification/declaration.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/notification/getpreferences.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/notification/getunreadcount.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/notification/listactivitysubscriptions.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/notification/listnotifications.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/notification/putactivitysubscription.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/notification/putpreferences.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/notification/putpreferencesv2.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/notification/registerpush.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/notification/unregisterpush.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/notification/updateseen.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/unspecced/defs.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/unspecced/getageassurancestate.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/unspecced/getconfig.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/unspecced/getpopularfeedgenerators.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/unspecced/getpostthreadotherv2.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/unspecced/getpostthreadv2.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/unspecced/getsuggestedfeeds.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/unspecced/getsuggestedfeedsskeleton.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/unspecced/getsuggestedstarterpacks.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/unspecced/getsuggestedstarterpacksskeleton.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/unspecced/getsuggestedusers.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/unspecced/getsuggestedusersskeleton.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/unspecced/getsuggestionsskeleton.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/unspecced/gettaggedsuggestions.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/unspecced/gettrendingtopics.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/unspecced/gettrends.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/unspecced/gettrendsskeleton.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/unspecced/initageassurance.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/unspecced/searchactorsskeleton.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/unspecced/searchpostsskeleton.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/unspecced/searchstarterpacksskeleton.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/video/defs.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/video/getjobstatus.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/video/getuploadlimits.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/app/bsky/video/uploadvideo.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/actor/declaration.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/actor/defs.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/actor/deleteaccount.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/actor/exportaccountdata.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/convo/acceptconvo.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/convo/defs.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/convo/addreaction.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/convo/deletemessageforself.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/convo/getconvo.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/convo/getconvoavailability.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/convo/getconvoformembers.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/convo/getlog.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/convo/getmessages.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/convo/leaveconvo.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/convo/listconvos.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/convo/muteconvo.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/convo/removereaction.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/convo/sendmessage.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/convo/sendmessagebatch.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/convo/unmuteconvo.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/convo/updateallread.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/convo/updateread.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/moderation/getactormetadata.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/moderation/getmessagecontext.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/types/chat/bsky/moderation/updateactoraccess.d.ts","./node_modules/@atcute/bluesky/dist/lexicons/index.d.ts","./node_modules/@atcute/bluesky/dist/utilities/embeds.d.ts","./node_modules/@atcute/bluesky/dist/utilities/list.d.ts","./node_modules/@atcute/bluesky/dist/utilities/profile.d.ts","./node_modules/@atcute/bluesky/dist/utilities/starterpack.d.ts","./node_modules/@atcute/bluesky/dist/index.d.ts","./lib/types/bluesky.ts","./lib/hooks/usecolorscheme.ts","./lib/utils/at-uri.ts","./lib/hooks/useblob.ts","./lib/renderers/blueskypostrenderer.tsx","./lib/renderers/blueskyprofilerenderer.tsx","./lib/utils/profile.ts","./lib/components/blueskyprofile.tsx","./lib/components/blueskypost.tsx","./lib/hooks/usepaginatedrecords.ts","./lib/components/blueskypostlist.tsx","./lib/components/blueskyquotepost.tsx","./lib/components/colorschemetoggle.tsx","./lib/types/leaflet.ts","./lib/renderers/leafletdocumentrenderer.tsx","./lib/components/leafletdocument.tsx","./lib/renderers/tangledstringrenderer.tsx","./lib/components/tangledstring.tsx","./lib/hooks/useblueskyprofile.ts","./lib/hooks/uselatestrecord.ts","./lib/index.ts","./node_modules/@types/argparse/index.d.ts","./node_modules/@babel/types/lib/index.d.ts","./node_modules/@types/babel__generator/index.d.ts","./node_modules/@babel/parser/typings/babel-parser.d.ts","./node_modules/@types/babel__template/index.d.ts","./node_modules/@types/babel__traverse/index.d.ts","./node_modules/@types/babel__core/index.d.ts","./node_modules/@types/estree/index.d.ts","./node_modules/@types/json-schema/index.d.ts","./node_modules/@types/node/compatibility/iterators.d.ts","./node_modules/@types/node/globals.typedarray.d.ts","./node_modules/@types/node/buffer.buffer.d.ts","./node_modules/@types/node/globals.d.ts","./node_modules/@types/node/web-globals/abortcontroller.d.ts","./node_modules/@types/node/web-globals/crypto.d.ts","./node_modules/@types/node/web-globals/domexception.d.ts","./node_modules/@types/node/web-globals/events.d.ts","./node_modules/undici-types/utility.d.ts","./node_modules/undici-types/header.d.ts","./node_modules/undici-types/readable.d.ts","./node_modules/undici-types/fetch.d.ts","./node_modules/undici-types/formdata.d.ts","./node_modules/undici-types/connector.d.ts","./node_modules/undici-types/client-stats.d.ts","./node_modules/undici-types/client.d.ts","./node_modules/undici-types/errors.d.ts","./node_modules/undici-types/dispatcher.d.ts","./node_modules/undici-types/global-dispatcher.d.ts","./node_modules/undici-types/global-origin.d.ts","./node_modules/undici-types/pool-stats.d.ts","./node_modules/undici-types/pool.d.ts","./node_modules/undici-types/handlers.d.ts","./node_modules/undici-types/balanced-pool.d.ts","./node_modules/undici-types/h2c-client.d.ts","./node_modules/undici-types/agent.d.ts","./node_modules/undici-types/mock-interceptor.d.ts","./node_modules/undici-types/mock-call-history.d.ts","./node_modules/undici-types/mock-agent.d.ts","./node_modules/undici-types/mock-client.d.ts","./node_modules/undici-types/mock-pool.d.ts","./node_modules/undici-types/snapshot-agent.d.ts","./node_modules/undici-types/mock-errors.d.ts","./node_modules/undici-types/proxy-agent.d.ts","./node_modules/undici-types/env-http-proxy-agent.d.ts","./node_modules/undici-types/retry-handler.d.ts","./node_modules/undici-types/retry-agent.d.ts","./node_modules/undici-types/api.d.ts","./node_modules/undici-types/cache-interceptor.d.ts","./node_modules/undici-types/interceptors.d.ts","./node_modules/undici-types/util.d.ts","./node_modules/undici-types/cookies.d.ts","./node_modules/undici-types/patch.d.ts","./node_modules/undici-types/websocket.d.ts","./node_modules/undici-types/eventsource.d.ts","./node_modules/undici-types/diagnostics-channel.d.ts","./node_modules/undici-types/content-type.d.ts","./node_modules/undici-types/cache.d.ts","./node_modules/undici-types/index.d.ts","./node_modules/@types/node/web-globals/fetch.d.ts","./node_modules/@types/node/web-globals/navigator.d.ts","./node_modules/@types/node/web-globals/storage.d.ts","./node_modules/@types/node/web-globals/streams.d.ts","./node_modules/@types/node/assert.d.ts","./node_modules/@types/node/assert/strict.d.ts","./node_modules/@types/node/async_hooks.d.ts","./node_modules/@types/node/buffer.d.ts","./node_modules/@types/node/child_process.d.ts","./node_modules/@types/node/cluster.d.ts","./node_modules/@types/node/console.d.ts","./node_modules/@types/node/constants.d.ts","./node_modules/@types/node/crypto.d.ts","./node_modules/@types/node/dgram.d.ts","./node_modules/@types/node/diagnostics_channel.d.ts","./node_modules/@types/node/dns.d.ts","./node_modules/@types/node/dns/promises.d.ts","./node_modules/@types/node/domain.d.ts","./node_modules/@types/node/events.d.ts","./node_modules/@types/node/fs.d.ts","./node_modules/@types/node/fs/promises.d.ts","./node_modules/@types/node/http.d.ts","./node_modules/@types/node/http2.d.ts","./node_modules/@types/node/https.d.ts","./node_modules/@types/node/inspector.d.ts","./node_modules/@types/node/inspector.generated.d.ts","./node_modules/@types/node/module.d.ts","./node_modules/@types/node/net.d.ts","./node_modules/@types/node/os.d.ts","./node_modules/@types/node/path.d.ts","./node_modules/@types/node/perf_hooks.d.ts","./node_modules/@types/node/process.d.ts","./node_modules/@types/node/punycode.d.ts","./node_modules/@types/node/querystring.d.ts","./node_modules/@types/node/readline.d.ts","./node_modules/@types/node/readline/promises.d.ts","./node_modules/@types/node/repl.d.ts","./node_modules/@types/node/sea.d.ts","./node_modules/@types/node/sqlite.d.ts","./node_modules/@types/node/stream.d.ts","./node_modules/@types/node/stream/promises.d.ts","./node_modules/@types/node/stream/consumers.d.ts","./node_modules/@types/node/stream/web.d.ts","./node_modules/@types/node/string_decoder.d.ts","./node_modules/@types/node/test.d.ts","./node_modules/@types/node/timers.d.ts","./node_modules/@types/node/timers/promises.d.ts","./node_modules/@types/node/tls.d.ts","./node_modules/@types/node/trace_events.d.ts","./node_modules/@types/node/tty.d.ts","./node_modules/@types/node/url.d.ts","./node_modules/@types/node/util.d.ts","./node_modules/@types/node/v8.d.ts","./node_modules/@types/node/vm.d.ts","./node_modules/@types/node/wasi.d.ts","./node_modules/@types/node/worker_threads.d.ts","./node_modules/@types/node/zlib.d.ts","./node_modules/@types/node/index.d.ts","./node_modules/@types/react-dom/index.d.ts"],"fileIdsList":[[52,53,438,492,509,510],[52,53,253,255,256,406,408,409,410,412,413,438,492,509,510],[52,53,253,257,406,407,408,415,438,492,509,510],[52,53,253,256,406,408,409,411,412,438,492,509,510],[52,53,408,410,414,438,492,509,510],[52,53,407,438,492,509,510],[52,53,255,256,407,408,419,420,438,492,509,510],[52,53,256,422,438,492,509,510],[52,53,255,438,492,509,510],[52,53,250,253,254,438,492,509,510],[52,53,252,253,254,438,492,509,510],[52,53,250,254,438,492,509,510],[52,53,252,438,492,509,510],[53,250,252,253,254,255,256,257,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,438,492,509,510],[52,53,250,251,438,492,509,510],[52,53,253,257,406,407,408,409,438,492,509,510],[52,53,257,406,407,438,492,509,510],[52,53,253,407,408,409,414,419,438,492,509,510],[52,53,153,407,438,492,509,510],[53,405,438,492,509,510],[53,438,492,509,510],[53,71,79,88,99,153,249,438,492,509,510],[53,88,250,438,492,509,510],[53,406,438,492,509,510],[248,438,492,509,510],[154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,438,492,509,510],[73,154,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,155,156,157,158,159,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,155,156,157,158,159,160,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,154,156,157,158,159,160,161,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,155,156,157,158,159,160,161,162,163,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,155,156,157,158,159,160,161,162,164,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,172,173,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,172,173,174,175,176,177,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,182,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,182,183,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,186,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,188,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,188,189,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,188,189,190,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,188,189,190,191,192,193,194,195,196,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,154,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,182,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[400,401,402,403,404,438,492,509,510],[258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,163,182,258,259,260,269,270,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,271,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,271,272,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,271,272,273,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,271,272,273,274,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,182,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,271,272,273,274,275,276,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,271,272,273,274,275,276,277,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,271,272,273,274,275,276,277,278,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,258,259,260,272,273,274,275,276,277,278,279,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,163,268,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,282,283,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,261,438,492,509,510],[73,163,182,258,262,263,264,265,268,269,271,438,492,509,510],[73,258,262,263,266,438,492,509,510],[73,182,258,262,263,264,266,267,269,271,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,182,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,267,272,273,274,275,276,277,278,279,280,281,283,284,285,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,268,272,273,274,275,276,277,278,279,280,281,283,284,285,286,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,268,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,268,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,268,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,268,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,268,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,268,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,271,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,268,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,268,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,268,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,268,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,271,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,268,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,268,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,182,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,258,259,260,262,263,264,266,267,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,268,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,268,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,182,267,268,271,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,269,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,271,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,271,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,271,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,271,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,269,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,269,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,269,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,269,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,269,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,271,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,269,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,269,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,269,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,269,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,271,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,182,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,267,269,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,269,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,267,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,182,186,271,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,265,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,265,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,270,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,271,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,182,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,271,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,270,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,270,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,268,271,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,268,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,268,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,268,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,269,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,271,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,182,271,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,380,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,266,267,376,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,380,381,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,380,381,382,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,380,381,382,383,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,380,381,382,383,384,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,380,381,382,383,384,385,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,380,381,382,383,384,385,386,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,380,381,382,383,384,385,386,387,388,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,380,381,382,383,384,385,386,387,388,389,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,380,381,382,383,384,385,386,387,388,389,390,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,438,492,509,510],[74,264,266,268,303,438,492,509,510],[400,438,492,509,510],[73,74,75,76,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[74,76,438,492,509,510],[438,492,509,510],[76,77,78,438,492,509,510],[71,88,89,438,492,509,510],[71,438,492,509,510],[71,89,438,492,509,510],[89,90,91,92,93,94,95,96,97,98,438,492,509,510],[71,88,438,492,509,510],[81,82,83,84,85,86,87,438,492,509,510],[74,438,492,509,510],[80,81,438,492,509,510],[74,81,438,492,509,510],[54,55,56,57,58,60,61,62,63,64,65,66,67,68,69,73,438,492,509,510],[61,66,438,492,509,510],[61,438,492,509,510],[66,67,68,438,492,509,510],[54,55,438,492,509,510],[54,56,57,58,59,438,492,509,510],[54,55,56,57,58,60,61,62,63,64,65,438,492,509,510],[69,70,71,72,438,492,509,510],[152,438,492,509,510],[100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,438,492,509,510],[73,75,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,134,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,135,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,136,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,137,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,138,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,139,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,140,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,141,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,145,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,146,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,147,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,148,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,149,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,150,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,151,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[73,75,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,134,135,136,137,138,139,140,141,145,146,147,148,149,150,156,157,158,159,160,161,162,164,165,166,167,168,169,170,171,173,174,175,176,177,178,179,180,181,183,184,185,187,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,259,260,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,372,373,374,375,377,378,379,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,438,492,509,510],[428,438,492,509,510],[428,429,430,431,432,438,492,509,510],[428,430,438,492,509,510],[438,489,490,492,509,510],[438,491,492,509,510],[492,509,510],[438,492,497,509,510,527],[438,492,493,498,503,509,510,512,524,535],[438,492,493,494,503,509,510,512],[438,492,495,509,510,536],[438,492,496,497,504,509,510,513],[438,492,497,509,510,524,532],[438,492,498,500,503,509,510,512],[438,491,492,499,509,510],[438,492,500,501,509,510],[438,492,502,503,509,510],[438,491,492,503,509,510],[438,492,503,504,505,509,510,524,535],[438,492,503,504,505,509,510,519,524,527],[438,484,492,500,503,506,509,510,512,524,535],[438,492,503,504,506,507,509,510,512,524,532,535],[438,492,506,508,509,510,524,532,535],[436,437,438,439,440,441,442,443,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541],[438,492,503,509,510],[438,492,509,510,511,535],[438,492,500,503,509,510,512,524],[438,492,509,510,513],[438,492,509,510,514],[438,491,492,509,510,515],[438,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541],[438,492,509,510,517],[438,492,509,510,518],[438,492,503,509,510,519,520],[438,492,509,510,519,521,536,538],[438,492,503,509,510,524,525,527],[438,492,509,510,526,527],[438,492,509,510,524,525],[438,492,509,510,527],[438,492,509,510,528],[438,489,492,509,510,524,529],[438,492,503,509,510,530,531],[438,492,509,510,530,531],[438,492,497,509,510,512,524,532],[438,492,509,510,533],[438,492,509,510,512,534],[438,492,506,509,510,518,535],[438,492,497,509,510,536],[438,492,509,510,524,537],[438,492,509,510,511,538],[438,492,509,510,539],[438,492,497,509,510],[438,484,492,509,510],[438,492,509,510,540],[438,484,492,503,505,509,510,515,524,527,535,537,538,540],[438,492,509,510,524,541],[52,438,492,509,510],[50,51,438,492,509,510],[438,450,453,456,457,492,509,510,535],[438,453,492,509,510,524,535],[438,453,457,492,509,510,535],[438,492,509,510,524],[438,447,492,509,510],[438,451,492,509,510],[438,449,450,453,492,509,510,535],[438,492,509,510,512,532],[438,492,509,510,542],[438,447,492,509,510,542],[438,449,453,492,509,510,512,535],[438,444,445,446,448,452,492,503,509,510,524,535],[438,453,461,469,492,509,510],[438,445,451,492,509,510],[438,453,478,479,492,509,510],[438,445,448,453,492,509,510,527,535,542],[438,453,492,509,510],[438,449,453,492,509,510,535],[438,444,492,509,510],[438,447,448,449,451,452,453,454,455,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,479,480,481,482,483,492,509,510],[438,453,471,474,492,500,509,510],[438,453,461,462,463,492,509,510],[438,451,453,462,464,492,509,510],[438,452,492,509,510],[438,445,447,453,492,509,510],[438,453,457,462,464,492,509,510],[438,457,492,509,510],[438,451,453,456,492,509,510,535],[438,445,449,453,461,492,509,510],[438,453,471,492,509,510],[438,464,492,509,510],[438,447,453,478,492,509,510,527,540,542]],"fileInfos":[{"version":"c430d44666289dae81f30fa7b2edebf186ecc91a2d4c71266ea6ae76388792e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"080941d9f9ff9307f7e27a83bcd888b7c8270716c39af943532438932ec1d0b9","affectsGlobalScope":true,"impliedFormat":1},{"version":"2e80ee7a49e8ac312cc11b77f1475804bee36b3b2bc896bead8b6e1266befb43","affectsGlobalScope":true,"impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fb0f136d372979348d59b3f5020b4cdb81b5504192b1cacff5d1fbba29378aa1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"a680117f487a4d2f30ea46f1b4b7f58bef1480456e18ba53ee85c2746eeca012","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"51ad4c928303041605b4d7ae32e0c1ee387d43a24cd6f1ebf4a2699e1076d4fa","affectsGlobalScope":true,"impliedFormat":1},{"version":"196cb558a13d4533a5163286f30b0509ce0210e4b316c56c38d4c0fd2fb38405","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"170d4db14678c68178ee8a3d5a990d5afb759ecb6ec44dbd885c50f6da6204f6","affectsGlobalScope":true,"impliedFormat":1},{"version":"8a8eb4ebffd85e589a1cc7c178e291626c359543403d58c9cd22b81fab5b1fb9","impliedFormat":1},{"version":"0ff1b165090b491f5e1407ae680b9a0bc3806dc56827ec85f93c57390491e732","impliedFormat":1},{"version":"42c169fb8c2d42f4f668c624a9a11e719d5d07dacbebb63cbcf7ef365b0a75b3","impliedFormat":1},{"version":"ea72cc9550b89d2fd7b8ac2ab4a6ad5b179bf897de7859bba0dc7a934bbca734","impliedFormat":99},{"version":"aa45d08c94931e0b7a9a4c418b33ab895aaf240e192839b36866ad84198c062a","impliedFormat":99},{"version":"dbddbfd48c1d54d619891c895f6e8ff16d30717f4a0952e701387e8040d99f85","impliedFormat":99},{"version":"3361e3db8cb33aa91beaf33b3c79c108f2410e6414498e79d2c7da1838fdfc4d","impliedFormat":99},{"version":"4d54ec33bb701c533741e8abc4233d5f378805166d3a5999d234ae189702d93f","impliedFormat":99},{"version":"f1eed69ccd2798f31d0996306c51d648e19e6e09088f9a7f57c3dcb4367cef51","impliedFormat":99},{"version":"da276fcfe4fb73d74245eee5d1dfb7776bd450d77c591f6e03b54d60be5299b4","impliedFormat":99},{"version":"b402b88cf99c4dc208e5fd337e198e9ee703f48b239dbc8d08ec3b6389e5b55b","impliedFormat":99},{"version":"6f99fbd5ea27a199f84fbc41105525d207d8c6838d62babcbe12e5be0c4a0271","impliedFormat":99},{"version":"528939385e62838eb5631e339475ba93c2ce3ba7e3819cacd42d8ba9adfe5025","impliedFormat":99},{"version":"ef7d56a3fff2aa6476c694027c4844905d40ecc7e8b775dd8743dfd8378353fe","impliedFormat":99},{"version":"3894b5833c452b46d1c59f7d58a8c45e55bcc75a0248af65e1c9c9dd88afeac7","impliedFormat":99},{"version":"1ef2ed1e48da7d651f705bc0131d1028725841d4a97652ef0905367360ba3f73","impliedFormat":99},{"version":"47c221ec0b8802eb5887d6a1be6d7a33ddcd10116185a15c36803e0ae1c0539c","impliedFormat":99},{"version":"0d42fe6c9f1fab8c308ab1ec0ec2ad814a1bd2fb685e2f12cabc0c7732c089b9","impliedFormat":99},{"version":"74967284243720aad05a852617f2891ae384d7a6470c824169a351ad31cab9fb","impliedFormat":99},{"version":"76af14c3cce62da183aaf30375e3a4613109d16c7f16d30702f16d625a95e62c","impliedFormat":99},{"version":"19bc69921209ad7269f886c69e5f812499e133ce318e1aa5d53ac82427c1a477","impliedFormat":99},{"version":"31c17a52735cb1f6cc5a4c452857f568341f95424f07fdb5ee2fbcd6a4a4c094","impliedFormat":99},{"version":"06b419067158787fe33af288531a1df891b452a11e485896bded780b2ef70732","impliedFormat":99},{"version":"44c976b666ef022c74dc1405abb2b167346f9b8ebed3ab4bd9464711c8caa1f5","impliedFormat":99},{"version":"8e52008b516a7a7301f9d43884dc899019695eab471312b72be8a72f89850327","impliedFormat":99},{"version":"f47d865499c8b58d931d7f16e4432c69a3501cb324ead037804e8f292ff195a3","impliedFormat":99},{"version":"1e2f699820214b98d8d16c57137c7adb04b13f3ac573b4f0bbe7b7a601d09495","impliedFormat":99},{"version":"3fc902025baa4cbc0b4648466ac6be6117dc4b0e5b56d245d959839e58fdca8f","impliedFormat":99},{"version":"8ca7d6aee90a5a1d40d356c70c8d5b0ca55ab31a3d17ba73ffb51604674c48f4","impliedFormat":99},{"version":"8de5552b84830fba2143c18d43ebfc3c1289c67402c51a378c32daa7ff7adf32","impliedFormat":99},{"version":"651b59286248bd10267c630f728172866ae427f4036372bcd63f1502532454f8","impliedFormat":99},{"version":"1be150449268e28edc1a1d31acb2b9fa030aee87897a41856d50ddccc124ea53","impliedFormat":99},{"version":"ae0bff9b2245fc399295d0572519a2833ff1a47550b7fdddf96e648eca5271ea","impliedFormat":99},{"version":"0b903757cdc9fe17029ff023c454ae06941499fbf9ae0f733c5e7314555797aa","impliedFormat":99},{"version":"f7ff68ca4ababc2bea9fe21a476be0f6096b8f9f54d34f3408f921850b770e24","impliedFormat":99},{"version":"fa689046e96fc6bd92d2f6edcdb9c0c45efedcfe23443ae1fd4a470bf6e9eda3","impliedFormat":99},{"version":"cb54ec232cad4e0c94cebfd4f560de0907e65c1b55b62a7c1063ab73fe2b014d","impliedFormat":99},{"version":"39f0d3b66804b002c2f462c9ee61bfca709b607559893cccb4ade202f01028d6","impliedFormat":99},{"version":"1f0316a5da01034b17aed99fdd5ec8fe805bb65c5181587c8da353e7c1c31466","impliedFormat":99},{"version":"56442d4cc6dbee39651e056fa1497720913f1f801791b84e50e892cfbe078bd4","impliedFormat":99},{"version":"03cd861598cd715ca2bac8148c04a5f0ed2d21e90bf8db13de771be632f28c66","impliedFormat":99},{"version":"bd1578e4ca78d8de0d3dc05f95d147e45b4dfda47186ce874b3c0d7539e2098f","impliedFormat":99},{"version":"735c117db157cdfd07b4a18b777995e5ce23e535f49cbb12f5fd2c9111c5db18","impliedFormat":99},{"version":"303e57dc66fb6f7e6a79344e5135d48c73ed024cb311d2babf4df5b89fbcf3c8","impliedFormat":99},{"version":"d334f6d54e3907bf5a76f95119c4cc3f91220e96eb113487062d416c3bb70667","impliedFormat":99},{"version":"41178e3f5b546481e0a44eb7aaee78751843dffd525360d953550e8704880445","impliedFormat":99},{"version":"6d0cffb06c980b1ded7ed62302284696b2e9c88ed2608a36acee3ae30cebf88c","impliedFormat":99},{"version":"c57d47d923b6851e8880b395d0935d0b3bccc5c3691e7ce33abb247195b262ba","impliedFormat":99},{"version":"aedbbff1a84bb4cc113b3aa603afd19ea5a53e505744f971b715c412dae0505d","impliedFormat":99},{"version":"e04ad05711a15421294f32c07c87f23a99e792e44a2109700cec6e031038e5a8","impliedFormat":99},{"version":"05b4b78a0fe3f591b9f46700396ec760bf4785c238f8a27cbf78037357615994","impliedFormat":99},{"version":"54469d80797325cac80ddf053a12afe121953b9f327a3865925c1ea5fedc1e04","impliedFormat":99},{"version":"8ac43b3a5564c1b963aa0598ce3fe1d2b5673f220a2d0900a05cc03a2098433c","impliedFormat":99},{"version":"9555fc148c875680bb94cf7afd8c96cb6bd39575833f4d57755a3b8e3639937e","impliedFormat":99},{"version":"2dd5d9fe6995942adf82fff82e624e5aac2965a605587cc777c852981670f7c7","impliedFormat":99},{"version":"09ded16b94109529ea27304a7292084332eea0fec7960361650feaa57f738763","impliedFormat":99},{"version":"89bfc04207450b25e880200f4b1548391b539fc60bc2f2945fc0edfb23e23634","impliedFormat":99},{"version":"7c9600f96f56cb5356fb26046a60d5ea86f4e3a48709d316244395a8ca007029","impliedFormat":99},{"version":"8b10bff76988431e8f68b2a0dbb79df3ee0331753c4fac29b40ab62801f2aa06","impliedFormat":99},{"version":"724ce9a87bbacc89ff4ab317df599f77a55ee6545d76e056d8b36bb55f24c58b","impliedFormat":99},{"version":"79ddbd060c4878d83b491a4f8469794c8184f59ec9d1b022bc5b14c29215f590","impliedFormat":99},{"version":"c80b21e0bc14336675fe80924a468b9ecbda995c0b4705988f53c38dddf41922","impliedFormat":99},{"version":"aefa7fd02617fd165f8f06e921b8c0d8e60867af6634a622ddd017c158c5a505","impliedFormat":99},{"version":"bab81fad10b35ea3ec3886895b7b2e44716d7c73e009b1b3c6aabcff8dd28b42","impliedFormat":99},{"version":"78c2b0c973739c69dc21745ccb2c8dfaabd0bc97f27675a11eec5ddcb44f04e2","impliedFormat":99},{"version":"8883a6e862b5f07b07fccf8a0100ca73d35a2117fa2656d4368fbe089dc45ad5","impliedFormat":99},{"version":"9262edf59574bb4b69221a2289c08e9d8d9b83f51ac9838191dc43c176e26312","impliedFormat":99},{"version":"8f3e70c49f9abb6115f25ad78fc1d65edaa463f2d6d5a5a1554cc83bae5fb284","impliedFormat":99},{"version":"17aa7e05470aee99f362246e3b2fbccb3833d155b103bc85fcf3cd0166e8385d","impliedFormat":99},{"version":"c47eedce9426b4a330be6cc94f31ab0430557bf3d66b2f6fdaa8bc2a9fe3dc63","impliedFormat":99},{"version":"8fc134de25055444c3f7cf24895245a20009342b7d27fefe046a23f06050775d","impliedFormat":99},{"version":"5f291db565a8a521639a3f6414c1d7484b1692ced3fab25d5f6d9c7622412239","impliedFormat":99},{"version":"9d97d4c094e8fb4a39dc3c9c61a5ab3750df7f640f10d7cc1f0cc95254867a46","impliedFormat":99},{"version":"13b381b958471357ea0e5d55331fe8da40ef6dd444c765620f5ac6ed8604fea5","impliedFormat":99},{"version":"c7b04352ef5338a362cb852b254bcef5fd9f299611830722ca96bef2272a727d","impliedFormat":99},{"version":"5b7cc254748cfad68a29f1708899c3c053ab74088d08ab4a55488eb2a2a6ffc3","impliedFormat":99},{"version":"32d7684d69e6fb0d6b0b9526c81791c866e379d890969248ec033b76014e5ae3","impliedFormat":99},{"version":"3004fd440a0ce893bde0047ded249354f17fc5bf5f0e18cb443ad5875ce624af","impliedFormat":99},{"version":"616bd5a947e0f6c9b3b1115ff93e6bf6bde37f0f8874ad22ce1b94972210ecbb","impliedFormat":99},{"version":"e93070a564ab221196230b074e5316c1780fd97e32d134984662d77686a03da0","impliedFormat":99},{"version":"f14fb34a1756869066dcf0101061dc28a3125165a19033870b99da489aef7b8a","impliedFormat":99},{"version":"d8c6ddb39e8570cfe28b4bff78b60c3b0f8989b18f1cff11b65b3bce72cc8b7b","impliedFormat":99},{"version":"bc676aee1c0487b866e6c4879c44b4022726bd4aabdda10d8a869bfff2fc4fd1","impliedFormat":99},{"version":"94fdd74bb75c869bb49cff84e2cc0d96847e54550d07f190e6aa2f66f48df3cd","impliedFormat":99},{"version":"df87131c4e90121f3735d75f8687fd6593a2cf532f584f1c007929b2a30a5f9b","impliedFormat":99},{"version":"ede4c4fa5909299b5ef08f59bdca60f233b267dbd1cba1dad89977aca2d2a832","impliedFormat":99},{"version":"64e5054bb3a621b29863c2af6682d288c14635b2d14ffb5b446a17a63b88dd87","impliedFormat":99},{"version":"bb1fb4df5b57dd20edc2b411f0b0149f15ab5a106cdc8a953b4209f645034785","impliedFormat":99},{"version":"060c85a4fc9199e1f44449c4496e50da8803b007aa3fdd20f2285978060c33c0","impliedFormat":99},{"version":"0acc2626aeba6dec96b73ec578bc3bc823af3fce72c12c5309ac1863604c076b","impliedFormat":99},{"version":"9a761443a08143aab9c4de9693e72f6d8d23247186eb8889bcd10393dc3532c0","impliedFormat":99},{"version":"da1417971dd43589cf2f64e5f39da372a9413bbdaf4fc535b0a3bb132b1657e3","impliedFormat":99},{"version":"8889a09c6af3130c89f3447054fa5460754471e0a1f98a527e71fdfde899cb2f","impliedFormat":99},{"version":"ba77a7192b018f6e461de533baed7b4c7e574d708bb65217c42201c2ed10abfb","impliedFormat":99},{"version":"78ac78b6372510eeba34d59c12baf2f2d3e711b466161dce30d73c935340a8f7","impliedFormat":99},{"version":"a8d4f94ba30bf367db014cbef8d6ece4cb664e69aeba758567acb8c02b0bfe2c","impliedFormat":99},{"version":"8f489b6a9e3d21271875f468482bc0418341e23a0688734c3ee7e6b9ff74d7c4","impliedFormat":99},{"version":"787633e9a13f49fe7403439b33388a99637c899236a6cfbf381a063cdbe92542","impliedFormat":99},{"version":"e78023dc028d670a73c72661acbed753764a505e2f464d9d7e118046508c26bb","impliedFormat":99},{"version":"b0486c6fe4f9e68f2105cabed1c388aaf94c06774305d712013fdb5043e46bb7","impliedFormat":99},{"version":"b617febcd2b87748a5896415458836838cc7a047c9ba3c1f93e145ba972117bc","impliedFormat":99},{"version":"c2ed7a65f90e182168b8946ec12ff5aec58c10e9927b04745875843c0568846f","impliedFormat":99},{"version":"e4813e26203d7c6caee2675461cb8694d0a5a2a692fe955b3becdffb1b229726","impliedFormat":99},{"version":"90740a4740eb94a7cfa4c346de4ce38329d161423444f13d86153ad503571cc8","impliedFormat":99},{"version":"f419f04277f873a6c9cddb78465d66a7fc89453768283bc66610f4d563c1fa16","impliedFormat":99},{"version":"85c11e5e250abb4a591509a61e9db2202e7a186cadbd4184d77357f6d768ed1d","impliedFormat":99},{"version":"5fe57966bc656055ea2e4c1657dcc16edc32a08ef87dc30c09671004bdd4cc14","impliedFormat":99},{"version":"ead716385d47a7d5ee147bd5a7fdc0d156c989b4c8806a76f220649c6accde95","impliedFormat":99},{"version":"bc16ae537239eb39d5020afb0958f401befba9d0aa17bb8f895984c6c688569f","impliedFormat":99},{"version":"e551cfaaa5020ea281dbe01991d644059e60cb22b1dcc9634192db9238542723","impliedFormat":99},{"version":"21fc8b8d6387a8a5cc9e62c31fee3c8da8249fb3bc4a8ba79c5092057c892f7d","impliedFormat":99},{"version":"19082f3df1f25f7fb304a911d1a153c9391f464e3001080a524c995e4028a3c4","impliedFormat":99},{"version":"e0f6aafed1acaba5854688e6fdaf8d124383a9282c111b41e22c63f3eb3634ce","impliedFormat":99},{"version":"6562b25cdd9cf562a6d9c614d6294a5b4a5d53013a337b684198672aaa1d61e7","impliedFormat":99},{"version":"3a99f401d0459a24124f6510c9fd84c3ddc94cc9dda88bc092b2c328a2316f10","impliedFormat":99},{"version":"25f8badc9dcd1b4ed1b670442a5cb3bce3855aa2273600123ca82f7105cbd05f","impliedFormat":99},{"version":"df348ecd79b09037176daee7995ddd749a1862a11ed6ac4b0c8a3e7a27cfad27","impliedFormat":99},{"version":"36b1f70dafde83b308cf0d9605fe43900cd340320a5943c79085e39b7ce9c344","impliedFormat":99},{"version":"d5631a56aeb2279698572bf985113de7e1deee43c56cd9dd85aa2be1a41bb998","impliedFormat":99},{"version":"108a85619ed468d15c2f5ea49aa19be365c18a123d2c096cdb682533cafddee5","impliedFormat":99},{"version":"e8e65217abc06cbbd6f5d331cc2fecc278491350423f03ac47aec6978456716b","impliedFormat":99},{"version":"0ae17e04bf71b5eaa46a509bccf6d58cf793a33e39c27077820fb010d4f9521a","impliedFormat":99},{"version":"60d25f66f4b6ef80e0f66f3b2ffbdc88b9ee98d925838d5964fccaa792bb7bc6","impliedFormat":99},{"version":"fce7a2dfbc5f0e8cc50b843e3b4dc606a98832cd6d4a5ebe6ddd054a92dc2597","impliedFormat":99},{"version":"c30274fdea2366b5a293415a6a09124c85b42cc6c02b8d0fc72af5a05351f55e","impliedFormat":99},{"version":"5dd427cc3c26d8e97c7dc0b287e06297717f7a148829fb7fc5875e93bf40956c","impliedFormat":99},{"version":"3abfe64fea01a095950c9f1782ca2ef01ae5391fe5b7fe6443222e5a6adc5d08","impliedFormat":99},{"version":"17a168032c270ec761481e277ac16efeac6530b01870720c17ea6649c9db518b","impliedFormat":99},{"version":"b9e54097ce2e07b1911e42f1c578d9304ca3e2c824f989759bc2199d54e4db0a","impliedFormat":99},{"version":"52256083681cca90fcbf3796937308d94e1c8e3ced04a7974b49ec4209f2ab4f","impliedFormat":99},{"version":"7086e03c6bbd58177835da26104c3124e985afbd9a91b3a148e0cb88fbadcbf0","impliedFormat":99},{"version":"d46dc9978eefe051bc8f6679dc6b6a8be7594247effd2563ac488afee31ce9c7","impliedFormat":99},{"version":"2baba9d417f5388ecf1f2b1a9a58a4b6d4ed7df15509d60de9d7caf1f0043ba1","impliedFormat":99},{"version":"fa412c9f26d7be8ccbbd56ab3f1fad78eb9cf87af63fd8c6fb29dd0450b47622","impliedFormat":99},{"version":"4da7dcbb288a72cb7488728930efa47e46fb3dc042f25aa7d50468f0949bd1a0","impliedFormat":99},{"version":"b0b15e47e8d7e2875b28284ea08678baf6f4dcd420241046fc91743c905d0947","impliedFormat":99},{"version":"7eef51f067c640ef085973e8e13608a0b91c912297514e3264fa6596f328c9fe","impliedFormat":99},{"version":"4afc590f38f8051eec35231e6946ecf2151d7a23ad4e138047b01c800d94d9d0","impliedFormat":99},{"version":"4c42c37e1f02b327024ecb1edf1b5a12e4d45092bc51b405985a791ce32598e0","impliedFormat":99},{"version":"8adbcb728b2d3bd8282e1a657a45f6f9103a7eb43f6fbe36c554bfef17df9656","impliedFormat":99},{"version":"ae061bc7af2f9ea15a742b07e471c27fc4d82e2b940509f9e7da3f129595e03e","impliedFormat":99},{"version":"d15f78dca6c2afbdd2596cb17983fc60a79d95dc0142408d224d671f8b6564dc","impliedFormat":99},{"version":"2307f448951cae8a6b9bf7b09c114369e42d590c53fb99c99fb1cc34ead0f0dc","impliedFormat":99},{"version":"71ceec981852d2a8b0fb281799199344a6ec90aa55e13302916f38b48debd10a","impliedFormat":99},{"version":"5c943d5009f2f31841d04d8ba9e853a13201a9e81fb96234c90191f00a50a713","impliedFormat":99},{"version":"cf7f50328f9916c083247e28d938b986a9d9fd60ba956a90ce540ff676e3deff","impliedFormat":99},{"version":"9005e5cc014620c428d72c3333d6430f4be9ab113c7c41400ea4babe458907fb","impliedFormat":99},{"version":"5040c1eb043d900faf3cbc181831b7aefda2fa75bc08cac59897baefe2666e43","impliedFormat":99},{"version":"83e5ae91867c4b4d94ef5c43b9652401642b80f3a4b86af579390dc2fa97ed10","impliedFormat":99},{"version":"b87b16115bb301284968c766678ee98ab1c2276f1bc4e437945db172718a22b3","impliedFormat":99},{"version":"ec78470f53dc3905513b87992cae127a1d5b793ea42cd48c8ff809ebf576f19a","impliedFormat":99},{"version":"a22df7d38217bf9917cd51c7df7da7965d6a5f57b56b5e612f48ecb34a693c1e","impliedFormat":99},{"version":"df740e512060283334dc9f4d608bb7ddf9097b6e1613dd2b3145d1455bc4f73d","impliedFormat":99},{"version":"b7eea3116456adebb14baa549db35cd82759bdf2f5b161e8ba12768e634b10e8","impliedFormat":99},{"version":"930612d51e2a0cb1402f15a758d8bd025ee29b4c47a13d038faa3fc8ee16e3ba","impliedFormat":99},{"version":"da4d4b60a3c4a12f155b1ca908ff6500c81262168dd39bf6b7f2a632661beb4a","impliedFormat":99},{"version":"1c7a163091d67b9af010e10f5c43ceccde78320486d2901053b4d5af2b751b2a","impliedFormat":99},{"version":"6fb3541ebbb5e2a930fea38603d4c0cbfb4dfbbb7df8999396a8a90939131ef1","impliedFormat":99},{"version":"545dc958d8101a8e3c9932370a7b6c2f8599df0cd53449114fadd7f59fa9d6f6","impliedFormat":99},{"version":"cc8b39d1f46ad8e39ebbc27d5664594a82625199459a9ddbe54ef17b4239ce24","impliedFormat":99},{"version":"08c3b01490d49ce93d06bcb7593ef9ad02dc2d91cd583eb9cd0f3d2fa75e440a","impliedFormat":99},{"version":"6ba19623201e7dda0bda2eb91bc7d1ee6ed719be167f999564a42ad8535e2f9b","impliedFormat":99},{"version":"482f77de2d4972e66c7c6a3aa53b524e20eca97cdaa3220cd2ab7acd3a7a54f3","impliedFormat":99},{"version":"634708acac0aa7d170f03a37a9d8cf6a9febefad220477649f6ec3e1ac1f7adc","impliedFormat":99},{"version":"89b2f499dba3c24fdb44acef871860328553cc46a4802874e17de01d530056f8","impliedFormat":99},{"version":"0288e5f29c1d2b678afce4d682a7ce94c323b86c479f28a4a33928261a5fe4ef","impliedFormat":99},{"version":"4e0c84783c17101df536fa4018dad2c210ba3a41daca0c1df4957f7e8dbabbaf","impliedFormat":99},{"version":"bf17c4d237818052f7f3bdd00fa2433e5ee151e1dbbaa1700edd2d229bacfb03","impliedFormat":99},{"version":"862052995b61cdf46e9fdf9b83acb076975dcfe2f44e45c07b23ffa70f9dde0a","impliedFormat":99},{"version":"8a85e856fe6d7a45e4acac5406bf440ec274ac46171d08567d38a7ff36796c3b","impliedFormat":99},{"version":"b48976ad99fc88001f7c2757d84a6bcc5e8830f7e95fb3c73d774e7710b51aa0","impliedFormat":99},{"version":"40ec8dd574cfdd80de30ba61a0dda32c83d6b60b783ddd5c9afe21187a8b0353","impliedFormat":99},{"version":"4ef67ffb70b66a188eb391c50965ce59a997e5995a060cb0eb803e7937f80cc1","impliedFormat":99},{"version":"bd3f53621504b6b6fb460130652d71bedc7b48c4fe26e81a62f9976de519700a","impliedFormat":99},{"version":"1a94fffe1807952952587e8d392df98582a90f034abdce57217cdf8409a0a16d","impliedFormat":99},{"version":"b7b4608cddbb582012556d2016b1704bb77c9b320770cbde8b98ebbaccdc6056","impliedFormat":99},{"version":"7ff126c2720906e2edc4917be8a00ff52597dd050a0ba8deb82ae1dfff440432","impliedFormat":99},{"version":"53aaccfcf252817f557afc4e9aa18084dcc90e5c096411b9f60b6b7de4fcc41c","impliedFormat":99},{"version":"a7f0bf6a7172f6c4a33877693190c8dca6b5ca0bf0deb5130bfad368b61e16c8","impliedFormat":99},{"version":"fe428bc5c0d6ce416defb7a7e67fa6a10b182b7ee2c16b42419f9538cac0fe10","impliedFormat":99},{"version":"5f19171239190089286ae47ff6d0c9d6fd2b29342dfd0acf6cc6f66f9d1bb4d5","impliedFormat":99},{"version":"d2a502e2c30b775339bfea8c1d51d3dd5244980a3cd5063ba12227cfe03fef44","impliedFormat":99},{"version":"a64913d689476c4743b020c801672718d1a736ab243907396312b832b65cbdc4","impliedFormat":99},{"version":"2d7bd36015925a348793ebfbc2e2a1fbd390bf335be8b9ec780696ed6dde26d4","impliedFormat":99},{"version":"336e86ff9f1abe22105776c7e757e9580446aac47cf8429ca78e6ce980f284e9","impliedFormat":99},{"version":"1416b07f727c918e532f4134a45e3b07b0a116d9def6d9d347a00c50dc01060e","impliedFormat":99},{"version":"a44330e93e4a7f8759a73736215eef4590b74b3421d955d980ba3db8e6b5a7fe","impliedFormat":99},{"version":"ac84b7a6fdece6cbb0ee141a09b505890c3f11c83446f6304ab9d8e972eee60b","impliedFormat":99},{"version":"97ce0d7c831f1fa7934651c878f1af14090ba5d9ee471db035f465a7dc113202","impliedFormat":99},{"version":"cbcc2f6b5fa06c91e2a35cec35066fd14dacccf185dc8c64c5143381bc2d4b30","impliedFormat":99},{"version":"02bfa3730c6288cac5928a0fb08f01f8c236992b0ef57806c478f0f7bdb6eb83","impliedFormat":99},{"version":"5af40b9066886960f300ad8efd6dd8f77eddeb475903989841cf0385a1edf4c7","impliedFormat":99},{"version":"09d52052be4f3e0f4c8fd5d4954cb215a96e20bf6fade80f95706fbdd5cee318","impliedFormat":99},{"version":"f61822dc28d52652fd897fa846364a0c6e2f9d18c4488c104f4887b4627b3fb4","impliedFormat":99},{"version":"55a4f8c04961c6cb99a6d2c79a375e4ef107339c3ccfabd8d986f2a177dface2","impliedFormat":99},{"version":"a5433e2b1359ac2672f3dd287d58e0733fe778ef7dd71a4f913b01e794104119","impliedFormat":99},{"version":"19d3750d9f8f570936cea4be2a6feac27e1cb88391d7c54e3209f479019c1bb1","impliedFormat":99},{"version":"acc3dd66b849dbe92d07581baef23754c6bd3d4cc453d6d8f5d52e261304a3bc","impliedFormat":99},{"version":"e4813e26203d7c6caee2675461cb8694d0a5a2a692fe955b3becdffb1b229726","impliedFormat":99},{"version":"46ce3f884a6003b711e911505e2d1f5164cf8afb027c45e97c24959b8b6f23cc","signature":"deb5843390e2b62d099236b5831b18ce3f0acc31db078780c942cc78e0cbf798"},{"version":"d135fc23cbc0d02c33b0f8ed2be7df4311515064ffb370e826cd53b0d8622524","signature":"3651678bdeba3e39d96bcde883de468401f51943e3c7dc3220c4b7be5b0b52bb"},{"version":"246bf4998a6cef47739b4976189abe1afda3f566be0c6efdb3771b619e21dbde","signature":"f283ffd4999bb8027d29a0963b5e9796c80d42b774e452f38c95f2fb00747708"},{"version":"981ac80c705c3344e59e7901a57cefc7266812f5f5f99b10f1a85af715d58d3a","signature":"1f009a3450b7fda74839cda2709909e4954d55e56def759d215f937733eaf3f4"},{"version":"2241423b81ee7d79534911c32b9159d9668c21f63ae52d174e185b1decc538f7","signature":"201d60dd52e618046236c6d3fcbc68b5cc0265267c6e3cf680f414666b21ab44"},{"version":"dd12717c74416659bb5bd8a891daf5df0a93fa1de37d3b3e5814b87c14895f40","signature":"cb74476319bef6005353dc35d4cbbe462085eb62cadd2ea31369f74e946f8a28"},{"version":"80581c53a1991543fe881a3d7d4421ad45273d332bdccd39e0d4a2bfc21a4111","signature":"6d959ed0e5411cbc172b7f49650a5c915996433264be0c5c799449e9499e5bdb"},{"version":"959734acd7d29267ec7e15a4975ac091e0e806c65fe3367c19c791412720bd99","signature":"fb151c164a917f6ada3b9783fbee8518a8ea80695189b66920aa777aa76419af"},{"version":"b06d9380eb2fb5c35f16d03445b1963e8fef5647c592642f5d8dfbb11cebc1d0","impliedFormat":99},{"version":"33e160560eddf2de63ec16a76b8c1d91cba0f5906ff2f29819e07521d6382f6c","impliedFormat":99},{"version":"c35a50ae47731c15c54b6f359590d24776fdd74374bc85031afb800212181af0","impliedFormat":99},{"version":"f34a1a6965c0bbfa374873432849ec319413414ec186261e97ea70d5dc4d4654","impliedFormat":99},{"version":"a3f4b311af4127148f5dbb1a1ea80468a20725f10ae78001a8dada6e4a618696","impliedFormat":99},{"version":"790d03a802369d9a8ff78db3ece0cab418ec75a120dd5ab9aaeeb1c534493d3a","impliedFormat":99},{"version":"2aba871159bc6021308c5f1d05d7917e0c896c7436dcc3619038f381859fbd68","impliedFormat":99},{"version":"adaa0d941bbf9d3f11262c3739579aef70fea7af193718f8fd67e10a771fff8b","impliedFormat":99},{"version":"f178ad620e827581f2baf23c9c7fabb77d36ead92c15e149012934a30151dcf3","impliedFormat":99},{"version":"ef73187b0072b9b148b03acb62dd12615d704589772ce88e2e2e1bbf0255c802","impliedFormat":99},{"version":"417f252d9e1048c6b47d8a8a5a8e7ff5e9a4de37d6d3468152f2e8eb35b88c29","impliedFormat":99},{"version":"f3b2ef02288170cb72b7d412a7cc67dfd85dd24c168b78b77554f1ec515b5701","impliedFormat":99},{"version":"590460ef9a2cf9ab9e34504aba42d6daffe4ff7c347ded7bd8d9a989e0920c3b","impliedFormat":99},{"version":"da45f9cde46eaf3ef2d3135b5354bd3739897d72b406e0f0ec1f5455108580a1","impliedFormat":99},{"version":"cdfaab58a31962eb873192959e14bca891669fa0edfd469c9c35babc36e490a3","impliedFormat":99},{"version":"206d171772d21c82353069668d680a40df7489bde0446fb70f378256ad9d33ff","impliedFormat":99},{"version":"b6104978f6a9921d214c58df950900dc2a9319815a843d354881fd1bad7e62f0","impliedFormat":99},{"version":"1202e02184a9fcfafad7333bfac2da836eaff83653845e00c9495d9c82c9f635","impliedFormat":99},{"version":"6899200d51b7d7491d15521da878142c5fe50d711afe22e60e359f6db6c98088","impliedFormat":99},{"version":"c5e79b84695297cc596924039842c2ab7821470f1c97c4b1aa9d6a7f5f2d2e3f","impliedFormat":99},{"version":"630927db336d1990af0f696dec46f8844c44c507e3a72069f50754541dfcdf5b","impliedFormat":99},{"version":"b4e7867fcdc8d3c7a23b45cd2d705d2dc576a7f7a70156b17aadd7e01f334315","impliedFormat":99},{"version":"c89ac8740afdfc27b2166cad337e716fe843eba690167cbec823bd689f613e6b","impliedFormat":99},{"version":"23c280c11bce285e8f022b0009e083a1bdfc3839f348a38df9dde0c3c571820c","impliedFormat":99},{"version":"dd5be7220598df4a07b6281e01170d0dad5fcd74bcd27daad19619b1fdacc6e0","impliedFormat":99},{"version":"c526474a2770a981d08d9f00644e2a390475b0f9910888d426a6b2e6686b77ec","impliedFormat":99},{"version":"d5cd7c1300ee1f45cc7ef5afef746a1a34c701b94958532a88d265a9f0068063","impliedFormat":99},{"version":"a01c5aaacdd5362cda056105f2acea8b8c4699ce28ccfe641399dd0b49239419","impliedFormat":99},{"version":"6ca50db42bff8c322c4a7449cb09545ff575a1c4bd4fe6d32a9adb563f3fac2b","impliedFormat":99},{"version":"2a45ce8c09f2f343ac47fede405b833cd0ccb325f9b313fd2febfff8ccebd8bd","impliedFormat":99},{"version":"c67e3783cb681d6277dec8ada124cea535c8c7f4d99f5d6f0fed69bca38f3807","impliedFormat":99},{"version":"76ff4e5304fd22a8ebe6cb01ca297feaa0dbe14988ff43746345b55ab3504e19","impliedFormat":99},{"version":"361cb330385d846fbabf3d4db59be3655d45d7c76a483a03c71b0082014f4e9d","impliedFormat":99},{"version":"43b526d382577c18840fb6c10030753b82eb60a377c50233959437dc6493b047","impliedFormat":99},{"version":"7529eb5b698818410c1858e22ddd689fc3fb6f86d54af06872e40423574d15ab","impliedFormat":99},{"version":"3ee6957c2293a69d9f7ff232da8425d396e3115e9ba261a3e532d350e2bebdb0","impliedFormat":99},{"version":"6f70230fab4be1aebb2ef95828669b89dda35280965c55ce88aecaf94848f036","impliedFormat":99},{"version":"8d87cfe48ed90323bac6da16f46aff7fa293e32057cee38d14aab11e9f66e4c5","impliedFormat":99},{"version":"eaa88006a1ba314595330bf47f08eb4a468e7764a1060d6e133183aed7babe13","impliedFormat":99},{"version":"0645cd3e93a26c8a7c16595dc63a169d137f6b58bf50cca98449ea23b333475f","impliedFormat":99},{"version":"1586cdd29126d1a54dee78b46eae7b26c7d473bfd7eaa8bbfc5bf2a76946c545","impliedFormat":99},{"version":"accf489fbfb2dac5d38e71b2fe81687fd44d64b21b5631f6084b9acff57b4d48","impliedFormat":99},{"version":"0c5390e201ce2722d720a82c2105e07606576903e599ed3af15fb8e4e45ea2f4","impliedFormat":99},{"version":"b556cdad15c625405519814fac6ef355484a25c1cc9344e6e5dc110d57a8cdff","impliedFormat":99},{"version":"3e810c39b288e419bc933c293cf5703b948b73bbf07050527c9d73f7107c0c4e","impliedFormat":99},{"version":"9278bac0ed6d0d99fcee6f0f217399ec12edc1d10a9b3c0873c7b97a25223384","impliedFormat":99},{"version":"6f3dccb219fdfb3816c02e9a99d959c853c855c7b7beadecd3a3d3b0a374d953","impliedFormat":99},{"version":"2eeaf63552fd9c5d3ab821464d8f4a5db0de7132331acafafce577f58d871a39","impliedFormat":99},{"version":"9025d4254c18b31d9220e4d33dad5035507ee1e863d1858891e56ffe0eb2ff13","impliedFormat":99},{"version":"001a2571401e839a4b68cec0af11c6188f766ebba01cc1e1895027e3d35030b1","impliedFormat":99},{"version":"846715a4679c9be48434e2b6dfcc466588301a733f51ba0ea15e348fc7312528","impliedFormat":99},{"version":"0b77894d2bbddb9024a230e9d00eb9df633c8d190887f92959d9683a81286c39","impliedFormat":99},{"version":"fe438b40de8ec7fb4a1734f8a3c8315aafcc90dcd15512484e7dcafac310e856","impliedFormat":99},{"version":"96d53f66b4fa3ab1ef688b676450895730863e298e62dc6bc051442195aa1a5f","impliedFormat":99},{"version":"877f538909bb2120565ca0c39e93341e5a4a737bc5fda014c5148c3676fec8df","impliedFormat":99},{"version":"fba10fca31d18ed5fafacb21e2ed389ae5b347b552c5b7a69023a563e27fdf5d","impliedFormat":99},{"version":"600beaefece9011d792a4e165db46b9de5563e025e941aebd069b95cb30e7af5","impliedFormat":99},{"version":"bdc387fdccb98bd48da4cd4cbc8f29342586c2f8ac7215396547442c3b0ff8be","impliedFormat":99},{"version":"7ed291bf246832b2745528de9e68b2bd3e2fe7cdf32631665a326740c3905836","impliedFormat":99},{"version":"e61bc77843da1980c2b6851df589e730bbbdada172986ecb47101974f44aeb5a","impliedFormat":99},{"version":"00d79566e3d5682a968b44aed9eba1557b1f62c884546fee2bca88be8c477104","impliedFormat":99},{"version":"f82d26f23d5e3093ca86458544b54befaf0957a5535149f673976187a60f9e6b","impliedFormat":99},{"version":"9f0d621f43198d0db510779ba65ca3d1a8fbca37f408efa5e25ac5ca01f74875","impliedFormat":99},{"version":"9bc53a206914661c0f98bb869eeda7214778367683a5e3e0fe7c6eaa6c474556","impliedFormat":99},{"version":"71987002d6409ea81e705fbfb97afc644851c16d9fbb5e90fcb3bc3e00e4ac5d","impliedFormat":99},{"version":"70e86eda2938040292fac398debcbe47114a3b9bd6eb8f632a89dcd23ac0e2f0","impliedFormat":99},{"version":"6241345f59b24be6e85c159db51cfd937f853aa8020b38b2aac5345813b25a8d","impliedFormat":99},{"version":"583eb3b56fc84b730641e623070f6eefa3fbacae4e15a6a3f19e1b09c81a7685","impliedFormat":99},{"version":"1c96afc9b678d9f15ec1b045864ea6cff25c134fd594cdddd42d66d99c8663b5","impliedFormat":99},{"version":"cd37c2470a4ac1ad7e1bdbd29bc8953589a4da6a7326a3bfd885bb7b220ffcde","impliedFormat":99},{"version":"ce82368397e5c926481222b9adb2547e4f9e0206982ac71c301284d107e77ebb","impliedFormat":99},{"version":"602a7beeec46d5f481d8f017adc1e01314101dea37f8f9ba3debcf88c83a44d5","impliedFormat":99},{"version":"d4e62d466b6302ad6419cf38669dda1eabe141200b15928a120ec32423904fdb","impliedFormat":99},{"version":"7baac7cf35ef7ef1b049fdfaa215f66891fd677bd617ec7e9a89ca9d430406d1","impliedFormat":99},{"version":"7869a702c21d4fe08180df0919c6365d4662cbdd9e0cbfd17bae7222d10fae58","impliedFormat":99},{"version":"e2944368a3fc08ea1ecde61384f2aea35d8551f02e20373f26f19a1e15f33c01","impliedFormat":99},{"version":"1e13585db16f3406755c1f7a3b32a2003d0b04f83df215fafae61c665de938a1","impliedFormat":99},{"version":"5dbbbf480819904753f84c454eba9bebc455b19966195e97f6b365e7cdcae4b6","impliedFormat":99},{"version":"a96af1a20dbd8aeffb9dc6c2461c7d9d131979390a8b41ca6975f652e2a897a4","impliedFormat":99},{"version":"46f1bf29bd4165fe2bff54eecd23a31f45b1432ab50ba3a0304100697dce91b0","impliedFormat":99},{"version":"1b5cbd26dd659f174a672c6d81b3088c9f46ae0dfd160ce93d2afad5bb7151a6","impliedFormat":99},{"version":"261790ad96cccfe94b94e4825a11a719210f9251d430e05829ed4f0b3d90fe48","impliedFormat":99},{"version":"55eca0dcf8f3192e5906e73aa8c7b88d898b1351bba84c69f4c5c38ab4e43f6f","impliedFormat":99},{"version":"686832a82159a4ea4dd25329c3a99c0a94d9b2a83e7b4ceeb6dfa58bd6707aa6","impliedFormat":99},{"version":"ac339c5b90464b77c2f28dcc686944c9d084f62e680960619f6832471da398ef","impliedFormat":99},{"version":"5090c4c9eb11d488fe455e985891f55e90d65365933d5797b30c188fdbe8015c","impliedFormat":99},{"version":"959c4529d03aebf8f76af7e58797800a25a6a14f560228a69235edcac4e8bfde","impliedFormat":99},{"version":"e893479eb9d99a9c479248a70650f43d3630614ccd0ef07352e208a23988f7cd","impliedFormat":99},{"version":"04d51092411e37e0df07828195cf9e0462861523461eba25eb9dc52344ead7d6","impliedFormat":99},{"version":"a2bf25976a0749263db4e003c2db061217b6e63aaa674f3f2e9dbaeb75f0cf87","impliedFormat":99},{"version":"92bf26f78ac596c9f643b340974854edb633f4719c7d9ad812367883e90272b0","impliedFormat":99},{"version":"afc885e843cf91a18e1c9b674d958c5c71ad3b8d2c9762c6983025d4a30d0918","impliedFormat":99},{"version":"01ff8948288663a825d5d4b5a48fc4dd54adfd4136c00c11d2a01eaf19084340","impliedFormat":99},{"version":"fc61c6168137297ec33f5720835a8f1e7fc424b00e0faab2d24e980dd0bd03c2","impliedFormat":99},{"version":"0b1cdbb2aef2c6ce308de85e80148059f7e16bf727eb3830a2e3e744c4aba6ad","impliedFormat":99},{"version":"1568200178c3ffe44819798eab91cbede3b302ff487149b18aa814a9410645c9","impliedFormat":99},{"version":"3ccf7553bce15ff3fd0b3a0cf4ee9177e9835577aeaeff17c1c6e04a5fa60b4b","impliedFormat":99},{"version":"44182cb6be79f471d6c4a40937a8d6d183af1a87cb26a3bad310c613d006351e","impliedFormat":99},{"version":"261e48dbb899ec4e2de4b9a72b8127a3314d28828b357288bcdebf39be32c126","impliedFormat":99},{"version":"80b3a4c879b86f31611611d628c61546a3924a17609d2abce5af75ab1526bd17","impliedFormat":99},{"version":"69260d8b8cd174b1fa69eb05cad51051da0cb9bad809cf391c1d8234d4b403a6","impliedFormat":99},{"version":"79992568ff244f34b7112942a3d52eb9375885d7e1d8099fc1a17552d14c6fe5","impliedFormat":99},{"version":"dde1fa7a49e820b8801d01bfe9e9b7829d9c62e8eb82a29ef2c28f239aadb5f2","impliedFormat":99},{"version":"e0cd63cf24da521cea60545e5573cbd7eb13d024cca52cc342032e2db987e7b0","impliedFormat":99},{"version":"b1c80011f3a457bbf2e1dec4b6016e63121e60de3b4ff805f261f69016aeada5","impliedFormat":99},{"version":"0bc0511027cff18f7025fdb354850e43083e16d2af2a48da869e095b8df05616","impliedFormat":99},{"version":"70aa4b70c1ebd45e76e4dc63b414d0a7e12fd41ed860da7d9e42737e2a11559b","impliedFormat":99},{"version":"7602bb9744aa13918f0dc9713e4a84e9e97cb099317eaf164c042a636311963d","impliedFormat":99},{"version":"de557ce115571688c6a8dbd486281e4d5a8068ba9c8339ab483014d4aee792a0","impliedFormat":99},{"version":"d942ff22d0bd25a2f26c50d2cc59d6cde2bf7a6cd428e3dd26356033015391ad","impliedFormat":99},{"version":"06e3997ff9c559d21c94113cb949cd03bc44f16cd77c2d7bd42f85c9be29a70f","impliedFormat":99},{"version":"f0029f53c3acc648f4215bc446cd60d92e8c29a8e73cd4008c1e1b37f91eb811","impliedFormat":99},{"version":"b59791581c6df3f62a81a0e96fb3e833a2f5b36304bcb074d765fd79d2fba320","impliedFormat":99},{"version":"627109c27f42261a2148c5758e5529e0694e09ffb74c2cb20e86a7a3682134c5","impliedFormat":99},{"version":"233ab9a64155ad15a070b03a52f8192ace79a29c03a9d4f7cea88929afeb1d45","impliedFormat":99},{"version":"fa7781b202e5845b1609eb84653dfc54189ce4e891909259a9aea73cba9859e9","impliedFormat":99},{"version":"a54b716354950f63c6e8ad298bdc90f94dab416eaecb3d32e9c6dd1bccc79eb0","impliedFormat":99},{"version":"38e6306d5a856a848f6737da319f79b703006b16ced089b2c4e80d04efa58adf","impliedFormat":99},{"version":"0f1434bb4e24cb50e9e73f0144414af44c1610514cb1ba0665936fb4993a3db3","impliedFormat":99},{"version":"1f15564e79f492da5842d1fd5f29cae75d37737e5abb4690b3b4bb9e7e856f3b","impliedFormat":99},{"version":"91d60e5b5441b738133c095fa2d6a809a3c3c4b75556d7f13cc19df48e20de12","impliedFormat":99},{"version":"6beeccd58698b2f72df8cff766e658f4adf98ef39ce1402799d4c18db1b2d803","impliedFormat":99},{"version":"980b920f853e57fd46983d0f5a2e7164f2d2e9dac780aa04d4325aa235c0a75e","impliedFormat":99},{"version":"3a39f3263b853937eca381775fb7558b4867a2714a89d770ea98c30dd1fadaa7","impliedFormat":99},{"version":"ced0b20e13a057c20d802a11870ff310579c6e80a5e5e45166de9e5f0e88f8d3","impliedFormat":99},{"version":"62f73fab1b97e50ee8092499cd5a8b5085abf700b372c24aa53e1879a3d68979","impliedFormat":99},{"version":"a393c298d0678e3e0b610c1069e3721de31dcdf1f885d6ecd813b837330156aa","impliedFormat":99},{"version":"e4784320828932df26b306ec4839c8f9496b959173179a29b29163efe301a7b6","impliedFormat":99},{"version":"5dbb45a20780dd90e28869e05035e681c90afa007364f01c3c3cf14c4cc04467","impliedFormat":99},{"version":"c9e1e15b8ab027dbbe4a2d85c0669905497e0d55a09c702f06c79e57645e347b","impliedFormat":99},{"version":"4078ccf4490cf97463a7ff2f9e02ff30a36ed2e4b18e8566445838d0d4d603a3","impliedFormat":99},{"version":"727d10cd972ba9b52da4defa702f65739323f9ff9949a7e9c7bd55fa76c37ac5","impliedFormat":99},{"version":"9420bd92184bda15c9a04daf532afae98df4fbbb17a930983ca664e929fe6c6a","impliedFormat":99},{"version":"684ad94c713c5f22951e9f433d52786c8508447510005459b6d9764c75cd2c74","impliedFormat":99},{"version":"3e00971f3dcbbe00de774d5387485454c98b8873bb636b8e6bcd4d9915ee0a2d","impliedFormat":99},{"version":"931674e02ae4a041ad822756dd4dbd30236bb3b52e21201aabe678b734baedbf","impliedFormat":99},{"version":"940961ea4bd1da98cef1edca26d6380eeb0c3e06df2e9d7a29dcb57303fb0326","impliedFormat":99},{"version":"581f0278df053736226f58d9a4671e2bdba6508f8be23751247c846e82736a0a","impliedFormat":99},{"version":"ff7eebe9610f96732e29782294ee55529ca5ff804e2325ba992cab0c2ca4c05f","impliedFormat":99},{"version":"e0138d7c2408df5bcc623e3e3b496ffbc405421c7dd7ae6ecf897a657926e2c4","impliedFormat":99},{"version":"18bbffdecf7eed3cefa4a37f34dc879050e629231ba0bd011e2ec6f7503a6cfa","impliedFormat":99},{"version":"fd2e67b97e27962b7c2a6083a2ebf936e7dc2b2335286df2ef5cfc09eb8522b9","impliedFormat":99},{"version":"2e1ccba239f8919e62f83719bc95b4d47b1d1e0187cc6968b5481c86dbbffe3c","impliedFormat":99},{"version":"983bd1482518c10b3e7549f6fe3f51cb7b9868f38ea715cc0c19c8ad6c5c34ca","impliedFormat":99},{"version":"728cf2a025de44eb3e43b3e87d9c8bb2feafe8a34de5ba9b2158317b265125f0","impliedFormat":99},{"version":"54977f121205ea7c7a6c86b42d813dc55d7db6e69c9554a262fc64cae0c7eacf","impliedFormat":99},{"version":"2f94e898529d71f48c841206140ac13988a5ab275bddf852922ad75b7021537d","impliedFormat":99},{"version":"d27f8ee9a610635b566109a359d00923f7e8f286ab7936894671c39a006e8b1a","impliedFormat":99},{"version":"5822d798e08ca6c321c2e5deb337e3b6d6472f2133440c4a2468f0ddee71ab75","signature":"f3688333654359ade219d4e94fb2a91f12339e46c19e03e451714a21e577435c"},{"version":"8db3f96517a120bade1643b55b24ed75a18970f4d38221402d9eccdbb5106fdb","signature":"f9a16b54b8913022325e94f69c48805664e20b6556089e3f3506306b97fe129e"},{"version":"e34e93f5498ed7bc9c53a9ee97d679f90fb941b9ab4190b5ba0747184ef12ad3","signature":"6411762007a15dd690acee3a833c9d06863ca69119d48bca9527fe1f81789e17"},{"version":"012e4aced863fe99eee38c5f48f5d3e79b2afbc9aaa56bef5daadd5ee6464b39","signature":"4c73137788f0bbedcc9e0442183a89a07c3b30303ebc069e6ab02ced95c249f7"},{"version":"3e7b55ed03072f277b2f5d8555bc4707f62be805d9fda85cb9fb6a7c17238afc","signature":"a0cee837e5373cf7095c21e187a4580b8216a64ecd64aa80d19a6967e6d1bb59"},{"version":"e7434e5f90aaa3c85f4658f7e3d3dbe8fc90d286ec4338c282f90d3a6bda0e60","signature":"006d76e50e7f1e25a37da6d436aad571aeb2d646c47f833f9bff146080c9605d"},{"version":"f5c96a4ee0e61f5664d81620d619f5db8aee48c11dd320d767701570438cf0f4","signature":"52a7d02b1fe8db0b42f5259d721b5c7f6bea6d862b8c5ba4331b7169d058305f"},{"version":"65c1e989444a2f3f3f925187ac087ef5de0a880944945644a597a895057a5f1f","signature":"652b463ed1eaf99f278d254973cffb72ea7ef2e76ed166857abe2161fc04d04c"},{"version":"5a2672453bf725ec5acb835ae4d14225718773d493b82a18ddd09c0f1837399c","signature":"8e609a09273295280918847c8f011e60b4c35d8d6591355f4e803712f5f8d6c3"},{"version":"39ecf44f9a385a3b0a20112d827f6bdd6e4fe0ab6e9e46788c8046a13be528b4","signature":"b86992151f5eb07dd0c135d7c1507df75fdeadcbc317e6f37295cdd44f61babf"},{"version":"7fe45be306bc1197001c20c483e2573ce5675181128484669b22de5b58d3332d","signature":"cafc2d90a1946bf6b9447683f11a384aeca03cb10c38b8945e4ceb287f8a97fb"},{"version":"5442b92ed2b5d6f2fa515b8df5c198aaf5b244babf631bbadefa1226284ea7fb","signature":"2864072f8edbbc54e60c45c4d397ec8b00fc21f2524747065c5da1814d77d30a"},{"version":"64e4a36aabd778ea468c12dba55fb5990d2c711b295f1b580c6c859e667492d0","signature":"404049eff8654148369e62fb3e430ac039e762b0f5e25f1aeec5b5c35499710e"},{"version":"002a6f95435929fb339cf9495f6faecc314a30fc0b434f08b7ece78e5152339f","signature":"b46a7be2bec9c094170bd64ff5e51062de78828862893ccb070c57c58948abf4"},{"version":"3a32529dc96bdcfe52cb9331b2cce36d8e92b1164a34ceb4a7443359aec49061","signature":"b0f87819f7baf6659bf4531fcf0687f9333c26d56bf86c00a5162165d68a2aeb"},{"version":"4b854ba79ddff6d7b672f009655ddefd087ab142ad8e82558f48d387b0780ffa","signature":"a0ad37ab2c1f847fe8bb1e9bdfef18ee4719429f1ed808f8aa543d363f23069a"},{"version":"fb7a0827a700b2998bc668b649c22d0cb606ff9557b0990672449e9f518fda72","signature":"e034180f88ee9195af896f639e7cee117b277e3b765995424f8991b3f6b4dda2"},{"version":"d6bc387f53aaf1f3d8cb4c5ea4e4c84865e4fa26d42472ee446bac50e0f7125b","signature":"b871a827a3198ec8b0e0281e1a5dad54d3a3cd2b319f4fd162d55c35833d91f8"},{"version":"ab596340e3c0d463ad4207a8c70118746d30d011de74dc13cd576754169b3b8f","signature":"842f5c6f3899cd852c58d006876c188b06c9093b7372f967948198882a9c32ba"},{"version":"f56f0523d9dfee6fcddcb10d3a6429ba50954f50ec0df71e0ce11e3e7f3ee200","signature":"c261639266a388d9118c5d2c16c6d68f83f9631c30aceb6898dfb173194ab716"},{"version":"bd7c206bd2bc79d129d22f89abdf25968fa171c6956ac9d0a92c0bdf3d3c04b7","signature":"9ff2309cbe37c21de662b3cfffc8755c3620f1b604e32454506cd2da292fa127"},{"version":"dc3b172ee27054dbcedcf5007b78c256021db936f6313a9ce9a3ecbb503fd646","impliedFormat":1},{"version":"a28ac3e717907284b3910b8e9b3f9844a4e0b0a861bea7b923e5adf90f620330","impliedFormat":1},{"version":"b6d03c9cfe2cf0ba4c673c209fcd7c46c815b2619fd2aad59fc4229aaef2ed43","impliedFormat":1},{"version":"82e5a50e17833a10eb091923b7e429dc846d42f1c6161eb6beeb964288d98a15","impliedFormat":1},{"version":"670a76db379b27c8ff42f1ba927828a22862e2ab0b0908e38b671f0e912cc5ed","impliedFormat":1},{"version":"13b77ab19ef7aadd86a1e54f2f08ea23a6d74e102909e3c00d31f231ed040f62","impliedFormat":1},{"version":"069bebfee29864e3955378107e243508b163e77ab10de6a5ee03ae06939f0bb9","impliedFormat":1},{"version":"151ff381ef9ff8da2da9b9663ebf657eac35c4c9a19183420c05728f31a6761d","impliedFormat":1},{"version":"f3d8c757e148ad968f0d98697987db363070abada5f503da3c06aefd9d4248c1","impliedFormat":1},{"version":"d153a11543fd884b596587ccd97aebbeed950b26933ee000f94009f1ab142848","affectsGlobalScope":true,"impliedFormat":1},{"version":"c0671b50bb99cc7ad46e9c68fa0e7f15ba4bc898b59c31a17ea4611fab5095da","affectsGlobalScope":true,"impliedFormat":1},{"version":"d802f0e6b5188646d307f070d83512e8eb94651858de8a82d1e47f60fb6da4e2","affectsGlobalScope":true,"impliedFormat":1},{"version":"aa83e100f0c74a06c9d24f40a096c9e9cc3c02704250d01541e22c0ae9264eda","affectsGlobalScope":true,"impliedFormat":1},{"version":"1db0b7dca579049ca4193d034d835f6bfe73096c73663e5ef9a0b5779939f3d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"387a023d363f755eb63450a66c28b14cdd7bc30a104565e2dbf0a8988bb4a56c","affectsGlobalScope":true,"impliedFormat":1},{"version":"9798340ffb0d067d69b1ae5b32faa17ab31b82466a3fc00d8f2f2df0c8554aaa","affectsGlobalScope":true,"impliedFormat":1},{"version":"f26b11d8d8e4b8028f1c7d618b22274c892e4b0ef5b3678a8ccbad85419aef43","affectsGlobalScope":true,"impliedFormat":1},{"version":"cdcf9ea426ad970f96ac930cd176d5c69c6c24eebd9fc580e1572d6c6a88f62c","impliedFormat":1},{"version":"23cd712e2ce083d68afe69224587438e5914b457b8acf87073c22494d706a3d0","impliedFormat":1},{"version":"487b694c3de27ddf4ad107d4007ad304d29effccf9800c8ae23c2093638d906a","impliedFormat":1},{"version":"3a80bc85f38526ca3b08007ee80712e7bb0601df178b23fbf0bf87036fce40ce","impliedFormat":1},{"version":"ccf4552357ce3c159ef75f0f0114e80401702228f1898bdc9402214c9499e8c0","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"68834d631c8838c715f225509cfc3927913b9cc7a4870460b5b60c8dbdb99baf","impliedFormat":1},{"version":"2931540c47ee0ff8a62860e61782eb17b155615db61e36986e54645ec67f67c2","impliedFormat":1},{"version":"3c8e93af4d6ce21eb4c8d005ad6dc02e7b5e6781f429d52a35290210f495a674","impliedFormat":1},{"version":"f6faf5f74e4c4cc309a6c6a6c4da02dbb840be5d3e92905a23dcd7b2b0bd1986","impliedFormat":1},{"version":"ea6bc8de8b59f90a7a3960005fd01988f98fd0784e14bc6922dde2e93305ec7d","impliedFormat":1},{"version":"36107995674b29284a115e21a0618c4c2751b32a8766dd4cb3ba740308b16d59","impliedFormat":1},{"version":"914a0ae30d96d71915fc519ccb4efbf2b62c0ddfb3a3fc6129151076bc01dc60","impliedFormat":1},{"version":"33e981bf6376e939f99bd7f89abec757c64897d33c005036b9a10d9587d80187","impliedFormat":1},{"version":"7fd1b31fd35876b0aa650811c25ec2c97a3c6387e5473eb18004bed86cdd76b6","impliedFormat":1},{"version":"b41767d372275c154c7ea6c9d5449d9a741b8ce080f640155cc88ba1763e35b3","impliedFormat":1},{"version":"3bacf516d686d08682751a3bd2519ea3b8041a164bfb4f1d35728993e70a2426","impliedFormat":1},{"version":"00b21ef538da5a2bbe419e2144f3be50661768e1e039ef2b57bb89f96aff9b18","impliedFormat":1},{"version":"0a60a292b89ca7218b8616f78e5bbd1c96b87e048849469cccb4355e98af959a","impliedFormat":1},{"version":"0b6e25234b4eec6ed96ab138d96eb70b135690d7dd01f3dd8a8ab291c35a683a","impliedFormat":1},{"version":"9666f2f84b985b62400d2e5ab0adae9ff44de9b2a34803c2c5bd3c8325b17dc0","impliedFormat":1},{"version":"40cd35c95e9cf22cfa5bd84e96408b6fcbca55295f4ff822390abb11afbc3dca","impliedFormat":1},{"version":"b1616b8959bf557feb16369c6124a97a0e74ed6f49d1df73bb4b9ddf68acf3f3","impliedFormat":1},{"version":"e843e840f484f7e59b2ef9488501a301e3300a8e3e56aa84a02ddf915c7ce07d","impliedFormat":1},{"version":"40b463c6766ca1b689bfcc46d26b5e295954f32ad43e37ee6953c0a677e4ae2b","impliedFormat":1},{"version":"249b9cab7f5d628b71308c7d9bb0a808b50b091e640ba3ed6e2d0516f4a8d91d","impliedFormat":1},{"version":"80aae6afc67faa5ac0b32b5b8bc8cc9f7fa299cff15cf09cc2e11fd28c6ae29e","impliedFormat":1},{"version":"f473cd2288991ff3221165dcf73cd5d24da30391f87e85b3dd4d0450c787a391","impliedFormat":1},{"version":"499e5b055a5aba1e1998f7311a6c441a369831c70905cc565ceac93c28083d53","impliedFormat":1},{"version":"54c3e2371e3d016469ad959697fd257e5621e16296fa67082c2575d0bf8eced0","impliedFormat":1},{"version":"beb8233b2c220cfa0feea31fbe9218d89fa02faa81ef744be8dce5acb89bb1fd","impliedFormat":1},{"version":"78b29846349d4dfdd88bd6650cc5d2baaa67f2e89dc8a80c8e26ef7995386583","impliedFormat":1},{"version":"5d0375ca7310efb77e3ef18d068d53784faf62705e0ad04569597ae0e755c401","impliedFormat":1},{"version":"59af37caec41ecf7b2e76059c9672a49e682c1a2aa6f9d7dc78878f53aa284d6","impliedFormat":1},{"version":"addf417b9eb3f938fddf8d81e96393a165e4be0d4a8b6402292f9c634b1cb00d","impliedFormat":1},{"version":"48cc3ec153b50985fb95153258a710782b25975b10dd4ac8a4f3920632d10790","impliedFormat":1},{"version":"adf27937dba6af9f08a68c5b1d3fce0ca7d4b960c57e6d6c844e7d1a8e53adae","impliedFormat":1},{"version":"18f8cfbb14ba9405e67d30968ae67b8d19133867d13ebc49c8ed37ec64ce9bdb","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"866078923a56d026e39243b4392e282c1c63159723996fa89243140e1388a98d","impliedFormat":1},{"version":"830171b27c5fdf9bcbe4cf7d428fcf3ae2c67780fb7fbdccdf70d1623d938bc4","affectsGlobalScope":true,"impliedFormat":1},{"version":"1cf059eaf468efcc649f8cf6075d3cb98e9a35a0fe9c44419ec3d2f5428d7123","affectsGlobalScope":true,"impliedFormat":1},{"version":"e7721c4f69f93c91360c26a0a84ee885997d748237ef78ef665b153e622b36c1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d97fb21da858fb18b8ae72c314e9743fd52f73ebe2764e12af1db32fc03f853f","affectsGlobalScope":true,"impliedFormat":1},{"version":"f68328826a275104d92bd576c796c570f66365f25ea8bbaaa208727bce132d5f","impliedFormat":1},{"version":"7cf69dd5502c41644c9e5106210b5da7144800670cbe861f66726fa209e231c4","impliedFormat":1},{"version":"72c1f5e0a28e473026074817561d1bc9647909cf253c8d56c41d1df8d95b85f7","impliedFormat":1},{"version":"18334defc3d0a0e1966f5f3c23c7c83b62c77811e51045c5a7ff3883b446f81f","affectsGlobalScope":true,"impliedFormat":1},{"version":"8b17fcd63aa13734bf1d01419f4d6031b1c6a5fb2cbdb45e9839fb1762bdf0df","impliedFormat":1},{"version":"c4e8e8031808b158cfb5ac5c4b38d4a26659aec4b57b6a7e2ba0a141439c208c","impliedFormat":1},{"version":"2c91d8366ff2506296191c26fd97cc1990bab3ee22576275d28b654a21261a44","affectsGlobalScope":true,"impliedFormat":1},{"version":"5524481e56c48ff486f42926778c0a3cce1cc85dc46683b92b1271865bcf015a","impliedFormat":1},{"version":"beb77fcd86c8cee62c32b2fb82753f5bc0e171d938e20af3cb0b8925db78d60b","impliedFormat":1},{"version":"289e9894a4668c61b5ffed09e196c1f0c2f87ca81efcaebdf6357cfb198dac14","impliedFormat":1},{"version":"25a1105595236f09f5bce42398be9f9ededc8d538c258579ab662d509aa3b98e","impliedFormat":1},{"version":"aa9224557befad144262c85b463c0a7ba8a3a0ad2a7c907349f8bb8bc3fe4abc","impliedFormat":1},{"version":"a2e2bbde231b65c53c764c12313897ffdfb6c49183dd31823ee2405f2f7b5378","impliedFormat":1},{"version":"ad1cc0ed328f3f708771272021be61ab146b32ecf2b78f3224959ff1e2cd2a5c","impliedFormat":1},{"version":"8d86c8d8c43e04cc3dde9953e571656812c8964a3651203af7b3a1df832a34df","affectsGlobalScope":true,"impliedFormat":1},{"version":"0121911fcc364eb821d058cf4c3b9339f197eccbe298098a4c6be0396b607d90","impliedFormat":1},{"version":"c6176c7b9f3769ba7f076c7a791588562c653cc0ba08fb2184f87bf78db2a87c","impliedFormat":1},{"version":"6def204d0b267101d3a42300a7363f53406c5d86b932e76e2365bf89689a85c4","impliedFormat":1},{"version":"4f766affd1281935fe5f7fd5d7af693a7c26d81adef7c1aefb84b9cd573a9cbb","impliedFormat":1},{"version":"165a0c1f95bc939c72f18a280fc707fba6f2f349539246b050cfc09eb1d9f446","impliedFormat":1},{"version":"bbf42f98a5819f4f06e18c8b669a994afe9a17fe520ae3454a195e6eabf7700d","impliedFormat":1},{"version":"c0bb1b65757c72bbf8ddf7eaa532223bacf58041ff16c883e76f45506596e925","impliedFormat":1},{"version":"c8b85f7aed29f8f52b813f800611406b0bfe5cf3224d20a4bdda7c7f73ce368e","affectsGlobalScope":true,"impliedFormat":1},{"version":"7baae9bf5b50e572e7742c886c73c6f8fa50b34190bc5f0fd20dd7e706fda832","impliedFormat":1},{"version":"e99b0e71f07128fc32583e88ccd509a1aaa9524c290efb2f48c22f9bf8ba83b1","impliedFormat":1},{"version":"76957a6d92b94b9e2852cf527fea32ad2dc0ef50f67fe2b14bd027c9ceef2d86","impliedFormat":1},{"version":"5e9f8c1e042b0f598a9be018fc8c3cb670fe579e9f2e18e3388b63327544fe16","affectsGlobalScope":true,"impliedFormat":1},{"version":"a8a99a5e6ed33c4a951b67cc1fd5b64fd6ad719f5747845c165ca12f6c21ba16","affectsGlobalScope":true,"impliedFormat":1},{"version":"a58a15da4c5ba3df60c910a043281256fa52d36a0fcdef9b9100c646282e88dd","impliedFormat":1},{"version":"b36beffbf8acdc3ebc58c8bb4b75574b31a2169869c70fc03f82895b93950a12","impliedFormat":1},{"version":"de263f0089aefbfd73c89562fb7254a7468b1f33b61839aafc3f035d60766cb4","impliedFormat":1},{"version":"70b57b5529051497e9f6482b76d91c0dcbb103d9ead8a0549f5bab8f65e5d031","impliedFormat":1},{"version":"8c81fd4a110490c43d7c578e8c6f69b3af01717189196899a6a44f93daa57a3a","impliedFormat":1},{"version":"1013eb2e2547ad8c100aca52ef9df8c3f209edee32bb387121bb3227f7c00088","impliedFormat":1},{"version":"b827f8800f42858f0a751a605c003b7ab571ff7af184436f36cef9bdfebae808","impliedFormat":1},{"version":"363eedb495912790e867da6ff96e81bf792c8cfe386321e8163b71823a35719a","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"125d792ec6c0c0f657d758055c494301cc5fdb327d9d9d5960b3f129aff76093","impliedFormat":1},{"version":"6b306cd4282bbb54d4a6bb23cfb7a271160983dfc38c67b5a132504cfcc34896","affectsGlobalScope":true,"impliedFormat":1},{"version":"ea713aa14a670b1ea0fbaaca4fd204e645f71ca7653a834a8ec07ee889c45de6","impliedFormat":1},{"version":"450172a56b944c2d83f45cc11c9a388ea967cd301a21202aa0a23c34c7506a18","impliedFormat":1},{"version":"9705cd157ffbb91c5cab48bdd2de5a437a372e63f870f8a8472e72ff634d47c1","affectsGlobalScope":true,"impliedFormat":1},{"version":"ae86f30d5d10e4f75ce8dcb6e1bd3a12ecec3d071a21e8f462c5c85c678efb41","impliedFormat":1},{"version":"3af7d02e5d6ecbf363e61fb842ee55d3518a140fd226bdfb24a3bca6768c58df","impliedFormat":1},{"version":"e03460fe72b259f6d25ad029f085e4bedc3f90477da4401d8fbc1efa9793230e","impliedFormat":1},{"version":"4286a3a6619514fca656089aee160bb6f2e77f4dd53dc5a96b26a0b4fc778055","impliedFormat":1},{"version":"7dfa742c23851808a77ec27062fbbd381c8c36bb3cfdff46cb8af6c6c233bfc1","affectsGlobalScope":true,"impliedFormat":1},{"version":"cb078cfcd14dc0b1700a48272958f803f30f13f99111c5978c75c3a0aa07e40e","affectsGlobalScope":true,"impliedFormat":1},{"version":"784490137935e1e38c49b9289110e74a1622baf8a8907888dcbe9e476d7c5e44","impliedFormat":1},{"version":"420fdd37c51263be9db3fcac35ffd836216c71e6000e6a9740bb950fb0540654","impliedFormat":1},{"version":"73b0bff83ee76e3a9320e93c7fc15596e858b33c687c39a57567e75c43f2a324","impliedFormat":1},{"version":"3c947600f6f5664cca690c07fcf8567ca58d029872b52c31c2f51d06fbdb581b","affectsGlobalScope":true,"impliedFormat":1},{"version":"493c64d062139b1849b0e9c4c3a6465e1227d2b42be9e26ec577ca728984c041","impliedFormat":1},{"version":"d7e9ab1b0996639047c61c1e62f85c620e4382206b3abb430d9a21fb7bc23c77","impliedFormat":1},{"version":"be1cc4d94ea60cbe567bc29ed479d42587bf1e6cba490f123d329976b0fe4ee5","impliedFormat":1}],"root":[[250,257],[406,426]],"options":{"allowSyntheticDefaultImports":true,"composite":true,"declaration":true,"declarationMap":true,"emitDeclarationOnly":true,"esModuleInterop":true,"jsx":4,"module":99,"outDir":"./lib-dist","rootDir":"./lib","skipLibCheck":true,"sourceMap":false,"strict":true,"target":7},"referencedMap":[[257,1],[414,2],[416,3],[413,4],[417,5],[418,6],[421,7],[423,8],[256,9],[255,10],[409,11],[424,12],[407,1],[253,13],[425,10],[415,10],[254,13],[426,14],[252,15],[410,16],[411,17],[420,18],[422,19],[406,20],[419,21],[408,21],[250,22],[251,23],[412,24],[249,25],[248,26],[155,27],[156,28],[157,29],[158,30],[159,31],[160,32],[161,33],[162,34],[164,35],[165,36],[166,37],[167,38],[168,39],[169,40],[170,41],[171,42],[172,43],[173,44],[174,45],[175,46],[176,47],[177,48],[178,49],[179,50],[180,51],[181,52],[182,43],[183,53],[184,54],[185,55],[187,56],[186,43],[189,57],[190,58],[188,43],[191,59],[192,60],[193,61],[194,62],[195,63],[196,64],[197,65],[163,43],[198,66],[199,67],[200,68],[201,69],[202,70],[203,71],[204,72],[205,73],[206,74],[207,75],[154,43],[208,76],[209,77],[210,78],[211,79],[212,80],[213,81],[214,82],[215,83],[216,84],[217,85],[218,86],[219,87],[220,88],[221,89],[222,90],[223,91],[224,43],[225,92],[226,93],[227,94],[228,95],[229,96],[230,97],[231,98],[232,99],[233,100],[234,101],[235,102],[236,103],[237,104],[238,105],[239,106],[240,107],[241,108],[242,109],[243,110],[244,111],[245,112],[246,113],[247,114],[405,115],[400,116],[271,117],[272,118],[273,119],[274,120],[275,121],[276,122],[277,123],[278,124],[279,125],[280,126],[281,127],[282,128],[283,129],[284,130],[261,43],[258,43],[262,131],[266,132],[264,133],[263,131],[268,134],[285,135],[286,136],[287,137],[288,138],[289,139],[290,140],[291,141],[292,142],[293,143],[294,144],[295,145],[297,146],[296,147],[298,148],[299,149],[300,150],[301,151],[302,152],[303,153],[259,154],[304,155],[305,156],[306,157],[260,158],[307,159],[269,160],[308,161],[309,162],[310,163],[311,164],[312,165],[313,166],[314,167],[315,168],[316,169],[317,170],[318,171],[319,172],[320,173],[321,174],[322,175],[323,176],[324,177],[325,178],[326,179],[327,180],[328,181],[329,182],[330,183],[331,184],[332,185],[333,186],[334,187],[335,188],[336,189],[265,190],[337,191],[338,192],[339,193],[270,43],[340,194],[341,195],[342,196],[343,197],[344,198],[345,199],[346,200],[347,201],[348,202],[349,203],[267,43],[350,204],[351,205],[352,206],[353,207],[354,208],[355,209],[356,210],[357,211],[358,212],[359,213],[360,214],[361,215],[362,216],[363,217],[364,218],[365,219],[366,220],[367,221],[368,222],[369,223],[370,224],[371,43],[372,225],[373,226],[374,227],[375,228],[376,229],[377,230],[378,231],[379,232],[381,233],[380,234],[382,235],[383,236],[384,237],[385,238],[386,239],[387,240],[388,241],[389,242],[390,243],[391,244],[392,245],[393,246],[394,247],[395,248],[396,249],[397,250],[398,251],[399,252],[401,253],[402,254],[403,254],[404,254],[77,255],[78,256],[76,257],[79,258],[90,259],[91,259],[92,259],[93,259],[98,260],[94,261],[95,261],[96,261],[97,261],[99,262],[89,263],[84,260],[88,264],[85,265],[86,260],[87,260],[82,266],[81,265],[83,267],[75,257],[74,268],[67,269],[68,257],[66,270],[72,271],[56,272],[60,273],[61,257],[62,257],[54,257],[55,257],[71,274],[63,257],[57,257],[58,257],[64,257],[65,257],[69,257],[59,257],[73,275],[153,276],[152,277],[100,278],[101,279],[102,280],[103,281],[104,282],[105,283],[106,284],[107,285],[108,286],[109,287],[110,288],[111,289],[112,290],[113,291],[114,292],[115,293],[116,294],[117,295],[118,296],[119,297],[120,298],[121,299],[122,300],[123,301],[124,302],[125,303],[126,304],[127,305],[128,306],[129,307],[130,308],[131,309],[132,43],[133,43],[134,310],[135,311],[136,312],[137,313],[138,314],[139,315],[140,316],[141,317],[142,43],[143,43],[144,43],[145,318],[146,319],[147,320],[148,321],[149,322],[150,323],[151,324],[430,325],[428,257],[80,257],[70,257],[427,257],[433,326],[429,325],[431,327],[432,325],[434,257],[435,257],[489,328],[490,328],[491,329],[438,330],[492,331],[493,332],[494,333],[436,257],[495,334],[496,335],[497,336],[498,337],[499,338],[500,339],[501,339],[502,340],[503,341],[504,342],[505,343],[439,257],[437,257],[506,344],[507,345],[508,346],[542,347],[509,348],[510,257],[511,349],[512,350],[513,351],[514,352],[515,353],[516,354],[517,355],[518,356],[519,357],[520,357],[521,358],[522,257],[523,257],[524,359],[526,360],[525,361],[527,362],[528,363],[529,364],[530,365],[531,366],[532,367],[533,368],[534,369],[535,370],[536,371],[537,372],[538,373],[539,374],[440,257],[441,375],[442,257],[443,257],[485,376],[486,377],[487,257],[488,362],[540,378],[541,379],[543,380],[50,257],[52,381],[53,380],[51,257],[48,257],[49,257],[8,257],[9,257],[11,257],[10,257],[2,257],[12,257],[13,257],[14,257],[15,257],[16,257],[17,257],[18,257],[19,257],[3,257],[20,257],[21,257],[4,257],[22,257],[26,257],[23,257],[24,257],[25,257],[27,257],[28,257],[29,257],[5,257],[30,257],[31,257],[32,257],[33,257],[6,257],[37,257],[34,257],[35,257],[36,257],[38,257],[7,257],[39,257],[44,257],[45,257],[40,257],[41,257],[42,257],[43,257],[1,257],[46,257],[47,257],[461,382],[473,383],[459,384],[474,385],[483,386],[450,387],[451,388],[449,389],[482,390],[477,391],[481,392],[453,393],[470,394],[452,395],[480,396],[447,397],[448,391],[454,398],[455,257],[460,399],[458,398],[445,400],[484,401],[475,402],[464,403],[463,398],[465,404],[468,405],[462,406],[466,407],[478,390],[456,408],[457,409],[469,410],[446,385],[472,411],[471,398],[467,412],[476,257],[444,257],[479,413]],"latestChangedDtsFile":"./lib-dist/core/AtProtoRecord.d.ts","version":"5.9.3"}
+2
-1
tsconfig.node.json
+2
-1
tsconfig.node.json
+2
vite.config.d.ts
+2
vite.config.d.ts
+73
-4
vite.config.ts
+73
-4
vite.config.ts
···
1
-
import { defineConfig } from 'vite'
2
-
import react from '@vitejs/plugin-react'
1
+
import { defineConfig } from 'vite';
2
+
import react from '@vitejs/plugin-react';
3
+
import dts from 'unplugin-dts/vite'
4
+
import { resolve } from 'path';
5
+
import type { Plugin } from 'vite';
6
+
7
+
// Plugin to inject CSS import as a side effect in the main entry
8
+
function injectCssImport(): Plugin {
9
+
return {
10
+
name: 'inject-css-import',
11
+
generateBundle(_, bundle) {
12
+
const indexFile = bundle['index.js'];
13
+
if (indexFile && indexFile.type === 'chunk') {
14
+
// Inject the CSS import at the top of the file
15
+
indexFile.code = `import './styles.css';\n${indexFile.code}`;
16
+
}
17
+
}
18
+
};
19
+
}
20
+
21
+
const buildDemo = process.env.BUILD_TARGET === 'demo';
3
22
4
23
// https://vite.dev/config/
5
24
export default defineConfig({
6
-
plugins: [react()],
7
-
})
25
+
plugins: buildDemo
26
+
? [react()]
27
+
: [react(), dts({ tsconfigPath: './tsconfig.lib.json' }), injectCssImport()],
28
+
29
+
// Demo app needs to resolve from src
30
+
root: buildDemo ? '.' : undefined,
31
+
32
+
build: buildDemo ? {
33
+
// Demo app build configuration
34
+
outDir: 'demo',
35
+
rollupOptions: {
36
+
input: resolve(__dirname, 'index.html')
37
+
},
38
+
sourcemap: false
39
+
} : {
40
+
// Library build configuration
41
+
lib: {
42
+
entry: resolve(__dirname, 'lib/index.ts'),
43
+
cssFileName: resolve(__dirname, 'lib/styles.css'),
44
+
name: 'atproto-ui',
45
+
formats: ['es'],
46
+
fileName: 'atproto-ui'
47
+
},
48
+
cssCodeSplit: false,
49
+
outDir: 'lib-dist',
50
+
rollupOptions: {
51
+
// Externalize dependencies that shouldn't be bundled
52
+
external: [
53
+
'react',
54
+
'react-dom',
55
+
'react/jsx-runtime',
56
+
'@atcute/atproto',
57
+
'@atcute/bluesky',
58
+
'@atcute/client',
59
+
'@atcute/identity-resolver',
60
+
'@atcute/tangled'
61
+
],
62
+
output: {
63
+
preserveModules: true,
64
+
preserveModulesRoot: 'lib',
65
+
entryFileNames: '[name].js',
66
+
assetFileNames: (assetInfo) => {
67
+
// Output CSS to root of lib-dist as styles.css
68
+
if (assetInfo.name && assetInfo.name.endsWith('.css')) {
69
+
return 'styles.css';
70
+
}
71
+
return 'assets/[name][extname]';
72
+
}
73
+
}
74
+
},
75
+
}
76
+
});