+2
-1
index.html
+2
-1
index.html
···
5
5
<meta charset="UTF-8" />
6
6
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
7
7
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
-
<title>Vite + React + TS</title>
8
+
<title>MappedAt</title>
9
+
<link href="/src/styles.css" rel="stylesheet">
9
10
<link rel="icon"
10
11
href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🏃</text></svg>">
11
12
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
+3
-1
package.json
+3
-1
package.json
···
14
14
"dependencies": {
15
15
"@atproto/api": "^0.15.6",
16
16
"@atproto/oauth-client-browser": "^0.3.16",
17
+
"@tailwindcss/vite": "^4.1.6",
17
18
"hono": "^4.7.9",
18
19
"react": "^19.0.0",
19
-
"react-dom": "^19.0.0"
20
+
"react-dom": "^19.0.0",
21
+
"tailwindcss": "^4.1.6"
20
22
},
21
23
"devDependencies": {
22
24
"@atproto/oauth-types": "^0.2.7",
+404
-40
pnpm-lock.yaml
+404
-40
pnpm-lock.yaml
···
14
14
'@atproto/oauth-client-browser':
15
15
specifier: ^0.3.16
16
16
version: 0.3.16
17
+
'@tailwindcss/vite':
18
+
specifier: ^4.1.6
19
+
version: 4.1.6(vite@6.3.5(jiti@2.4.2)(lightningcss@1.29.2))
17
20
hono:
18
21
specifier: ^4.7.9
19
22
version: 4.7.9
···
23
26
react-dom:
24
27
specifier: ^19.0.0
25
28
version: 19.1.0(react@19.1.0)
29
+
tailwindcss:
30
+
specifier: ^4.1.6
31
+
version: 4.1.6
26
32
devDependencies:
27
33
'@atproto/oauth-types':
28
34
specifier: ^0.2.7
29
35
version: 0.2.7
30
36
'@cloudflare/vite-plugin':
31
37
specifier: ^1.1.1
32
-
version: 1.1.1(rollup@4.40.2)(vite@6.3.5)(workerd@1.20250507.0)(wrangler@4.14.4(@cloudflare/workers-types@4.20250510.0))
38
+
version: 1.1.1(rollup@4.40.2)(vite@6.3.5(jiti@2.4.2)(lightningcss@1.29.2))(workerd@1.20250507.0)(wrangler@4.14.4(@cloudflare/workers-types@4.20250510.0))
33
39
'@cloudflare/workers-types':
34
40
specifier: ^4.20250510.0
35
41
version: 4.20250510.0
···
44
50
version: 19.1.3(@types/react@19.1.3)
45
51
'@vitejs/plugin-react':
46
52
specifier: ^4.3.4
47
-
version: 4.4.1(vite@6.3.5)
53
+
version: 4.4.1(vite@6.3.5(jiti@2.4.2)(lightningcss@1.29.2))
48
54
eslint:
49
55
specifier: ^9.22.0
50
-
version: 9.26.0
56
+
version: 9.26.0(jiti@2.4.2)
51
57
eslint-plugin-react-hooks:
52
58
specifier: ^5.2.0
53
-
version: 5.2.0(eslint@9.26.0)
59
+
version: 5.2.0(eslint@9.26.0(jiti@2.4.2))
54
60
eslint-plugin-react-refresh:
55
61
specifier: ^0.4.19
56
-
version: 0.4.20(eslint@9.26.0)
62
+
version: 0.4.20(eslint@9.26.0(jiti@2.4.2))
57
63
globals:
58
64
specifier: ^16.0.0
59
65
version: 16.1.0
···
62
68
version: 5.7.3
63
69
typescript-eslint:
64
70
specifier: ^8.26.1
65
-
version: 8.32.0(eslint@9.26.0)(typescript@5.7.3)
71
+
version: 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3)
66
72
vite:
67
73
specifier: ^6.3.1
68
-
version: 6.3.5
74
+
version: 6.3.5(jiti@2.4.2)(lightningcss@1.29.2)
69
75
wrangler:
70
76
specifier: ^4.14.4
71
77
version: 4.14.4(@cloudflare/workers-types@4.20250510.0)
···
604
610
cpu: [x64]
605
611
os: [win32]
606
612
613
+
'@isaacs/fs-minipass@4.0.1':
614
+
resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==}
615
+
engines: {node: '>=18.0.0'}
616
+
607
617
'@jridgewell/gen-mapping@0.3.8':
608
618
resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==}
609
619
engines: {node: '>=6.0.0'}
···
762
772
cpu: [x64]
763
773
os: [win32]
764
774
775
+
'@tailwindcss/node@4.1.6':
776
+
resolution: {integrity: sha512-ed6zQbgmKsjsVvodAS1q1Ld2BolEuxJOSyyNc+vhkjdmfNUDCmQnlXBfQkHrlzNmslxHsQU/bFmzcEbv4xXsLg==}
777
+
778
+
'@tailwindcss/oxide-android-arm64@4.1.6':
779
+
resolution: {integrity: sha512-VHwwPiwXtdIvOvqT/0/FLH/pizTVu78FOnI9jQo64kSAikFSZT7K4pjyzoDpSMaveJTGyAKvDjuhxJxKfmvjiQ==}
780
+
engines: {node: '>= 10'}
781
+
cpu: [arm64]
782
+
os: [android]
783
+
784
+
'@tailwindcss/oxide-darwin-arm64@4.1.6':
785
+
resolution: {integrity: sha512-weINOCcqv1HVBIGptNrk7c6lWgSFFiQMcCpKM4tnVi5x8OY2v1FrV76jwLukfT6pL1hyajc06tyVmZFYXoxvhQ==}
786
+
engines: {node: '>= 10'}
787
+
cpu: [arm64]
788
+
os: [darwin]
789
+
790
+
'@tailwindcss/oxide-darwin-x64@4.1.6':
791
+
resolution: {integrity: sha512-3FzekhHG0ww1zQjQ1lPoq0wPrAIVXAbUkWdWM8u5BnYFZgb9ja5ejBqyTgjpo5mfy0hFOoMnMuVDI+7CXhXZaQ==}
792
+
engines: {node: '>= 10'}
793
+
cpu: [x64]
794
+
os: [darwin]
795
+
796
+
'@tailwindcss/oxide-freebsd-x64@4.1.6':
797
+
resolution: {integrity: sha512-4m5F5lpkBZhVQJq53oe5XgJ+aFYWdrgkMwViHjRsES3KEu2m1udR21B1I77RUqie0ZYNscFzY1v9aDssMBZ/1w==}
798
+
engines: {node: '>= 10'}
799
+
cpu: [x64]
800
+
os: [freebsd]
801
+
802
+
'@tailwindcss/oxide-linux-arm-gnueabihf@4.1.6':
803
+
resolution: {integrity: sha512-qU0rHnA9P/ZoaDKouU1oGPxPWzDKtIfX7eOGi5jOWJKdxieUJdVV+CxWZOpDWlYTd4N3sFQvcnVLJWJ1cLP5TA==}
804
+
engines: {node: '>= 10'}
805
+
cpu: [arm]
806
+
os: [linux]
807
+
808
+
'@tailwindcss/oxide-linux-arm64-gnu@4.1.6':
809
+
resolution: {integrity: sha512-jXy3TSTrbfgyd3UxPQeXC3wm8DAgmigzar99Km9Sf6L2OFfn/k+u3VqmpgHQw5QNfCpPe43em6Q7V76Wx7ogIQ==}
810
+
engines: {node: '>= 10'}
811
+
cpu: [arm64]
812
+
os: [linux]
813
+
814
+
'@tailwindcss/oxide-linux-arm64-musl@4.1.6':
815
+
resolution: {integrity: sha512-8kjivE5xW0qAQ9HX9reVFmZj3t+VmljDLVRJpVBEoTR+3bKMnvC7iLcoSGNIUJGOZy1mLVq7x/gerVg0T+IsYw==}
816
+
engines: {node: '>= 10'}
817
+
cpu: [arm64]
818
+
os: [linux]
819
+
820
+
'@tailwindcss/oxide-linux-x64-gnu@4.1.6':
821
+
resolution: {integrity: sha512-A4spQhwnWVpjWDLXnOW9PSinO2PTKJQNRmL/aIl2U/O+RARls8doDfs6R41+DAXK0ccacvRyDpR46aVQJJCoCg==}
822
+
engines: {node: '>= 10'}
823
+
cpu: [x64]
824
+
os: [linux]
825
+
826
+
'@tailwindcss/oxide-linux-x64-musl@4.1.6':
827
+
resolution: {integrity: sha512-YRee+6ZqdzgiQAHVSLfl3RYmqeeaWVCk796MhXhLQu2kJu2COHBkqlqsqKYx3p8Hmk5pGCQd2jTAoMWWFeyG2A==}
828
+
engines: {node: '>= 10'}
829
+
cpu: [x64]
830
+
os: [linux]
831
+
832
+
'@tailwindcss/oxide-wasm32-wasi@4.1.6':
833
+
resolution: {integrity: sha512-qAp4ooTYrBQ5pk5jgg54/U1rCJ/9FLYOkkQ/nTE+bVMseMfB6O7J8zb19YTpWuu4UdfRf5zzOrNKfl6T64MNrQ==}
834
+
engines: {node: '>=14.0.0'}
835
+
cpu: [wasm32]
836
+
bundledDependencies:
837
+
- '@napi-rs/wasm-runtime'
838
+
- '@emnapi/core'
839
+
- '@emnapi/runtime'
840
+
- '@tybys/wasm-util'
841
+
- '@emnapi/wasi-threads'
842
+
- tslib
843
+
844
+
'@tailwindcss/oxide-win32-arm64-msvc@4.1.6':
845
+
resolution: {integrity: sha512-nqpDWk0Xr8ELO/nfRUDjk1pc9wDJ3ObeDdNMHLaymc4PJBWj11gdPCWZFKSK2AVKjJQC7J2EfmSmf47GN7OuLg==}
846
+
engines: {node: '>= 10'}
847
+
cpu: [arm64]
848
+
os: [win32]
849
+
850
+
'@tailwindcss/oxide-win32-x64-msvc@4.1.6':
851
+
resolution: {integrity: sha512-5k9xF33xkfKpo9wCvYcegQ21VwIBU1/qEbYlVukfEIyQbEA47uK8AAwS7NVjNE3vHzcmxMYwd0l6L4pPjjm1rQ==}
852
+
engines: {node: '>= 10'}
853
+
cpu: [x64]
854
+
os: [win32]
855
+
856
+
'@tailwindcss/oxide@4.1.6':
857
+
resolution: {integrity: sha512-0bpEBQiGx+227fW4G0fLQ8vuvyy5rsB1YIYNapTq3aRsJ9taF3f5cCaovDjN5pUGKKzcpMrZst/mhNaKAPOHOA==}
858
+
engines: {node: '>= 10'}
859
+
860
+
'@tailwindcss/vite@4.1.6':
861
+
resolution: {integrity: sha512-zjtqjDeY1w3g2beYQtrMAf51n5G7o+UwmyOjtsDMP7t6XyoRMOidcoKP32ps7AkNOHIXEOK0bhIC05dj8oJp4w==}
862
+
peerDependencies:
863
+
vite: ^5.2.0 || ^6
864
+
765
865
'@types/babel__core@7.20.5':
766
866
resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
767
867
···
943
1043
chalk@4.1.2:
944
1044
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
945
1045
engines: {node: '>=10'}
1046
+
1047
+
chownr@3.0.0:
1048
+
resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==}
1049
+
engines: {node: '>=18'}
946
1050
947
1051
color-convert@2.0.1:
948
1052
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
···
1031
1135
resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
1032
1136
engines: {node: '>= 0.8'}
1033
1137
1138
+
enhanced-resolve@5.18.1:
1139
+
resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==}
1140
+
engines: {node: '>=10.13.0'}
1141
+
1034
1142
es-define-property@1.0.1:
1035
1143
resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
1036
1144
engines: {node: '>= 0.4'}
···
1258
1366
gopd@1.2.0:
1259
1367
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
1260
1368
engines: {node: '>= 0.4'}
1369
+
1370
+
graceful-fs@4.2.11:
1371
+
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
1261
1372
1262
1373
graphemer@1.4.0:
1263
1374
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
···
1329
1440
iso-datestring-validator@2.2.2:
1330
1441
resolution: {integrity: sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA==}
1331
1442
1443
+
jiti@2.4.2:
1444
+
resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==}
1445
+
hasBin: true
1446
+
1332
1447
jose@5.10.0:
1333
1448
resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==}
1334
1449
···
1365
1480
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
1366
1481
engines: {node: '>= 0.8.0'}
1367
1482
1483
+
lightningcss-darwin-arm64@1.29.2:
1484
+
resolution: {integrity: sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==}
1485
+
engines: {node: '>= 12.0.0'}
1486
+
cpu: [arm64]
1487
+
os: [darwin]
1488
+
1489
+
lightningcss-darwin-x64@1.29.2:
1490
+
resolution: {integrity: sha512-j5qYxamyQw4kDXX5hnnCKMf3mLlHvG44f24Qyi2965/Ycz829MYqjrVg2H8BidybHBp9kom4D7DR5VqCKDXS0w==}
1491
+
engines: {node: '>= 12.0.0'}
1492
+
cpu: [x64]
1493
+
os: [darwin]
1494
+
1495
+
lightningcss-freebsd-x64@1.29.2:
1496
+
resolution: {integrity: sha512-wDk7M2tM78Ii8ek9YjnY8MjV5f5JN2qNVO+/0BAGZRvXKtQrBC4/cn4ssQIpKIPP44YXw6gFdpUF+Ps+RGsCwg==}
1497
+
engines: {node: '>= 12.0.0'}
1498
+
cpu: [x64]
1499
+
os: [freebsd]
1500
+
1501
+
lightningcss-linux-arm-gnueabihf@1.29.2:
1502
+
resolution: {integrity: sha512-IRUrOrAF2Z+KExdExe3Rz7NSTuuJ2HvCGlMKoquK5pjvo2JY4Rybr+NrKnq0U0hZnx5AnGsuFHjGnNT14w26sg==}
1503
+
engines: {node: '>= 12.0.0'}
1504
+
cpu: [arm]
1505
+
os: [linux]
1506
+
1507
+
lightningcss-linux-arm64-gnu@1.29.2:
1508
+
resolution: {integrity: sha512-KKCpOlmhdjvUTX/mBuaKemp0oeDIBBLFiU5Fnqxh1/DZ4JPZi4evEH7TKoSBFOSOV3J7iEmmBaw/8dpiUvRKlQ==}
1509
+
engines: {node: '>= 12.0.0'}
1510
+
cpu: [arm64]
1511
+
os: [linux]
1512
+
1513
+
lightningcss-linux-arm64-musl@1.29.2:
1514
+
resolution: {integrity: sha512-Q64eM1bPlOOUgxFmoPUefqzY1yV3ctFPE6d/Vt7WzLW4rKTv7MyYNky+FWxRpLkNASTnKQUaiMJ87zNODIrrKQ==}
1515
+
engines: {node: '>= 12.0.0'}
1516
+
cpu: [arm64]
1517
+
os: [linux]
1518
+
1519
+
lightningcss-linux-x64-gnu@1.29.2:
1520
+
resolution: {integrity: sha512-0v6idDCPG6epLXtBH/RPkHvYx74CVziHo6TMYga8O2EiQApnUPZsbR9nFNrg2cgBzk1AYqEd95TlrsL7nYABQg==}
1521
+
engines: {node: '>= 12.0.0'}
1522
+
cpu: [x64]
1523
+
os: [linux]
1524
+
1525
+
lightningcss-linux-x64-musl@1.29.2:
1526
+
resolution: {integrity: sha512-rMpz2yawkgGT8RULc5S4WiZopVMOFWjiItBT7aSfDX4NQav6M44rhn5hjtkKzB+wMTRlLLqxkeYEtQ3dd9696w==}
1527
+
engines: {node: '>= 12.0.0'}
1528
+
cpu: [x64]
1529
+
os: [linux]
1530
+
1531
+
lightningcss-win32-arm64-msvc@1.29.2:
1532
+
resolution: {integrity: sha512-nL7zRW6evGQqYVu/bKGK+zShyz8OVzsCotFgc7judbt6wnB2KbiKKJwBE4SGoDBQ1O94RjW4asrCjQL4i8Fhbw==}
1533
+
engines: {node: '>= 12.0.0'}
1534
+
cpu: [arm64]
1535
+
os: [win32]
1536
+
1537
+
lightningcss-win32-x64-msvc@1.29.2:
1538
+
resolution: {integrity: sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA==}
1539
+
engines: {node: '>= 12.0.0'}
1540
+
cpu: [x64]
1541
+
os: [win32]
1542
+
1543
+
lightningcss@1.29.2:
1544
+
resolution: {integrity: sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==}
1545
+
engines: {node: '>= 12.0.0'}
1546
+
1368
1547
locate-path@6.0.0:
1369
1548
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
1370
1549
engines: {node: '>=10'}
···
1434
1613
resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
1435
1614
engines: {node: '>=16 || 14 >=14.17'}
1436
1615
1616
+
minipass@7.1.2:
1617
+
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
1618
+
engines: {node: '>=16 || 14 >=14.17'}
1619
+
1620
+
minizlib@3.0.2:
1621
+
resolution: {integrity: sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==}
1622
+
engines: {node: '>= 18'}
1623
+
1624
+
mkdirp@3.0.1:
1625
+
resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==}
1626
+
engines: {node: '>=10'}
1627
+
hasBin: true
1628
+
1437
1629
ms@2.1.3:
1438
1630
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
1439
1631
···
1691
1883
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
1692
1884
engines: {node: '>=8'}
1693
1885
1886
+
tailwindcss@4.1.6:
1887
+
resolution: {integrity: sha512-j0cGLTreM6u4OWzBeLBpycK0WIh8w7kSwcUsQZoGLHZ7xDTdM69lN64AgoIEEwFi0tnhs4wSykUa5YWxAzgFYg==}
1888
+
1889
+
tapable@2.2.1:
1890
+
resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
1891
+
engines: {node: '>=6'}
1892
+
1893
+
tar@7.4.3:
1894
+
resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==}
1895
+
engines: {node: '>=18'}
1896
+
1694
1897
tinyglobby@0.2.13:
1695
1898
resolution: {integrity: sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==}
1696
1899
engines: {node: '>=12.0.0'}
···
1850
2053
1851
2054
yallist@3.1.1:
1852
2055
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
2056
+
2057
+
yallist@5.0.0:
2058
+
resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==}
2059
+
engines: {node: '>=18'}
1853
2060
1854
2061
yocto-queue@0.1.0:
1855
2062
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
···
2115
2322
optionalDependencies:
2116
2323
workerd: 1.20250507.0
2117
2324
2118
-
'@cloudflare/vite-plugin@1.1.1(rollup@4.40.2)(vite@6.3.5)(workerd@1.20250507.0)(wrangler@4.14.4(@cloudflare/workers-types@4.20250510.0))':
2325
+
'@cloudflare/vite-plugin@1.1.1(rollup@4.40.2)(vite@6.3.5(jiti@2.4.2)(lightningcss@1.29.2))(workerd@1.20250507.0)(wrangler@4.14.4(@cloudflare/workers-types@4.20250510.0))':
2119
2326
dependencies:
2120
2327
'@cloudflare/unenv-preset': 2.3.1(unenv@2.0.0-rc.15)(workerd@1.20250507.0)
2121
2328
'@hattip/adapter-node': 0.0.49
···
2125
2332
picocolors: 1.1.1
2126
2333
tinyglobby: 0.2.13
2127
2334
unenv: 2.0.0-rc.15
2128
-
vite: 6.3.5
2335
+
vite: 6.3.5(jiti@2.4.2)(lightningcss@1.29.2)
2129
2336
wrangler: 4.14.4(@cloudflare/workers-types@4.20250510.0)
2130
2337
ws: 8.18.0
2131
2338
transitivePeerDependencies:
···
2235
2442
'@esbuild/win32-x64@0.25.4':
2236
2443
optional: true
2237
2444
2238
-
'@eslint-community/eslint-utils@4.7.0(eslint@9.26.0)':
2445
+
'@eslint-community/eslint-utils@4.7.0(eslint@9.26.0(jiti@2.4.2))':
2239
2446
dependencies:
2240
-
eslint: 9.26.0
2447
+
eslint: 9.26.0(jiti@2.4.2)
2241
2448
eslint-visitor-keys: 3.4.3
2242
2449
2243
2450
'@eslint-community/regexpp@4.12.1': {}
···
2393
2600
'@img/sharp-win32-x64@0.33.5':
2394
2601
optional: true
2395
2602
2603
+
'@isaacs/fs-minipass@4.0.1':
2604
+
dependencies:
2605
+
minipass: 7.1.2
2606
+
2396
2607
'@jridgewell/gen-mapping@0.3.8':
2397
2608
dependencies:
2398
2609
'@jridgewell/set-array': 1.2.1
···
2519
2730
'@rollup/rollup-win32-x64-msvc@4.40.2':
2520
2731
optional: true
2521
2732
2733
+
'@tailwindcss/node@4.1.6':
2734
+
dependencies:
2735
+
'@ampproject/remapping': 2.3.0
2736
+
enhanced-resolve: 5.18.1
2737
+
jiti: 2.4.2
2738
+
lightningcss: 1.29.2
2739
+
magic-string: 0.30.17
2740
+
source-map-js: 1.2.1
2741
+
tailwindcss: 4.1.6
2742
+
2743
+
'@tailwindcss/oxide-android-arm64@4.1.6':
2744
+
optional: true
2745
+
2746
+
'@tailwindcss/oxide-darwin-arm64@4.1.6':
2747
+
optional: true
2748
+
2749
+
'@tailwindcss/oxide-darwin-x64@4.1.6':
2750
+
optional: true
2751
+
2752
+
'@tailwindcss/oxide-freebsd-x64@4.1.6':
2753
+
optional: true
2754
+
2755
+
'@tailwindcss/oxide-linux-arm-gnueabihf@4.1.6':
2756
+
optional: true
2757
+
2758
+
'@tailwindcss/oxide-linux-arm64-gnu@4.1.6':
2759
+
optional: true
2760
+
2761
+
'@tailwindcss/oxide-linux-arm64-musl@4.1.6':
2762
+
optional: true
2763
+
2764
+
'@tailwindcss/oxide-linux-x64-gnu@4.1.6':
2765
+
optional: true
2766
+
2767
+
'@tailwindcss/oxide-linux-x64-musl@4.1.6':
2768
+
optional: true
2769
+
2770
+
'@tailwindcss/oxide-wasm32-wasi@4.1.6':
2771
+
optional: true
2772
+
2773
+
'@tailwindcss/oxide-win32-arm64-msvc@4.1.6':
2774
+
optional: true
2775
+
2776
+
'@tailwindcss/oxide-win32-x64-msvc@4.1.6':
2777
+
optional: true
2778
+
2779
+
'@tailwindcss/oxide@4.1.6':
2780
+
dependencies:
2781
+
detect-libc: 2.0.4
2782
+
tar: 7.4.3
2783
+
optionalDependencies:
2784
+
'@tailwindcss/oxide-android-arm64': 4.1.6
2785
+
'@tailwindcss/oxide-darwin-arm64': 4.1.6
2786
+
'@tailwindcss/oxide-darwin-x64': 4.1.6
2787
+
'@tailwindcss/oxide-freebsd-x64': 4.1.6
2788
+
'@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.6
2789
+
'@tailwindcss/oxide-linux-arm64-gnu': 4.1.6
2790
+
'@tailwindcss/oxide-linux-arm64-musl': 4.1.6
2791
+
'@tailwindcss/oxide-linux-x64-gnu': 4.1.6
2792
+
'@tailwindcss/oxide-linux-x64-musl': 4.1.6
2793
+
'@tailwindcss/oxide-wasm32-wasi': 4.1.6
2794
+
'@tailwindcss/oxide-win32-arm64-msvc': 4.1.6
2795
+
'@tailwindcss/oxide-win32-x64-msvc': 4.1.6
2796
+
2797
+
'@tailwindcss/vite@4.1.6(vite@6.3.5(jiti@2.4.2)(lightningcss@1.29.2))':
2798
+
dependencies:
2799
+
'@tailwindcss/node': 4.1.6
2800
+
'@tailwindcss/oxide': 4.1.6
2801
+
tailwindcss: 4.1.6
2802
+
vite: 6.3.5(jiti@2.4.2)(lightningcss@1.29.2)
2803
+
2522
2804
'@types/babel__core@7.20.5':
2523
2805
dependencies:
2524
2806
'@babel/parser': 7.27.2
···
2552
2834
dependencies:
2553
2835
csstype: 3.1.3
2554
2836
2555
-
'@typescript-eslint/eslint-plugin@8.32.0(@typescript-eslint/parser@8.32.0(eslint@9.26.0)(typescript@5.7.3))(eslint@9.26.0)(typescript@5.7.3)':
2837
+
'@typescript-eslint/eslint-plugin@8.32.0(@typescript-eslint/parser@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3)':
2556
2838
dependencies:
2557
2839
'@eslint-community/regexpp': 4.12.1
2558
-
'@typescript-eslint/parser': 8.32.0(eslint@9.26.0)(typescript@5.7.3)
2840
+
'@typescript-eslint/parser': 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3)
2559
2841
'@typescript-eslint/scope-manager': 8.32.0
2560
-
'@typescript-eslint/type-utils': 8.32.0(eslint@9.26.0)(typescript@5.7.3)
2561
-
'@typescript-eslint/utils': 8.32.0(eslint@9.26.0)(typescript@5.7.3)
2842
+
'@typescript-eslint/type-utils': 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3)
2843
+
'@typescript-eslint/utils': 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3)
2562
2844
'@typescript-eslint/visitor-keys': 8.32.0
2563
-
eslint: 9.26.0
2845
+
eslint: 9.26.0(jiti@2.4.2)
2564
2846
graphemer: 1.4.0
2565
2847
ignore: 5.3.2
2566
2848
natural-compare: 1.4.0
···
2569
2851
transitivePeerDependencies:
2570
2852
- supports-color
2571
2853
2572
-
'@typescript-eslint/parser@8.32.0(eslint@9.26.0)(typescript@5.7.3)':
2854
+
'@typescript-eslint/parser@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3)':
2573
2855
dependencies:
2574
2856
'@typescript-eslint/scope-manager': 8.32.0
2575
2857
'@typescript-eslint/types': 8.32.0
2576
2858
'@typescript-eslint/typescript-estree': 8.32.0(typescript@5.7.3)
2577
2859
'@typescript-eslint/visitor-keys': 8.32.0
2578
2860
debug: 4.4.0
2579
-
eslint: 9.26.0
2861
+
eslint: 9.26.0(jiti@2.4.2)
2580
2862
typescript: 5.7.3
2581
2863
transitivePeerDependencies:
2582
2864
- supports-color
···
2586
2868
'@typescript-eslint/types': 8.32.0
2587
2869
'@typescript-eslint/visitor-keys': 8.32.0
2588
2870
2589
-
'@typescript-eslint/type-utils@8.32.0(eslint@9.26.0)(typescript@5.7.3)':
2871
+
'@typescript-eslint/type-utils@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3)':
2590
2872
dependencies:
2591
2873
'@typescript-eslint/typescript-estree': 8.32.0(typescript@5.7.3)
2592
-
'@typescript-eslint/utils': 8.32.0(eslint@9.26.0)(typescript@5.7.3)
2874
+
'@typescript-eslint/utils': 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3)
2593
2875
debug: 4.4.0
2594
-
eslint: 9.26.0
2876
+
eslint: 9.26.0(jiti@2.4.2)
2595
2877
ts-api-utils: 2.1.0(typescript@5.7.3)
2596
2878
typescript: 5.7.3
2597
2879
transitivePeerDependencies:
···
2613
2895
transitivePeerDependencies:
2614
2896
- supports-color
2615
2897
2616
-
'@typescript-eslint/utils@8.32.0(eslint@9.26.0)(typescript@5.7.3)':
2898
+
'@typescript-eslint/utils@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3)':
2617
2899
dependencies:
2618
-
'@eslint-community/eslint-utils': 4.7.0(eslint@9.26.0)
2900
+
'@eslint-community/eslint-utils': 4.7.0(eslint@9.26.0(jiti@2.4.2))
2619
2901
'@typescript-eslint/scope-manager': 8.32.0
2620
2902
'@typescript-eslint/types': 8.32.0
2621
2903
'@typescript-eslint/typescript-estree': 8.32.0(typescript@5.7.3)
2622
-
eslint: 9.26.0
2904
+
eslint: 9.26.0(jiti@2.4.2)
2623
2905
typescript: 5.7.3
2624
2906
transitivePeerDependencies:
2625
2907
- supports-color
···
2629
2911
'@typescript-eslint/types': 8.32.0
2630
2912
eslint-visitor-keys: 4.2.0
2631
2913
2632
-
'@vitejs/plugin-react@4.4.1(vite@6.3.5)':
2914
+
'@vitejs/plugin-react@4.4.1(vite@6.3.5(jiti@2.4.2)(lightningcss@1.29.2))':
2633
2915
dependencies:
2634
2916
'@babel/core': 7.27.1
2635
2917
'@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.27.1)
2636
2918
'@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.27.1)
2637
2919
'@types/babel__core': 7.20.5
2638
2920
react-refresh: 0.17.0
2639
-
vite: 6.3.5
2921
+
vite: 6.3.5(jiti@2.4.2)(lightningcss@1.29.2)
2640
2922
transitivePeerDependencies:
2641
2923
- supports-color
2642
2924
···
2751
3033
ansi-styles: 4.3.0
2752
3034
supports-color: 7.2.0
2753
3035
3036
+
chownr@3.0.0: {}
3037
+
2754
3038
color-convert@2.0.1:
2755
3039
dependencies:
2756
3040
color-name: 1.1.4
···
2808
3092
2809
3093
depd@2.0.0: {}
2810
3094
2811
-
detect-libc@2.0.4:
2812
-
optional: true
3095
+
detect-libc@2.0.4: {}
2813
3096
2814
3097
dunder-proto@1.0.1:
2815
3098
dependencies:
···
2823
3106
2824
3107
encodeurl@2.0.0: {}
2825
3108
3109
+
enhanced-resolve@5.18.1:
3110
+
dependencies:
3111
+
graceful-fs: 4.2.11
3112
+
tapable: 2.2.1
3113
+
2826
3114
es-define-property@1.0.1: {}
2827
3115
2828
3116
es-errors@1.3.0: {}
···
2865
3153
2866
3154
escape-string-regexp@4.0.0: {}
2867
3155
2868
-
eslint-plugin-react-hooks@5.2.0(eslint@9.26.0):
3156
+
eslint-plugin-react-hooks@5.2.0(eslint@9.26.0(jiti@2.4.2)):
2869
3157
dependencies:
2870
-
eslint: 9.26.0
3158
+
eslint: 9.26.0(jiti@2.4.2)
2871
3159
2872
-
eslint-plugin-react-refresh@0.4.20(eslint@9.26.0):
3160
+
eslint-plugin-react-refresh@0.4.20(eslint@9.26.0(jiti@2.4.2)):
2873
3161
dependencies:
2874
-
eslint: 9.26.0
3162
+
eslint: 9.26.0(jiti@2.4.2)
2875
3163
2876
3164
eslint-scope@8.3.0:
2877
3165
dependencies:
···
2882
3170
2883
3171
eslint-visitor-keys@4.2.0: {}
2884
3172
2885
-
eslint@9.26.0:
3173
+
eslint@9.26.0(jiti@2.4.2):
2886
3174
dependencies:
2887
-
'@eslint-community/eslint-utils': 4.7.0(eslint@9.26.0)
3175
+
'@eslint-community/eslint-utils': 4.7.0(eslint@9.26.0(jiti@2.4.2))
2888
3176
'@eslint-community/regexpp': 4.12.1
2889
3177
'@eslint/config-array': 0.20.0
2890
3178
'@eslint/config-helpers': 0.2.2
···
2921
3209
natural-compare: 1.4.0
2922
3210
optionator: 0.9.4
2923
3211
zod: 3.24.4
3212
+
optionalDependencies:
3213
+
jiti: 2.4.2
2924
3214
transitivePeerDependencies:
2925
3215
- supports-color
2926
3216
···
3105
3395
3106
3396
gopd@1.2.0: {}
3107
3397
3398
+
graceful-fs@4.2.11: {}
3399
+
3108
3400
graphemer@1.4.0: {}
3109
3401
3110
3402
has-flag@4.0.0: {}
···
3159
3451
3160
3452
iso-datestring-validator@2.2.2: {}
3161
3453
3454
+
jiti@2.4.2: {}
3455
+
3162
3456
jose@5.10.0: {}
3163
3457
3164
3458
js-tokens@4.0.0: {}
···
3186
3480
prelude-ls: 1.2.1
3187
3481
type-check: 0.4.0
3188
3482
3483
+
lightningcss-darwin-arm64@1.29.2:
3484
+
optional: true
3485
+
3486
+
lightningcss-darwin-x64@1.29.2:
3487
+
optional: true
3488
+
3489
+
lightningcss-freebsd-x64@1.29.2:
3490
+
optional: true
3491
+
3492
+
lightningcss-linux-arm-gnueabihf@1.29.2:
3493
+
optional: true
3494
+
3495
+
lightningcss-linux-arm64-gnu@1.29.2:
3496
+
optional: true
3497
+
3498
+
lightningcss-linux-arm64-musl@1.29.2:
3499
+
optional: true
3500
+
3501
+
lightningcss-linux-x64-gnu@1.29.2:
3502
+
optional: true
3503
+
3504
+
lightningcss-linux-x64-musl@1.29.2:
3505
+
optional: true
3506
+
3507
+
lightningcss-win32-arm64-msvc@1.29.2:
3508
+
optional: true
3509
+
3510
+
lightningcss-win32-x64-msvc@1.29.2:
3511
+
optional: true
3512
+
3513
+
lightningcss@1.29.2:
3514
+
dependencies:
3515
+
detect-libc: 2.0.4
3516
+
optionalDependencies:
3517
+
lightningcss-darwin-arm64: 1.29.2
3518
+
lightningcss-darwin-x64: 1.29.2
3519
+
lightningcss-freebsd-x64: 1.29.2
3520
+
lightningcss-linux-arm-gnueabihf: 1.29.2
3521
+
lightningcss-linux-arm64-gnu: 1.29.2
3522
+
lightningcss-linux-arm64-musl: 1.29.2
3523
+
lightningcss-linux-x64-gnu: 1.29.2
3524
+
lightningcss-linux-x64-musl: 1.29.2
3525
+
lightningcss-win32-arm64-msvc: 1.29.2
3526
+
lightningcss-win32-x64-msvc: 1.29.2
3527
+
3189
3528
locate-path@6.0.0:
3190
3529
dependencies:
3191
3530
p-locate: 5.0.0
···
3253
3592
minimatch@9.0.5:
3254
3593
dependencies:
3255
3594
brace-expansion: 2.0.1
3595
+
3596
+
minipass@7.1.2: {}
3597
+
3598
+
minizlib@3.0.2:
3599
+
dependencies:
3600
+
minipass: 7.1.2
3601
+
3602
+
mkdirp@3.0.1: {}
3256
3603
3257
3604
ms@2.1.3: {}
3258
3605
···
3534
3881
dependencies:
3535
3882
has-flag: 4.0.0
3536
3883
3884
+
tailwindcss@4.1.6: {}
3885
+
3886
+
tapable@2.2.1: {}
3887
+
3888
+
tar@7.4.3:
3889
+
dependencies:
3890
+
'@isaacs/fs-minipass': 4.0.1
3891
+
chownr: 3.0.0
3892
+
minipass: 7.1.2
3893
+
minizlib: 3.0.2
3894
+
mkdirp: 3.0.1
3895
+
yallist: 5.0.0
3896
+
3537
3897
tinyglobby@0.2.13:
3538
3898
dependencies:
3539
3899
fdir: 6.4.4(picomatch@4.0.2)
···
3563
3923
media-typer: 1.1.0
3564
3924
mime-types: 3.0.1
3565
3925
3566
-
typescript-eslint@8.32.0(eslint@9.26.0)(typescript@5.7.3):
3926
+
typescript-eslint@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3):
3567
3927
dependencies:
3568
-
'@typescript-eslint/eslint-plugin': 8.32.0(@typescript-eslint/parser@8.32.0(eslint@9.26.0)(typescript@5.7.3))(eslint@9.26.0)(typescript@5.7.3)
3569
-
'@typescript-eslint/parser': 8.32.0(eslint@9.26.0)(typescript@5.7.3)
3570
-
'@typescript-eslint/utils': 8.32.0(eslint@9.26.0)(typescript@5.7.3)
3571
-
eslint: 9.26.0
3928
+
'@typescript-eslint/eslint-plugin': 8.32.0(@typescript-eslint/parser@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3)
3929
+
'@typescript-eslint/parser': 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3)
3930
+
'@typescript-eslint/utils': 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3)
3931
+
eslint: 9.26.0(jiti@2.4.2)
3572
3932
typescript: 5.7.3
3573
3933
transitivePeerDependencies:
3574
3934
- supports-color
···
3609
3969
3610
3970
vary@1.1.2: {}
3611
3971
3612
-
vite@6.3.5:
3972
+
vite@6.3.5(jiti@2.4.2)(lightningcss@1.29.2):
3613
3973
dependencies:
3614
3974
esbuild: 0.25.4
3615
3975
fdir: 6.4.4(picomatch@4.0.2)
···
3619
3979
tinyglobby: 0.2.13
3620
3980
optionalDependencies:
3621
3981
fsevents: 2.3.3
3982
+
jiti: 2.4.2
3983
+
lightningcss: 1.29.2
3622
3984
3623
3985
which@2.0.2:
3624
3986
dependencies:
···
3657
4019
ws@8.18.0: {}
3658
4020
3659
4021
yallist@3.1.1: {}
4022
+
4023
+
yallist@5.0.0: {}
3660
4024
3661
4025
yocto-queue@0.1.0: {}
3662
4026
+66
-39
src/components/App.tsx
+66
-39
src/components/App.tsx
···
1
-
import { useContext, useState } from "react";
1
+
import { useContext, useState, useEffect } from "react";
2
2
import { ATProtoContext } from "../context.tsx";
3
3
import { RunForm } from "./RunForm.tsx";
4
4
import { SignIn } from "./SignIn.tsx";
5
-
import { AtUri } from "@atproto/api"
5
+
import { AtUri, BlobRef } from "@atproto/api"
6
6
import { Run } from "../../shared/run_lexicon.ts";
7
7
8
8
type RunsResponse = {
···
22
22
}
23
23
}
24
24
25
-
export function App() {
25
+
function RunList() {
26
26
const { session, agent } = useContext(ATProtoContext);
27
-
const [runsResponse, setRunsResponse] = useState<RunsResponse>({ records: [] });
27
+
const [runsResponse, setRunsResponse] = useState<RunsResponse | undefined>(undefined);
28
28
29
29
const fetchRuns = () => session && agent?.com.atproto.repo
30
30
.listRecords({ collection: "me.wilb.test.run", repo: session.did })
···
34
34
.deleteRecord({ collection: "me.wilb.test.run", repo: session.did, rkey })
35
35
.then(() => fetchRuns())
36
36
37
+
useEffect(() => {
38
+
if (!runsResponse) {
39
+
fetchRuns();
40
+
}
41
+
}, [session, agent])
42
+
43
+
const loadGPX = (uri: string, gpx: BlobRef) => {
44
+
const map = window.L.map(`map-${uri}`);
45
+
window.L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
46
+
attribution: 'Map data © <a href="http://www.osm.org">OpenStreetMap</a>'
47
+
}).addTo(map);
48
+
49
+
const options = {
50
+
async: true,
51
+
polyline_options: { color: 'red' },
52
+
};
53
+
54
+
new window.L.GPX(`${session?.server.issuer}/xrpc/com.atproto.sync.getBlob?did=${session?.did}&cid=${gpx.ref}`, options).on('loaded', (e: any) => {
55
+
map.fitBounds(e.target.getBounds());
56
+
}).addTo(map);
57
+
};
58
+
37
59
return (
38
-
<>
39
-
<h1>ProtoRuns: your runs, on ATProto</h1>
40
-
<p><a target="_blank" href="https://www.val.town/x/wilhelm/ProtoRuns/code/README.md">[src]</a></p>
41
-
{session && <RunForm />}
42
-
<SignIn />
43
-
{session && <button
44
-
type="button"
45
-
onClick={fetchRuns}>
46
-
Get my runs
47
-
</button>}
48
-
<div id="map"></div>
60
+
<div className="flex flex-col gap-2 p-2">
49
61
{runsResponse?.records.map(({ uri, value: { note, date_iso, distance_meters, duration_seconds, gpx } }) => (
50
-
<div>
51
-
<p>distance (kilometers): {distance_meters / 1000}</p>
52
-
<p>duration (minutes): {duration_seconds ?? 0 / 60}</p>
53
-
<p>date: {date_iso}</p>
54
-
<p>note: {note}</p>
55
-
{gpx && <p><button type="button" onClick={() => {
56
-
const map = window.L.map('map');
57
-
window.L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
58
-
attribution: 'Map data © <a href="http://www.osm.org">OpenStreetMap</a>'
59
-
}).addTo(map);
60
-
61
-
const options = {
62
-
async: true,
63
-
polyline_options: { color: 'red' },
64
-
};
65
-
66
-
new window.L.GPX(`${session?.server.issuer}/xrpc/com.atproto.sync.getBlob?did=${session?.did}&cid=${gpx.ref}`, options).on('loaded', (e: any) => {
67
-
map.fitBounds(e.target.getBounds());
68
-
}).addTo(map);
69
-
}}>Load gpx</button></p>}
70
-
<button type="button" onClick={() => deleteRun(new AtUri(uri).rkey)}>
71
-
delete
72
-
</button>
62
+
<div className="flex flex-row" key={uri}>
63
+
<div className="flex flex-col w-full gap-2 p-2">
64
+
<p>distance (kilometers): {distance_meters / 1000}</p>
65
+
<p>duration (minutes): {duration_seconds ?? 0 / 60}</p>
66
+
<p>date: {date_iso}</p>
67
+
<p>note: {note}</p>
68
+
<div className="flex flex-row gap-2 p-2">
69
+
{gpx && <button type="button" onClick={() => loadGPX(uri, gpx)}>Load gpx</button>}
70
+
<button type="button" onClick={() => deleteRun(new AtUri(uri).rkey)}>
71
+
delete
72
+
</button>
73
+
</div>
74
+
</div>
75
+
<div id={`map-${uri}`} data-active={!!gpx} className="flex w-full h-2 data-[active=true]:h-[180px]"></div>
73
76
</div>
74
77
))}
75
-
</>
78
+
</div>
76
79
);
80
+
}
81
+
82
+
export function App() {
83
+
const { session } = useContext(ATProtoContext);
84
+
85
+
return (
86
+
<div className="flex flex-col gap-2 p-2 items-center">
87
+
<aside className="w-full flex justify-between bg-amber-50 gap-2">
88
+
<h1 className="text-xl">MappedAt: map your runs and more</h1>
89
+
<SignIn />
90
+
</aside>
91
+
<main className="w-full flex flex-col gap-2 p-2 max-w-3xl">
92
+
{session &&
93
+
<details>
94
+
<summary>
95
+
New run form
96
+
</summary>
97
+
<RunForm />
98
+
</details>
99
+
}
100
+
<RunList />
101
+
</main>
102
+
</div>
103
+
)
77
104
}
+22
-10
src/components/RunForm.tsx
+22
-10
src/components/RunForm.tsx
···
49
49
}, null
50
50
)
51
51
return (
52
-
<>
53
-
<form action={submitRun}>
54
-
<input required name="distance_kilometers" type="number" placeholder="distance (in kilometers)" />
55
-
<input required name="date_iso" type="date" placeholder="date" />
56
-
<input required name="duration_minutes" type="number" placeholder="duration (in minutes)" />
57
-
<input name="note" type="text" placeholder="note" />
58
-
<span>GPX file: <input name="gpx" type="file" /></span>
59
-
<input type="submit" value="Submit run" />
52
+
<div className="flex justify-center">
53
+
<form action={submitRun} className="flex flex-col gap-2 p-2 w-xl">
54
+
<div className="outline-1 p-2 rounded-sm">
55
+
<input required name="distance_kilometers" type="number" placeholder="distance (in kilometers)" />
56
+
</div>
57
+
<div className="outline-1 p-2 rounded-sm">
58
+
<span>Date: <input required name="date_iso" type="date" placeholder="date" /></span>
59
+
</div>
60
+
<div className="outline-1 p-2 rounded-sm">
61
+
<input required name="duration_minutes" type="number" placeholder="duration (in minutes)" />
62
+
</div>
63
+
<div className="outline-1 p-2 rounded-sm">
64
+
<input name="note" type="text" placeholder="note" />
65
+
</div>
66
+
<div className="outline-1 p-2 rounded-sm">
67
+
<span>GPX file: <input name="gpx" type="file" /></span>
68
+
</div>
69
+
<div className="outline-1 p-2 rounded-sm">
70
+
<input type="submit" value="Submit run" />
71
+
</div>
60
72
</form>
61
73
{isPending && <p>submitting...</p>}
62
-
{error && <pre>{error as any}</pre>}
63
-
</>
74
+
{error ? <pre>{(error as Error).message}</pre> : ""}
75
+
</div>
64
76
)
65
77
}
+1
-18
src/index.css
+1
-18
src/index.css
+2
-1
vite.config.ts
+2
-1
vite.config.ts
···
2
2
import react from "@vitejs/plugin-react";
3
3
4
4
import { cloudflare } from "@cloudflare/vite-plugin";
5
+
import tailwindcss from "@tailwindcss/vite";
5
6
6
7
// https://vite.dev/config/
7
8
export default defineConfig({
8
-
plugins: [react(), cloudflare()],
9
+
plugins: [react(), cloudflare(), tailwindcss()],
9
10
server: {
10
11
allowedHosts: [
11
12
"currency-houston-arranged-scotia.trycloudflare.com",