@tokshare/pick 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,250 @@
1
+ "use strict";var TokSharePickBundle=(()=>{var nt=Object.defineProperty;var rt=(n,t,r)=>t in n?nt(n,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):n[t]=r;var M=(n,t,r)=>rt(n,typeof t!="symbol"?t+"":t,r);var te={maxFileBytes:5e7,maxFiles:20,maxSessionBytes:2e8,singlePutBytes:16777216,minPartBytes:8388608,maxParts:1e4,partBatch:10,idleMs:18e5,absoluteMs:72e5,fileTtlMs:6e5,codeTtlMs:6e5,maxDownloads:3,presignSeconds:900,sniffBytes:4096,directChunkBytes:65536,directConnectMs:8e3,directWaitMs:2500,directConfirmMs:2e4,maxSignalBytes:16384};var B=class extends Error{constructor(r,e,i=400){super(e||r);M(this,"code");M(this,"status");this.name="PickError",this.code=r,this.status=i}};function ke(n){let t=n.lastIndexOf(".");return t>0?n.slice(t).toLowerCase():""}function _e(n=""){let t={extensions:[],types:[],wildcards:[]};for(let r of n.split(",")){let e=r.trim().toLowerCase();e&&(e.startsWith(".")?t.extensions.push(e):/^[a-z0-9.+-]+\/\*$/.test(e)?t.wildcards.push(e.slice(0,-1)):/^[a-z0-9.+-]+\/[a-z0-9.+-]+$/.test(e)&&t.types.push(e))}return t}function it(n,t){let r=t.toLowerCase();return n.types.includes(r)||n.wildcards.some(e=>r.startsWith(e))}function Ie(n,t,r){let e=_e(n);return!e.extensions.length&&!e.types.length&&!e.wildcards.length?!0:e.extensions.includes(ke(t))||!!r&&it(e,r)}var F=(n,t,r)=>String.fromCharCode(...n.subarray(t,t+r)),O=(n,t,r=0)=>t.every((e,i)=>n[r+i]===e);function Be(n){if(n.length<4)return null;if(O(n,[255,216,255]))return"image/jpeg";if(O(n,[137,80,78,71,13,10,26,10]))return"image/png";if(F(n,0,4)==="GIF8")return"image/gif";if(F(n,0,4)==="RIFF"&&F(n,8,4)==="WEBP")return"image/webp";if(F(n,0,4)==="RIFF"&&F(n,8,4)==="WAVE")return"audio/wav";if(F(n,0,4)==="RIFF"&&F(n,8,4)==="AVI ")return"video/x-msvideo";if(F(n,4,4)==="ftyp"){let r=F(n,8,4);return/^(heic|heix|hevc|hevx|heim|heis)$/.test(r)?"image/heic":r==="mif1"||r==="msf1"?"image/heif":r==="avif"||r==="avis"?"image/avif":r==="qt "?"video/quicktime":/^(M4A |M4B )$/.test(r)?"audio/mp4":/^3g/.test(r)?"video/3gpp":"video/mp4"}if(F(n,0,5)==="%PDF-")return"application/pdf";if(O(n,[80,75,3,4])||O(n,[80,75,5,6]))return"application/zip";if(O(n,[31,139]))return"application/gzip";if(O(n,[55,122,188,175,39,28]))return"application/x-7z-compressed";if(F(n,0,4)==="Rar!")return"application/vnd.rar";if(F(n,0,3)==="ID3"||O(n,[255,251])||O(n,[255,243]))return"audio/mpeg";if(F(n,0,4)==="OggS")return"audio/ogg";if(F(n,0,4)==="fLaC")return"audio/flac";if(O(n,[26,69,223,163]))return"video/webm";if(O(n,[208,207,17,224,161,177,26,225]))return"application/x-ole-storage";if(F(n,0,2)==="MZ")return"application/x-msdownload";if(O(n,[127,69,76,70]))return"application/x-elf";if(O(n,[207,250,237,254])||O(n,[254,237,250,207]))return"application/x-mach-binary";let t=F(n,0,Math.min(n.length,256)).replace(/^/,"").trimStart().toLowerCase();return t.startsWith("<svg")||t.startsWith("<?xml")&&t.includes("<svg")?"image/svg+xml":t.startsWith("<!doctype html")||t.startsWith("<html")?"text/html":null}var ot=/^(application\/(zip|x-zip-compressed|epub\+zip|vnd\.android\.package-archive|java-archive|vnd\.openxmlformats-officedocument\..+|vnd\.oasis\.opendocument\..+))$/,st=/^application\/(msword|vnd\.ms-excel|vnd\.ms-powerpoint|vnd\.ms-outlook|x-ole-storage)$/,at=new Set(["application/x-msdownload","application/x-elf","application/x-mach-binary","text/html","image/svg+xml"]);function Oe(n,t,r,e){if(!e)return!0;let i=_e(n),o=r.toLowerCase(),a=s=>s===e||e==="application/zip"&&ot.test(s)||e==="application/x-ole-storage"&&st.test(s)||e==="image/heif"&&s==="image/heic"||e==="video/mp4"&&/^(video|audio)\//.test(s);return at.has(e)?i.types.includes(e)||e==="image/svg+xml"&&i.extensions.includes(".svg"):!i.types.length&&!i.wildcards.length||i.types.some(a)||i.wildcards.some(s=>e.startsWith(s))?!0:i.extensions.includes(ke(t))&&(a(o)||!o)}var De="tokshare.announce.hidden",lt="https://tokshare.vercel.app/?ref=pick",ct=()=>{try{return localStorage.getItem(De)==="1"}catch{return!1}};function fe(n,t){if(n===!1||ct())return null;let r=document.createElement("p");r.className="announce";let e=document.createElement("i");e.setAttribute("aria-hidden","true");let i=document.createElement("span");i.textContent=`${t("announceText")} `;let o=document.createElement("a");o.href=lt,o.target="_blank",o.rel="noopener",o.textContent=t("announceLink"),i.append(o);let a=document.createElement("button");return a.type="button",a.className="announce-hide",a.textContent="\xD7",a.setAttribute("aria-label",t("announceHide")),a.addEventListener("click",()=>{try{localStorage.setItem(De,"1")}catch{}r.remove()}),r.append(e,i,a),r}var we=`
2
+ :host { display: block; }
3
+ * { box-sizing: border-box; }
4
+ [hidden] { display: none !important; }
5
+ .wrap {
6
+ /* Light. Lime is unreadable as text or a thin line on white, so those use a deeper violet. */
7
+ --accent: var(--tsp-accent, #c8ff4d);
8
+ --accent-text: var(--tsp-accent-text, #0b0d12);
9
+ --accent-ink: var(--tsp-accent-ink, var(--tsp-accent, #6b4fe0));
10
+ --accent-2: var(--tsp-accent-2, var(--tsp-accent, #8a6cf5));
11
+ --button-edge: rgba(11, 13, 18, .1);
12
+ --bg: var(--tsp-bg, #ffffff);
13
+ --surface: var(--tsp-surface, #f6f7f9);
14
+ --text: var(--tsp-text, #0b0d12);
15
+ --muted: var(--tsp-muted, #5d6270);
16
+ --line: var(--tsp-line, rgba(11, 13, 18, .12));
17
+ --ok: #1a8a4c;
18
+ --error: #c42f3d;
19
+ --radius: var(--tsp-radius, 18px);
20
+ container-type: inline-size;
21
+ font: 14px/1.5 var(--tsp-font, Inter, system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans Arabic", sans-serif);
22
+ color: var(--text);
23
+ }
24
+ @media (prefers-color-scheme: dark) {
25
+ .wrap[data-theme="auto"] { --accent-ink: var(--tsp-accent-ink, var(--tsp-accent, #c8ff4d)); --accent-2: var(--tsp-accent-2, var(--tsp-accent, #9a7cff)); --button-edge: transparent; --bg: var(--tsp-bg, #171a22); --surface: var(--tsp-surface, #12151c); --text: var(--tsp-text, #f4f4f5); --muted: var(--tsp-muted, #9297a4); --line: var(--tsp-line, rgba(255,255,255,.09)); --ok: #c8ff4d; --error: #ff8a94; }
26
+ }
27
+ .wrap[data-theme="dark"] { --accent-ink: var(--tsp-accent-ink, var(--tsp-accent, #c8ff4d)); --accent-2: var(--tsp-accent-2, var(--tsp-accent, #9a7cff)); --button-edge: transparent; --bg: var(--tsp-bg, #171a22); --surface: var(--tsp-surface, #12151c); --text: var(--tsp-text, #f4f4f5); --muted: var(--tsp-muted, #9297a4); --line: var(--tsp-line, rgba(255,255,255,.09)); --ok: #c8ff4d; --error: #ff8a94; }
28
+
29
+ /* ---- drop zone ---- */
30
+ .zone {
31
+ position: relative;
32
+ border: 1.5px dashed color-mix(in srgb, var(--accent-ink) 42%, transparent);
33
+ border-radius: var(--radius);
34
+ background:
35
+ radial-gradient(120% 90% at 50% 0%, color-mix(in srgb, var(--accent-2) 12%, transparent), transparent 70%),
36
+ var(--surface);
37
+ padding: 30px 22px;
38
+ min-height: 232px;
39
+ display: grid;
40
+ align-items: center;
41
+ transition: border-color .18s, background-color .18s, box-shadow .18s;
42
+ }
43
+ .zone[data-state="idle"]:hover { border-color: color-mix(in srgb, var(--accent-ink) 70%, transparent); }
44
+ .zone[data-drag] {
45
+ border-style: solid;
46
+ border-color: var(--accent-ink);
47
+ background-color: color-mix(in srgb, var(--accent-ink) 8%, var(--surface));
48
+ box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent-ink) 16%, transparent);
49
+ }
50
+ .zone[data-drag] .tile { transform: translateY(-3px) scale(1.06); }
51
+ .idle { display: grid; justify-items: center; text-align: center; gap: 6px; }
52
+ .tile {
53
+ width: 56px; height: 56px; margin-bottom: 8px;
54
+ display: grid; place-items: center;
55
+ border-radius: 16px;
56
+ background: linear-gradient(145deg, color-mix(in srgb, var(--accent) 80%, #fff), var(--accent));
57
+ color: var(--accent-text);
58
+ box-shadow: inset 0 1px 0 rgba(255,255,255,.45), inset 0 0 0 1px var(--button-edge), 0 12px 26px -6px color-mix(in srgb, var(--accent) 45%, transparent);
59
+ transition: transform .2s;
60
+ }
61
+ svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; flex: none; }
62
+ .tile svg { width: 26px; height: 26px; stroke-width: 2; }
63
+ .title { margin: 0; font-size: 16px; font-weight: 650; letter-spacing: -.01em; }
64
+ .hint { margin: 0; color: var(--muted); font-size: 13px; }
65
+ .actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 10px; margin-top: 12px; }
66
+ .or { color: var(--muted); font-size: 12.5px; }
67
+
68
+ button { font: inherit; cursor: pointer; }
69
+ .primary, .ghost {
70
+ display: inline-flex; align-items: center; gap: 8px;
71
+ min-height: 40px; padding: 8px 16px;
72
+ border-radius: 11px; font-weight: 600; font-size: 14px;
73
+ border: 1px solid transparent;
74
+ transition: transform .12s, box-shadow .15s, background-color .15s, border-color .15s;
75
+ }
76
+ .primary { background: var(--accent); color: var(--accent-text); border-color: var(--button-edge); box-shadow: inset 0 1px 0 rgba(255,255,255,.45), 0 8px 22px -8px color-mix(in srgb, var(--accent) 60%, transparent); }
77
+ .primary:hover { background: color-mix(in srgb, var(--accent) 85%, #fff); box-shadow: inset 0 1px 0 rgba(255,255,255,.5), 0 12px 28px -8px color-mix(in srgb, var(--accent) 70%, transparent); }
78
+ .ghost { background: var(--bg); color: var(--text); border-color: var(--line); }
79
+ .ghost:hover { border-color: color-mix(in srgb, var(--accent-ink) 55%, transparent); color: var(--accent-ink); }
80
+ .primary:active, .ghost:active { transform: translateY(1px); }
81
+ .primary.small { min-height: 34px; padding: 6px 14px; font-size: 13px; }
82
+ .link { all: unset; cursor: pointer; display: inline-flex; align-items: center; gap: 4px; color: var(--muted); font-weight: 600; font-size: 13px; }
83
+ .link:hover { color: var(--text); }
84
+ button:focus-visible, .link:focus-visible { outline: 3px solid color-mix(in srgb, var(--accent-ink) 60%, transparent); outline-offset: 2px; border-radius: 10px; }
85
+ [dir="rtl"] .flip { transform: scaleX(-1); }
86
+
87
+ /* ---- phone, inside the field ---- */
88
+ .phone-view { display: grid; grid-template-columns: auto 1fr; gap: 24px; align-items: center; }
89
+ .qr-box { position: relative; width: 184px; height: 184px; padding: 8px; border-radius: 16px; background: #fff; border: 1px solid var(--line); box-shadow: 0 10px 30px rgba(15, 18, 30, .1); }
90
+ .qr { width: 100%; height: 100%; display: block; image-rendering: pixelated; transition: opacity .25s, filter .25s; }
91
+ .qr-box.dim .qr { opacity: .18; filter: blur(1px); }
92
+ .qr-loading { display: none; position: absolute; inset: 8px; border-radius: 10px; background: linear-gradient(100deg, #eef0f5 30%, #f8f9fc 50%, #eef0f5 70%); background-size: 200% 100%; animation: shimmer 1.2s linear infinite; }
93
+ .qr-box.loading .qr-loading { display: block; }
94
+ .phone-info { display: grid; gap: 10px; min-width: 0; }
95
+ .steps { margin: 0; padding: 0; list-style: none; counter-reset: step; display: grid; gap: 7px; }
96
+ .steps li { counter-increment: step; display: flex; gap: 10px; align-items: baseline; color: var(--muted); font-size: 13.5px; }
97
+ .steps li::before { content: counter(step); flex: none; width: 20px; height: 20px; display: inline-grid; place-items: center; border-radius: 50%; font-size: 11px; font-weight: 700; color: var(--accent-ink); background: color-mix(in srgb, var(--accent-ink) 14%, transparent); transform: translateY(4px); }
98
+ .code-line { margin: 0; color: var(--muted); font-size: 12.5px; }
99
+ .code-line b { direction: ltr; display: inline-block; font: 700 13px/1.4 ui-monospace, "SF Mono", Menlo, Consolas, monospace; letter-spacing: 1.2px; color: var(--text); background: var(--bg); border: 1px solid var(--line); padding: 1px 7px; border-radius: 6px; }
100
+ .status { margin: 0; justify-self: start; display: inline-flex; align-items: center; gap: 8px; padding: 6px 12px; border-radius: 999px; background: var(--bg); border: 1px solid var(--line); font-size: 13px; font-weight: 600; }
101
+ .status i { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); opacity: .6; }
102
+ .status.live i { background: var(--ok); opacity: 1; box-shadow: 0 0 0 0 color-mix(in srgb, var(--ok) 60%, transparent); animation: pulse 1.8s infinite; }
103
+ .phone-actions { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 2px; }
104
+ .announce-slot { grid-column: 1 / -1; }
105
+ /* ---- TokShare for desktop ---- */
106
+ .announce { margin: 0; display: flex; align-items: center; gap: 10px; padding: 9px 8px 9px 12px; border-radius: 12px; border: 1px solid var(--line); background: color-mix(in srgb, var(--accent-2) 7%, transparent); color: var(--muted); font-size: 12.5px; line-height: 1.45; text-align: start; }
107
+ .announce i { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--accent-2); }
108
+ .announce span { flex: 1; min-width: 0; }
109
+ .announce a { color: var(--accent-ink); font-weight: 650; text-decoration: underline; text-underline-offset: 2px; white-space: nowrap; }
110
+ .announce-hide { all: unset; cursor: pointer; flex: none; width: 24px; height: 24px; display: grid; place-items: center; border-radius: 50%; font-size: 16px; color: var(--muted); }
111
+ .announce-hide:hover { background: color-mix(in srgb, var(--text) 8%, transparent); color: var(--text); }
112
+ .announce-hide:focus-visible, .announce a:focus-visible { outline: 3px solid color-mix(in srgb, var(--accent-ink) 60%, transparent); outline-offset: 2px; }
113
+
114
+ /* ---- messages and list ---- */
115
+ .message { margin: 10px 2px 0; color: var(--error); font-size: 13px; }
116
+ .list-head { display: flex; justify-content: space-between; align-items: center; margin: 14px 2px 6px; color: var(--muted); font-size: 12.5px; font-weight: 600; }
117
+ .list { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 8px; }
118
+ .list-head:not([hidden]) + .list { margin-top: 0; }
119
+ .item { display: grid; grid-template-columns: 44px minmax(0, 1fr) auto; gap: 12px; align-items: center; padding: 9px 10px 9px 9px; border: 1px solid var(--line); border-radius: 14px; background: var(--bg); animation: rise .2s ease-out; }
120
+ .thumb { width: 44px; height: 44px; border-radius: 10px; overflow: hidden; display: grid; place-items: center; background: color-mix(in srgb, var(--accent-ink) 12%, transparent); color: var(--accent-ink); font-size: 10.5px; font-weight: 800; letter-spacing: .4px; }
121
+ .thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
122
+ .body { display: grid; gap: 2px; min-width: 0; }
123
+ .name { font-weight: 600; font-size: 13.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
124
+ .meta { color: var(--muted); font-size: 12px; }
125
+ .bar { height: 4px; border-radius: 4px; margin-top: 4px; background: color-mix(in srgb, var(--accent-ink) 12%, transparent); overflow: hidden; }
126
+ .bar i { display: block; height: 100%; width: 0; background: linear-gradient(90deg, var(--accent-2), var(--accent)); border-radius: inherit; transition: width .2s; }
127
+ .item.failed .meta { color: var(--error); }
128
+ .remove { all: unset; cursor: pointer; width: 32px; height: 32px; display: grid; place-items: center; border-radius: 50%; color: var(--muted); }
129
+ .remove:hover { background: color-mix(in srgb, var(--error) 10%, transparent); color: var(--error); }
130
+ .remove svg { width: 16px; height: 16px; }
131
+
132
+ @container (max-width: 520px) {
133
+ .zone { padding: 24px 16px; }
134
+ .phone-view { grid-template-columns: 1fr; justify-items: center; text-align: center; gap: 16px; }
135
+ .steps li { text-align: start; }
136
+ .status { justify-self: center; }
137
+ }
138
+ @keyframes shimmer { to { background-position: -200% 0; } }
139
+ @keyframes pulse { 70% { box-shadow: 0 0 0 7px transparent; } 100% { box-shadow: 0 0 0 0 transparent; } }
140
+ @keyframes rise { from { opacity: 0; transform: translateY(4px); } }
141
+ @media (prefers-reduced-motion: reduce) { .zone, .tile, .qr, .bar i, .item { transition: none; animation: none; } .qr-loading, .status.live i { animation: none; } }
142
+ `;var dt={title:"Pick files from your phone",titleOne:"Pick a file from your phone",scan:"Scan with your phone's camera",orType:"No camera? Open {host} on your phone and type",loading:"Getting a code\u2026",waiting:"Waiting for your phone\u2026",connected:"Connected: {label}",connectedDirect:"Connected over Wi-Fi: {label}",disconnect:"Not you? Disconnect",phoneLeft:"Your phone disconnected. It reconnects by itself when the page is open.",approveTitle:"Approve this phone?",approveMatch:"Your phone should show {match}.",approve:"Approve",reject:"Reject",sending:"Sending from phone {percent}%",receiving:"Receiving {percent}%",received:"Received",failed:"Not received",cancel:"Cancel",done:"Done",useFiles:"Use {count} files",useFile:"Use this file",expired:"This code expired.",newCode:"Get a new code",error:"Couldn't start: {message}",tryAgain:"Try again",close:"Close",privacy:"Files go straight to this site and are deleted from TokShare once received.",dropTitle:"Drag & drop files here",dropTitleOne:"Drag & drop a file here",dropActive:"Drop to add",or:"or",browse:"Browse files",usePhone:"Use your phone",hintTypes:"{types} \xB7 up to {size}",hintAny:"Any file \xB7 up to {size}",hintCount:"Up to {count} files",phoneTitle:"Scan with your phone",phoneStep1:"Open your phone's camera and scan the code",phoneStep2:"Pick photos or files on your phone",phoneStep3:"They appear here as they arrive",phoneCode:"No camera? Open {host} and type",back:"Back",doneWithPhone:"Done",sourcePhone:"From phone",sourceDevice:"This device",remove:"Remove {name}",tooLarge:"{name} is larger than {size}.",wrongType:"{name} isn't an accepted file type.",tooMany:"You can add up to {count} files.",fileCount:"{count} files",clearAll:"Remove all",announceText:"Move photos between your phone and your own PC anytime, over Wi-Fi.",announceLink:"Get TokShare for desktop",announceHide:"Hide"},pt={title:"\u0627\u062E\u062A\u0631 \u0645\u0644\u0641\u0627\u062A \u0645\u0646 \u0647\u0627\u062A\u0641\u0643",titleOne:"\u0627\u062E\u062A\u0631 \u0645\u0644\u0641\u064B\u0627 \u0645\u0646 \u0647\u0627\u062A\u0641\u0643",scan:"\u0627\u0645\u0633\u062D \u0627\u0644\u0631\u0645\u0632 \u0628\u0643\u0627\u0645\u064A\u0631\u0627 \u0647\u0627\u062A\u0641\u0643",orType:"\u0644\u0627 \u062A\u0648\u062C\u062F \u0643\u0627\u0645\u064A\u0631\u0627\u061F \u0627\u0641\u062A\u062D {host} \u0639\u0644\u0649 \u0647\u0627\u062A\u0641\u0643 \u0648\u0627\u0643\u062A\u0628",loading:"\u062C\u0627\u0631\u064D \u062A\u062C\u0647\u064A\u0632 \u0627\u0644\u0631\u0645\u0632\u2026",waiting:"\u0641\u064A \u0627\u0646\u062A\u0638\u0627\u0631 \u0647\u0627\u062A\u0641\u0643\u2026",connected:"\u0645\u062A\u0635\u0644: {label}",connectedDirect:"\u0645\u062A\u0635\u0644 \u0639\u0628\u0631 Wi-Fi: {label}",disconnect:"\u0644\u064A\u0633 \u0647\u0627\u062A\u0641\u0643\u061F \u0627\u0641\u0635\u0644\u0647",phoneLeft:"\u0627\u0646\u0642\u0637\u0639 \u0627\u062A\u0635\u0627\u0644 \u0647\u0627\u062A\u0641\u0643. \u0633\u064A\u0639\u0648\u062F \u062A\u0644\u0642\u0627\u0626\u064A\u064B\u0627 \u0645\u0627 \u062F\u0627\u0645\u062A \u0627\u0644\u0635\u0641\u062D\u0629 \u0645\u0641\u062A\u0648\u062D\u0629 \u0639\u0644\u064A\u0647.",approveTitle:"\u0647\u0644 \u062A\u0648\u0627\u0641\u0642 \u0639\u0644\u0649 \u0647\u0630\u0627 \u0627\u0644\u0647\u0627\u062A\u0641\u061F",approveMatch:"\u064A\u062C\u0628 \u0623\u0646 \u064A\u0639\u0631\u0636 \u0647\u0627\u062A\u0641\u0643 \u0627\u0644\u0631\u0642\u0645 {match}.",approve:"\u0645\u0648\u0627\u0641\u0642\u0629",reject:"\u0631\u0641\u0636",sending:"\u062C\u0627\u0631\u064D \u0627\u0644\u0625\u0631\u0633\u0627\u0644 \u0645\u0646 \u0627\u0644\u0647\u0627\u062A\u0641 {percent}%",receiving:"\u062C\u0627\u0631\u064D \u0627\u0644\u0627\u0633\u062A\u0644\u0627\u0645 {percent}%",received:"\u062A\u0645 \u0627\u0644\u0627\u0633\u062A\u0644\u0627\u0645",failed:"\u0644\u0645 \u064A\u064F\u0633\u062A\u0644\u0645",cancel:"\u0625\u0644\u063A\u0627\u0621",done:"\u062A\u0645",useFiles:"\u0627\u0633\u062A\u062E\u062F\u0645 {count} \u0645\u0644\u0641\u0627\u062A",useFile:"\u0627\u0633\u062A\u062E\u062F\u0645 \u0647\u0630\u0627 \u0627\u0644\u0645\u0644\u0641",expired:"\u0627\u0646\u062A\u0647\u062A \u0635\u0644\u0627\u062D\u064A\u0629 \u0647\u0630\u0627 \u0627\u0644\u0631\u0645\u0632.",newCode:"\u0627\u062D\u0635\u0644 \u0639\u0644\u0649 \u0631\u0645\u0632 \u062C\u062F\u064A\u062F",error:"\u062A\u0639\u0630\u0651\u0631 \u0627\u0644\u0628\u062F\u0621: {message}",tryAgain:"\u062D\u0627\u0648\u0644 \u0645\u0631\u0629 \u0623\u062E\u0631\u0649",close:"\u0625\u063A\u0644\u0627\u0642",privacy:"\u062A\u0635\u0644 \u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0645\u0628\u0627\u0634\u0631\u0629 \u0625\u0644\u0649 \u0647\u0630\u0627 \u0627\u0644\u0645\u0648\u0642\u0639\u060C \u0648\u064A\u062D\u0630\u0641\u0647\u0627 TokShare \u0641\u0648\u0631 \u0627\u0633\u062A\u0644\u0627\u0645\u0647\u0627.",dropTitle:"\u0627\u0633\u062D\u0628 \u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0648\u0623\u0641\u0644\u062A\u0647\u0627 \u0647\u0646\u0627",dropTitleOne:"\u0627\u0633\u062D\u0628 \u0645\u0644\u0641\u064B\u0627 \u0648\u0623\u0641\u0644\u062A\u0647 \u0647\u0646\u0627",dropActive:"\u0623\u0641\u0644\u062A \u0644\u0644\u0625\u0636\u0627\u0641\u0629",or:"\u0623\u0648",browse:"\u062A\u0635\u0641\u0651\u062D \u0627\u0644\u0645\u0644\u0641\u0627\u062A",usePhone:"\u0627\u0633\u062A\u062E\u062F\u0645 \u0647\u0627\u062A\u0641\u0643",hintTypes:"{types} \xB7 \u062D\u062A\u0649 {size}",hintAny:"\u0623\u064A \u0645\u0644\u0641 \xB7 \u062D\u062A\u0649 {size}",hintCount:"\u062D\u062A\u0649 {count} \u0645\u0644\u0641\u0627\u062A",phoneTitle:"\u0627\u0645\u0633\u062D \u0627\u0644\u0631\u0645\u0632 \u0628\u0647\u0627\u062A\u0641\u0643",phoneStep1:"\u0627\u0641\u062A\u062D \u0643\u0627\u0645\u064A\u0631\u0627 \u0647\u0627\u062A\u0641\u0643 \u0648\u0627\u0645\u0633\u062D \u0627\u0644\u0631\u0645\u0632",phoneStep2:"\u0627\u062E\u062A\u0631 \u0627\u0644\u0635\u0648\u0631 \u0623\u0648 \u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0639\u0644\u0649 \u0647\u0627\u062A\u0641\u0643",phoneStep3:"\u062A\u0638\u0647\u0631 \u0647\u0646\u0627 \u0641\u0648\u0631 \u0648\u0635\u0648\u0644\u0647\u0627",phoneCode:"\u0644\u0627 \u062A\u0648\u062C\u062F \u0643\u0627\u0645\u064A\u0631\u0627\u061F \u0627\u0641\u062A\u062D {host} \u0648\u0627\u0643\u062A\u0628",back:"\u0631\u062C\u0648\u0639",doneWithPhone:"\u062A\u0645",sourcePhone:"\u0645\u0646 \u0627\u0644\u0647\u0627\u062A\u0641",sourceDevice:"\u0647\u0630\u0627 \u0627\u0644\u062C\u0647\u0627\u0632",remove:"\u0625\u0632\u0627\u0644\u0629 {name}",tooLarge:"{name} \u0623\u0643\u0628\u0631 \u0645\u0646 {size}.",wrongType:"{name} \u0644\u064A\u0633 \u0645\u0646 \u0623\u0646\u0648\u0627\u0639 \u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0627\u0644\u0645\u0642\u0628\u0648\u0644\u0629.",tooMany:"\u064A\u0645\u0643\u0646\u0643 \u0625\u0636\u0627\u0641\u0629 {count} \u0645\u0644\u0641\u0627\u062A \u0643\u062D\u062F \u0623\u0642\u0635\u0649.",fileCount:"{count} \u0645\u0644\u0641\u0627\u062A",clearAll:"\u0625\u0632\u0627\u0644\u0629 \u0627\u0644\u0643\u0644",announceText:"\u0627\u0646\u0642\u0644 \u0627\u0644\u0635\u0648\u0631 \u0628\u064A\u0646 \u0647\u0627\u062A\u0641\u0643 \u0648\u0643\u0645\u0628\u064A\u0648\u062A\u0631\u0643 \u0641\u064A \u0623\u064A \u0648\u0642\u062A \u0639\u0628\u0631 Wi-Fi.",announceLink:"\u062D\u0645\u0651\u0644 TokShare \u0644\u0644\u0643\u0645\u0628\u064A\u0648\u062A\u0631",announceHide:"\u0625\u062E\u0641\u0627\u0621"},ut={en:dt,ar:pt};function he(n){if(n==="en"||n==="ar")return n;let r=(typeof document<"u"?document.documentElement.lang:"")||(typeof navigator<"u"?navigator.language:"en");return/^ar\b/i.test(r)?"ar":"en"}function me(n,t={}){return(r,e={})=>(t[r]??ut[n][r]).replace(/\{(\w+)\}/g,(i,o)=>String(e[o]??""))}function ne(n,t){let r=t==="ar"?["\u0628\u0627\u064A\u062A","\u0643.\u0628","\u0645.\u0628","\u062C.\u0628"]:["B","KB","MB","GB"],e=n,i=0;for(;e>=1e3&&i<r.length-1;)e/=1e3,i++;return`${(e>=100||i===0?Math.round(e):Math.round(e*10)/10).toLocaleString(t)} ${r[i]}`}var He="https://tokshare-pick.pjturki.workers.dev",Ne="0.1.1";function $e(n,t,r,e,i){if(r!==n.size||r>i)return{ok:!1,code:"size_mismatch"};let o=new Uint8Array(Math.min(r,te.sniffBytes)),a=0;for(let f of t){if(a>=o.length)break;let v=f.subarray(0,o.length-a);o.set(v,a),a+=v.length}let s=Be(o);return Oe(e,n.name,n.type,s)?{ok:!0,file:new File(t,n.name,{type:n.type||s||"",lastModified:n.lastModified}),sniffed:s}:{ok:!1,code:"type_rejected"}}var le=class n{constructor(t,r){M(this,"signal",t);M(this,"handlers",r);M(this,"pc",null);M(this,"channel",null);M(this,"id","");M(this,"isOpen",!1);M(this,"current",null)}static supported(){return typeof RTCPeerConnection=="function"}onSignal(t){if(t.kind==="offer"&&t.sdp){this.answer(t.pc,t.sdp);return}t.pc!==this.id||!this.pc||(t.kind==="ice"&&t.candidate?this.pc.addIceCandidate(t.candidate).catch(()=>{}):t.kind==="bye"&&this.close())}answer(t,r){if(!n.supported())return;this.close(),this.id=t;let e=new RTCPeerConnection({iceServers:[]});this.pc=e,e.onicecandidate=i=>{this.id===t&&this.signal({pc:t,kind:"ice",candidate:i.candidate?i.candidate.toJSON():null})},e.onconnectionstatechange=()=>{this.id===t&&(e.connectionState==="failed"||e.connectionState==="closed")&&this.close()},e.ondatachannel=i=>{if(this.id!==t)return;let o=i.channel;o.binaryType="arraybuffer",this.channel=o;let a=()=>{this.channel===o&&!this.isOpen&&(this.isOpen=!0,this.handlers.state(!0))};o.onopen=a,o.onclose=()=>{this.channel===o&&this.close()},o.onmessage=s=>this.onMessage(o,s.data),o.readyState==="open"&&a()},e.setRemoteDescription({type:"offer",sdp:r}).then(()=>e.createAnswer()).then(i=>e.setLocalDescription(i)).then(()=>{this.id===t&&this.signal({pc:t,kind:"answer",sdp:e.localDescription.sdp})}).catch(()=>this.close())}onMessage(t,r){if(typeof r!="string"){let i=this.current;if(!i||!(r instanceof ArrayBuffer))return;if(i.chunks.push(new Uint8Array(r)),i.received+=r.byteLength,i.received>i.size){i.chunks=[];return}this.handlers.progress(i.id,i.received,i.size);return}let e;try{e=JSON.parse(r)}catch{return}if(e.t==="file"&&typeof e.id=="string"&&Number.isSafeInteger(e.size))this.current={id:e.id,size:e.size,chunks:[],received:0};else if(e.t==="end"&&this.current?.id===e.id){let{id:i,chunks:o,received:a}=this.current;this.current=null,this.handlers.complete(i,o,a).then(s=>s,()=>({ok:!1,code:"failed"})).then(s=>{let p=s.ok?{t:"got",id:i}:{t:"bad",id:i,code:s.code};try{t.send(JSON.stringify(p))}catch{}})}}close(){let t=this.isOpen;this.isOpen=!1;let{pc:r,channel:e}=this;this.pc=null,this.channel=null,this.current=null;try{e?.close()}catch{}try{r?.close()}catch{}t&&this.handlers.state(!1)}};var re=(n=>(n[n.Border=-1]="Border",n[n.Data=0]="Data",n[n.Function=1]="Function",n[n.Position=2]="Position",n[n.Timing=3]="Timing",n[n.Alignment=4]="Alignment",n))(re||{}),ft=[0,1],qe=[1,0],je=[2,3],We=[3,2],ht={L:ft,M:qe,Q:je,H:We},mt=/^\d*$/,gt=/^[A-Z0-9 $%*+./:-]*$/,Ee="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:",Ce=1,Te=40,Ue=3,xt=3,ge=40,bt=10,Ke=[[-1,7,10,15,20,26,18,20,24,30,18,20,24,26,30,22,24,28,30,28,28,28,28,30,30,26,28,30,30,30,30,30,30,30,30,30,30,30,30,30,30],[-1,10,16,26,18,24,16,18,22,22,26,30,22,22,24,24,28,28,26,26,26,26,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28],[-1,13,22,18,26,18,24,18,22,20,24,28,26,24,20,30,24,28,28,26,30,28,30,30,30,30,28,30,30,30,30,30,30,30,30,30,30,30,30,30,30],[-1,17,28,22,16,22,28,26,26,24,28,24,28,22,24,24,30,28,28,26,28,30,24,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30]],Ye=[[-1,1,1,1,1,1,2,2,2,2,4,4,4,4,4,6,6,6,6,7,8,8,9,9,10,12,12,12,13,14,15,16,17,18,19,19,20,21,22,24,25],[-1,1,1,1,2,2,4,4,4,5,5,5,8,9,9,10,10,11,13,14,16,17,17,18,20,21,23,25,26,28,29,31,33,35,37,38,40,43,45,47,49],[-1,1,1,2,2,4,4,6,6,8,8,8,10,12,16,12,17,16,18,21,20,23,23,25,27,29,34,34,35,38,40,43,45,48,51,53,56,59,62,65,68],[-1,1,1,2,4,4,4,5,6,8,8,11,11,16,16,18,16,19,21,25,25,25,34,30,32,35,37,40,42,45,48,51,54,57,60,63,66,70,74,77,81]],Me=class{constructor(t,r,e,i){M(this,"size");M(this,"mask");M(this,"modules",[]);M(this,"types",[]);if(this.version=t,this.ecc=r,t<Ce||t>Te)throw new RangeError("Version value out of range");if(i<-1||i>7)throw new RangeError("Mask value out of range");this.size=t*4+17;let o=Array.from({length:this.size}).fill(!1);for(let s=0;s<this.size;s++)this.modules.push(o.slice()),this.types.push(o.map(()=>0));this.drawFunctionPatterns();let a=this.addEccAndInterleave(e);if(this.drawCodewords(a),i===-1){let s=1e9;for(let p=0;p<8;p++){this.applyMask(p),this.drawFormatBits(p);let f=this.getPenaltyScore();f<s&&(i=p,s=f),this.applyMask(p)}}this.mask=i,this.applyMask(i),this.drawFormatBits(i)}getModule(t,r){return t>=0&&t<this.size&&r>=0&&r<this.size&&this.modules[r][t]}drawFunctionPatterns(){for(let e=0;e<this.size;e++)this.setFunctionModule(6,e,e%2===0,re.Timing),this.setFunctionModule(e,6,e%2===0,re.Timing);this.drawFinderPattern(3,3),this.drawFinderPattern(this.size-4,3),this.drawFinderPattern(3,this.size-4);let t=this.getAlignmentPatternPositions(),r=t.length;for(let e=0;e<r;e++)for(let i=0;i<r;i++)e===0&&i===0||e===0&&i===r-1||e===r-1&&i===0||this.drawAlignmentPattern(t[e],t[i]);this.drawFormatBits(0),this.drawVersion()}drawFormatBits(t){let r=this.ecc[1]<<3|t,e=r;for(let o=0;o<10;o++)e=e<<1^(e>>>9)*1335;let i=(r<<10|e)^21522;for(let o=0;o<=5;o++)this.setFunctionModule(8,o,Y(i,o));this.setFunctionModule(8,7,Y(i,6)),this.setFunctionModule(8,8,Y(i,7)),this.setFunctionModule(7,8,Y(i,8));for(let o=9;o<15;o++)this.setFunctionModule(14-o,8,Y(i,o));for(let o=0;o<8;o++)this.setFunctionModule(this.size-1-o,8,Y(i,o));for(let o=8;o<15;o++)this.setFunctionModule(8,this.size-15+o,Y(i,o));this.setFunctionModule(8,this.size-8,!0)}drawVersion(){if(this.version<7)return;let t=this.version;for(let e=0;e<12;e++)t=t<<1^(t>>>11)*7973;let r=this.version<<12|t;for(let e=0;e<18;e++){let i=Y(r,e),o=this.size-11+e%3,a=Math.floor(e/3);this.setFunctionModule(o,a,i),this.setFunctionModule(a,o,i)}}drawFinderPattern(t,r){for(let e=-4;e<=4;e++)for(let i=-4;i<=4;i++){let o=Math.max(Math.abs(i),Math.abs(e)),a=t+i,s=r+e;a>=0&&a<this.size&&s>=0&&s<this.size&&this.setFunctionModule(a,s,o!==2&&o!==4,re.Position)}}drawAlignmentPattern(t,r){for(let e=-2;e<=2;e++)for(let i=-2;i<=2;i++)this.setFunctionModule(t+i,r+e,Math.max(Math.abs(i),Math.abs(e))!==1,re.Alignment)}setFunctionModule(t,r,e,i=re.Function){this.modules[r][t]=e,this.types[r][t]=i}addEccAndInterleave(t){let r=this.version,e=this.ecc;if(t.length!==xe(r,e))throw new RangeError("Invalid argument");let i=Ye[e[0]][r],o=Ke[e[0]][r],a=Math.floor(Se(r)/8),s=i-a%i,p=Math.floor(a/i),f=[],v=Ct(o);for(let y=0,S=0;y<i;y++){let z=t.slice(S,S+p-o+(y<s?0:1));S+=z.length;let P=Tt(z,v);y<s&&z.push(0),f.push(z.concat(P))}let g=[];for(let y=0;y<f[0].length;y++)f.forEach((S,z)=>{(y!==p-o||z>=s)&&g.push(S[y])});return g}drawCodewords(t){if(t.length!==Math.floor(Se(this.version)/8))throw new RangeError("Invalid argument");let r=0;for(let e=this.size-1;e>=1;e-=2){e===6&&(e=5);for(let i=0;i<this.size;i++)for(let o=0;o<2;o++){let a=e-o,p=(e+1&2)===0?this.size-1-i:i;!this.types[p][a]&&r<t.length*8&&(this.modules[p][a]=Y(t[r>>>3],7-(r&7)),r++)}}}applyMask(t){if(t<0||t>7)throw new RangeError("Mask value out of range");for(let r=0;r<this.size;r++)for(let e=0;e<this.size;e++){let i;switch(t){case 0:i=(e+r)%2===0;break;case 1:i=r%2===0;break;case 2:i=e%3===0;break;case 3:i=(e+r)%3===0;break;case 4:i=(Math.floor(e/3)+Math.floor(r/2))%2===0;break;case 5:i=e*r%2+e*r%3===0;break;case 6:i=(e*r%2+e*r%3)%2===0;break;case 7:i=((e+r)%2+e*r%3)%2===0;break;default:throw new Error("Unreachable")}!this.types[r][e]&&i&&(this.modules[r][e]=!this.modules[r][e])}}getPenaltyScore(){let t=0;for(let o=0;o<this.size;o++){let a=!1,s=0,p=[0,0,0,0,0,0,0];for(let f=0;f<this.size;f++)this.modules[o][f]===a?(s++,s===5?t+=Ue:s>5&&t++):(this.finderPenaltyAddHistory(s,p),a||(t+=this.finderPenaltyCountPatterns(p)*ge),a=this.modules[o][f],s=1);t+=this.finderPenaltyTerminateAndCount(a,s,p)*ge}for(let o=0;o<this.size;o++){let a=!1,s=0,p=[0,0,0,0,0,0,0];for(let f=0;f<this.size;f++)this.modules[f][o]===a?(s++,s===5?t+=Ue:s>5&&t++):(this.finderPenaltyAddHistory(s,p),a||(t+=this.finderPenaltyCountPatterns(p)*ge),a=this.modules[f][o],s=1);t+=this.finderPenaltyTerminateAndCount(a,s,p)*ge}for(let o=0;o<this.size-1;o++)for(let a=0;a<this.size-1;a++){let s=this.modules[o][a];s===this.modules[o][a+1]&&s===this.modules[o+1][a]&&s===this.modules[o+1][a+1]&&(t+=xt)}let r=0;for(let o of this.modules)r=o.reduce((a,s)=>a+(s?1:0),r);let e=this.size*this.size,i=Math.ceil(Math.abs(r*20-e*10)/e)-1;return t+=i*bt,t}getAlignmentPatternPositions(){if(this.version===1)return[];{let t=Math.floor(this.version/7)+2,r=this.version===32?26:Math.ceil((this.version*4+4)/(t*2-2))*2,e=[6];for(let i=this.size-7;e.length<t;i-=r)e.splice(1,0,i);return e}}finderPenaltyCountPatterns(t){let r=t[1],e=r>0&&t[2]===r&&t[3]===r*3&&t[4]===r&&t[5]===r;return(e&&t[0]>=r*4&&t[6]>=r?1:0)+(e&&t[6]>=r*4&&t[0]>=r?1:0)}finderPenaltyTerminateAndCount(t,r,e){return t&&(this.finderPenaltyAddHistory(r,e),r=0),r+=this.size,this.finderPenaltyAddHistory(r,e),this.finderPenaltyCountPatterns(e)}finderPenaltyAddHistory(t,r){r[0]===0&&(t+=this.size),r.pop(),r.unshift(t)}};function V(n,t,r){if(t<0||t>31||n>>>t)throw new RangeError("Value out of range");for(let e=t-1;e>=0;e--)r.push(n>>>e&1)}function Y(n,t){return(n>>>t&1)!==0}var ce=class{constructor(t,r,e){if(this.mode=t,this.numChars=r,this.bitData=e,r<0)throw new RangeError("Invalid argument");this.bitData=e.slice()}getData(){return this.bitData.slice()}},vt=[1,10,12,14],yt=[2,9,11,13],kt=[4,8,16,16];function Ve(n,t){return n[Math.floor((t+7)/17)+1]}function Ge(n){let t=[];for(let r of n)V(r,8,t);return new ce(kt,n.length,t)}function wt(n){if(!Je(n))throw new RangeError("String contains non-numeric characters");let t=[];for(let r=0;r<n.length;){let e=Math.min(n.length-r,3);V(Number.parseInt(n.substring(r,r+e),10),e*3+1,t),r+=e}return new ce(vt,n.length,t)}function Et(n){if(!Ze(n))throw new RangeError("String contains unencodable characters in alphanumeric mode");let t=[],r;for(r=0;r+2<=n.length;r+=2){let e=Ee.indexOf(n.charAt(r))*45;e+=Ee.indexOf(n.charAt(r+1)),V(e,11,t)}return r<n.length&&V(Ee.indexOf(n.charAt(r)),6,t),new ce(yt,n.length,t)}function Mt(n){return n===""?[]:Je(n)?[wt(n)]:Ze(n)?[Et(n)]:[Ge(Lt(n))]}function Je(n){return mt.test(n)}function Ze(n){return gt.test(n)}function St(n,t){let r=0;for(let e of n){let i=Ve(e.mode,t);if(e.numChars>=1<<i)return Number.POSITIVE_INFINITY;r+=4+i+e.bitData.length}return r}function Lt(n){n=encodeURI(n);let t=[];for(let r=0;r<n.length;r++)n.charAt(r)!=="%"?t.push(n.charCodeAt(r)):(t.push(Number.parseInt(n.substring(r+1,r+3),16)),r+=2);return t}function Se(n){if(n<Ce||n>Te)throw new RangeError("Version number out of range");let t=(16*n+128)*n+64;if(n>=2){let r=Math.floor(n/7)+2;t-=(25*r-10)*r-55,n>=7&&(t-=36)}return t}function xe(n,t){return Math.floor(Se(n)/8)-Ke[t[0]][n]*Ye[t[0]][n]}function Ct(n){if(n<1||n>255)throw new RangeError("Degree out of range");let t=[];for(let e=0;e<n-1;e++)t.push(0);t.push(1);let r=1;for(let e=0;e<n;e++){for(let i=0;i<t.length;i++)t[i]=Le(t[i],r),i+1<t.length&&(t[i]^=t[i+1]);r=Le(r,2)}return t}function Tt(n,t){let r=t.map(e=>0);for(let e of n){let i=e^r.shift();r.push(0),t.forEach((o,a)=>r[a]^=Le(o,i))}return r}function Le(n,t){if(n>>>8||t>>>8)throw new RangeError("Byte out of range");let r=0;for(let e=7;e>=0;e--)r=r<<1^(r>>>7)*285,r^=(t>>>e&1)*n;return r}function Pt(n,t,r=1,e=40,i=-1,o=!0){if(!(Ce<=r&&r<=e&&e<=Te)||i<-1||i>7)throw new RangeError("Invalid value");let a,s;for(a=r;;a++){let g=xe(a,t)*8,y=St(n,a);if(y<=g){s=y;break}if(a>=e)throw new RangeError("Data too long")}for(let g of[qe,je,We])o&&s<=xe(a,g)*8&&(t=g);let p=[];for(let g of n){V(g.mode[0],4,p),V(g.numChars,Ve(g.mode,a),p);for(let y of g.getData())p.push(y)}let f=xe(a,t)*8;V(0,Math.min(4,f-p.length),p),V(0,(8-p.length%8)%8,p);for(let g=236;p.length<f;g^=253)V(g,8,p);let v=Array.from({length:Math.ceil(p.length/8)},()=>0);return p.forEach((g,y)=>v[y>>>3]|=g<<7-(y&7)),new Me(a,t,v,i)}function Xe(n,t){let{ecc:r="L",boostEcc:e=!1,minVersion:i=1,maxVersion:o=40,maskPattern:a=-1,border:s=1}=t||{},p=typeof n=="string"?Mt(n):Array.isArray(n)?[Ge(n)]:void 0;if(!p)throw new Error(`uqr only supports encoding string and binary data, but got: ${typeof n}`);let f=Pt(p,ht[r],i,o,a,e),v=At({version:f.version,maskPattern:f.mask,size:f.size,data:f.modules,types:f.types},s);return t?.invert&&(v.data=v.data.map(g=>g.map(y=>!y))),t?.onEncoded?.(v),v}function At(n,t=1){if(!t)return n;let{size:r}=n,e=r+t*2;n.size=e,n.data.forEach(o=>{for(let a=0;a<t;a++)o.unshift(!1),o.push(!1)});for(let o=0;o<t;o++)n.data.unshift(Array.from({length:e},a=>!1)),n.data.push(Array.from({length:e},a=>!1));let i=re.Border;n.types.forEach(o=>{for(let a=0;a<t;a++)o.unshift(i),o.push(i)});for(let o=0;o<t;o++)n.types.unshift(Array.from({length:e},a=>i)),n.types.push(Array.from({length:e},a=>i));return n}function be(n,t,r){let e=Xe(t,{ecc:"M",border:2}),i=Math.max(1,Math.min(window.devicePixelRatio||1,3));n.width=n.height=Math.round(r*i);let o=n.getContext("2d");if(!o)return;let a=n.width/e.size;o.fillStyle="#fff",o.fillRect(0,0,n.width,n.height),o.fillStyle="#000",e.data.forEach((s,p)=>s.forEach((f,v)=>{f&&o.fillRect(Math.floor(v*a),Math.floor(p*a),Math.ceil(a),Math.ceil(a))}))}var Qe=n=>`${n.slice(0,4)}-${n.slice(4)}`;function Ft(n){let t=/rgba?\(([\d.]+)[,\s]+([\d.]+)[,\s]+([\d.]+)(?:[,\s/]+([\d.]+%?))?\)/.exec(n);if(!t||(t[4]===void 0?1:t[4].endsWith("%")?Number.parseFloat(t[4])/100:Number(t[4]))<.5)return null;let[e,i,o]=[t[1],t[2],t[3]].map(a=>{let s=Number(a)/255;return s<=.03928?s/12.92:((s+.055)/1.055)**2.4});return .2126*e+.7152*i+.0722*o}function zt(n){for(let r=n;r;r=r.parentElement){let e=Ft(getComputedStyle(r).backgroundColor);if(e!==null)return e<.3?"dark":"light"}let t=getComputedStyle(document.documentElement).colorScheme||"";return/\bdark\b/.test(t)&&!/\blight\b/.test(t)||/\blight\b/.test(t)&&/\bdark\b/.test(t)&&matchMedia?.("(prefers-color-scheme: dark)").matches?"dark":"light"}function ve(n,t){return n==="light"||n==="dark"?n:zt(t)}var Pe=`
143
+ :host { all: initial; }
144
+ .overlay {
145
+ /* Light. Lime is unreadable as text on white, so links and focus rings use a deeper violet. */
146
+ --accent: var(--tsp-accent, #c8ff4d);
147
+ --accent-text: var(--tsp-accent-text, #0b0d12);
148
+ --accent-ink: var(--tsp-accent-ink, var(--tsp-accent, #6b4fe0));
149
+ --accent-2: var(--tsp-accent-2, var(--tsp-accent, #8a6cf5));
150
+ --button-edge: rgba(11, 13, 18, .1);
151
+ --bg: var(--tsp-bg, #fff);
152
+ --text: var(--tsp-text, #0b0d12);
153
+ --muted: var(--tsp-muted, #5d6270);
154
+ --line: var(--tsp-line, rgba(11, 13, 18, .12));
155
+ --track: rgba(11, 13, 18, .08);
156
+ --ok: #1a8a4c;
157
+ --error: #c42f3d;
158
+ --radius: var(--tsp-radius, 18px);
159
+ position: fixed; inset: 0; z-index: 2147483000;
160
+ display: grid; place-items: center; padding: 16px;
161
+ background: rgba(9, 11, 16, .6);
162
+ font: 15px/1.5 var(--tsp-font, Inter, system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans Arabic", sans-serif);
163
+ color: var(--text);
164
+ animation: fade .15s ease-out;
165
+ }
166
+ @media (prefers-color-scheme: dark) {
167
+ .overlay[data-theme="auto"] { --accent-ink: var(--tsp-accent-ink, var(--tsp-accent, #c8ff4d)); --accent-2: var(--tsp-accent-2, var(--tsp-accent, #9a7cff)); --button-edge: transparent; --bg: var(--tsp-bg, #12151c); --text: var(--tsp-text, #f4f4f5); --muted: var(--tsp-muted, #9297a4); --line: var(--tsp-line, rgba(255,255,255,.09)); --track: rgba(255,255,255,.08); --ok: #c8ff4d; --error: #ff8a94; }
168
+ }
169
+ .overlay[data-theme="dark"] { --accent-ink: var(--tsp-accent-ink, var(--tsp-accent, #c8ff4d)); --accent-2: var(--tsp-accent-2, var(--tsp-accent, #9a7cff)); --button-edge: transparent; --bg: var(--tsp-bg, #12151c); --text: var(--tsp-text, #f4f4f5); --muted: var(--tsp-muted, #9297a4); --line: var(--tsp-line, rgba(255,255,255,.09)); --track: rgba(255,255,255,.08); --ok: #c8ff4d; --error: #ff8a94; }
170
+ * { box-sizing: border-box; }
171
+ [hidden] { display: none !important; }
172
+ .dialog {
173
+ width: min(420px, 100%); max-height: calc(100dvh - 32px); overflow: auto;
174
+ background: var(--bg); border: 1px solid var(--line); border-radius: var(--radius);
175
+ box-shadow: 0 30px 80px rgba(0, 0, 0, .35); padding: 20px; display: grid; gap: 14px; outline: none;
176
+ }
177
+ .header { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
178
+ .title { margin: 0; font-size: 18px; font-weight: 700; line-height: 1.3; }
179
+ .icon-button { all: unset; cursor: pointer; width: 32px; height: 32px; display: grid; place-items: center; border-radius: 50%; font-size: 22px; color: var(--muted); }
180
+ .icon-button:hover { background: var(--track); color: var(--text); }
181
+ .qr-block { display: grid; justify-items: center; gap: 8px; text-align: center; }
182
+ .qr { width: 220px; height: 220px; border-radius: 12px; background: #fff; border: 1px solid var(--line); image-rendering: pixelated; }
183
+ .lead { margin: 4px 0 0; font-weight: 600; }
184
+ .muted { margin: 0; color: var(--muted); font-size: 13.5px; }
185
+ .small { font-size: 12px; }
186
+ .code { display: inline-block; direction: ltr; font: 700 15px/1.3 ui-monospace, "SF Mono", Menlo, Consolas, monospace; letter-spacing: 1.5px; color: var(--text); padding: 2px 8px; border-radius: 6px; background: var(--track); }
187
+ .status { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 4px 10px; text-align: center; font-size: 14px; min-height: 22px; }
188
+ .approval { display: grid; gap: 8px; width: 100%; padding: 14px; border: 1px solid var(--line); border-radius: 14px; text-align: center; }
189
+ .files { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
190
+ .files:empty { display: none; }
191
+ .file { display: grid; gap: 3px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 12px; }
192
+ .file .name { font-weight: 600; font-size: 13.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
193
+ .file .meta { color: var(--muted); font-size: 12px; }
194
+ .file .bar { height: 4px; border-radius: 4px; background: var(--track); overflow: hidden; margin-top: 3px; }
195
+ .file .fill { display: block; height: 100%; width: 0; background: linear-gradient(90deg, var(--accent-2), var(--accent)); transition: width .2s; }
196
+ .file.received .meta { color: var(--ok); }
197
+ .file.received .fill { background: var(--ok); }
198
+ .file.failed .meta { color: var(--error); }
199
+ .file.failed .bar { display: none; }
200
+ .footer { display: grid; gap: 12px; }
201
+ .buttons { display: flex; gap: 10px; justify-content: flex-end; }
202
+ button.primary, button.secondary { font: inherit; font-weight: 600; cursor: pointer; border-radius: 12px; padding: 10px 16px; min-height: 42px; border: 1px solid transparent; }
203
+ button.primary { background: var(--accent); color: var(--accent-text); border-color: var(--button-edge); box-shadow: inset 0 1px 0 rgba(255,255,255,.45), 0 8px 24px -8px color-mix(in srgb, var(--accent) 60%, transparent); }
204
+ button.primary:hover:not(:disabled) { background: color-mix(in srgb, var(--accent) 85%, #fff); }
205
+ button.primary:disabled { opacity: .45; cursor: default; box-shadow: none; }
206
+ button.secondary { background: transparent; color: var(--text); border-color: var(--line); }
207
+ button.secondary:hover { background: var(--track); }
208
+ button.link { all: unset; cursor: pointer; color: var(--accent-ink); font-weight: 600; font-size: 13.5px; text-decoration: underline; text-underline-offset: 3px; }
209
+ button:focus-visible, .icon-button:focus-visible { outline: 3px solid var(--accent-ink); outline-offset: 2px; }
210
+ /* ---- TokShare for desktop ---- */
211
+ .announce { margin: 0; display: flex; align-items: center; gap: 10px; padding: 9px 8px 9px 12px; border-radius: 12px; border: 1px solid var(--line); background: color-mix(in srgb, var(--accent-2) 7%, transparent); color: var(--muted); font-size: 12.5px; line-height: 1.45; text-align: start; }
212
+ .announce i { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--accent-2); }
213
+ .announce span { flex: 1; min-width: 0; }
214
+ .announce a { color: var(--accent-ink); font-weight: 650; text-decoration: underline; text-underline-offset: 2px; white-space: nowrap; }
215
+ .announce-hide { all: unset; cursor: pointer; flex: none; width: 24px; height: 24px; display: grid; place-items: center; border-radius: 50%; font-size: 16px; color: var(--muted); }
216
+ .announce-hide:hover { background: color-mix(in srgb, var(--text) 8%, transparent); color: var(--text); }
217
+ .announce-hide:focus-visible, .announce a:focus-visible { outline: 3px solid color-mix(in srgb, var(--accent-ink) 60%, transparent); outline-offset: 2px; }
218
+ @keyframes fade { from { opacity: 0; } }
219
+ @media (prefers-reduced-motion: reduce) { .overlay { animation: none; } .file .fill { transition: none; } }
220
+ `;function et(n,t){let r=he(t.locale),e=me(r,t.strings),i=document.activeElement,o=document.createElement("div");o.setAttribute("data-tokshare-pick","");let a=o.attachShadow({mode:"open"});if("adoptedStyleSheets"in Document.prototype&&"replaceSync"in CSSStyleSheet.prototype){let d=new CSSStyleSheet;d.replaceSync(Pe),a.adoptedStyleSheets=[d]}else{let d=document.createElement("style");d.textContent=Pe,a.append(d)}let s=(d,h="",l="")=>{let u=document.createElement(d);return h&&(u.className=h),l&&(u.textContent=l),u},p=s("div","overlay");p.dataset.theme=ve(t.theme,document.body);let f=s("div","dialog");f.setAttribute("role","dialog"),f.setAttribute("aria-modal","true"),f.setAttribute("aria-labelledby","tsp-title"),f.dir=r==="ar"?"rtl":"ltr",f.lang=r,f.tabIndex=-1;let v=s("div","header"),g=s("h2","title",e(t.multiple===!1?"titleOne":"title"));g.id="tsp-title";let y=s("button","icon-button","\xD7");y.type="button",y.setAttribute("aria-label",e("close")),v.append(g,y);let S=s("div","qr-block"),z=s("canvas","qr");z.setAttribute("role","img"),z.setAttribute("aria-label",e("scan"));let P=s("p","lead",e("scan")),m=s("p","muted"),L=s("span","code");S.append(z,P,m);let A=s("div","status");A.setAttribute("role","status"),A.setAttribute("aria-live","polite");let Q=s("ul","files"),G=s("div","footer"),C=s("p","muted small",e("privacy")),J=s("div","buttons"),D=s("button","secondary",e("cancel"));D.type="button";let $=s("button","primary",e("done"));$.type="button",$.disabled=!0,J.append(D,$);let U=fe(t.announce,e);G.append(...U?[U]:[],C,J),f.append(v,S,A,Q,G),p.append(f),a.append(p),document.body.append(o),f.focus();let R=new Map,c="",b=(d,h)=>{A.replaceChildren(s("span","",d),...h?[h]:[])},T=(d,h)=>{be(z,d,220);let l=new URL(d).host;L.textContent=`${h.slice(0,4)}-${h.slice(4)}`,m.replaceChildren(document.createTextNode(`${e("orType",{host:l})} `),L),S.hidden=!1,b(e("waiting"))},k=()=>{let d=n.files.length;$.disabled=d===0,$.textContent=d===0?e("done"):d===1?e("useFile"):e("useFiles",{count:d})},H=d=>{let h=d.state==="sending"?e("sending",{percent:d.percent}):d.state==="receiving"?e("receiving",{percent:d.percent}):e(d.state);d.element.className=`file ${d.state}`;let l=s("span","bar"),u=s("i","fill");u.style.width=`${d.state==="received"?100:d.percent}%`,l.append(u),d.element.replaceChildren(s("span","name",d.meta.name),s("span","meta",`${ne(d.meta.size,r)} \xB7 ${h}`),l)},N=d=>{let h=R.get(d.id);return h||(h={element:s("li"),meta:d,state:"sending",percent:0},R.set(d.id,h),Q.append(h.element)),h},Z=!1,q=()=>{let d=s("button","link",e("disconnect"));d.type="button",d.addEventListener("click",()=>{n.disconnect().catch(()=>{})}),b(e(Z?"connectedDirect":"connected",{label:c}),d)},ae=()=>{document.removeEventListener("keydown",j,!0),o.remove(),i?.focus?.()},j=d=>{if(d.key==="Escape"&&(d.stopPropagation(),n.cancel()),d.key==="Tab"){let h=[...a.querySelectorAll("button:not([disabled])")];if(!h.length)return;let l=h[0],u=h[h.length-1],E=a.activeElement;d.shiftKey&&(E===l||E===f)?(d.preventDefault(),u.focus()):!d.shiftKey&&E===u&&(d.preventDefault(),l.focus())}};document.addEventListener("keydown",j,!0),y.addEventListener("click",()=>n.cancel()),D.addEventListener("click",()=>n.cancel()),$.addEventListener("click",()=>n.finish()),p.addEventListener("click",d=>{d.target===p&&n.cancel()}),S.hidden=!0,b(e("loading")),n.on("ready",({claimUrl:d,code:h})=>T(d,h)),n.on("phone",({phone:d,needsApproval:h,match:l})=>{if(c=d.label,S.hidden=!0,h){let u=s("div","approval"),E=s("button","primary",e("approve")),x=s("button","secondary",e("reject"));E.type=x.type="button",E.addEventListener("click",()=>{n.approve(),q()}),x.addEventListener("click",()=>n.reject()),u.append(s("strong","",e("approveTitle")),s("span","muted",`${d.label} \xB7 ${e("approveMatch",{match:l??""})}`),s("div","buttons","")),u.lastElementChild.append(x,E),A.replaceChildren(u),E.focus()}else q()}),n.on("phone_left",()=>{Z=!1,b(e("phoneLeft"))}),n.on("direct",({connected:d})=>{Z=d,c&&q()}),n.on("file_started",d=>H(N(d))),n.on("progress",d=>{let h=R.get(d.id);h&&(h.state=d.phase==="upload"?"sending":"receiving",h.percent=d.total?Math.floor(d.sent/d.total*100):0,H(h))}),n.on("received",({id:d})=>{let h=R.get(d);h&&(h.state="received",H(h)),k()}),n.on("file_failed",({id:d})=>{let h=R.get(d);h&&(h.state="failed",H(h))}),n.on("error",d=>{S.hidden=!0;let h=s("button","link",e("tryAgain"));h.type="button",h.addEventListener("click",()=>{b(e("loading")),n.restart()}),b(e("error",{message:d.message}),h)}),n.on("close",d=>{if(d==="finished"||d==="canceled"||n.files.length)return ae();S.hidden=!0;let h=s("button","link",e("newCode"));h.type="button",h.addEventListener("click",()=>{b(e("loading")),n.restart()}),b(e("expired"),h)}),n.done.then(ae)}async function oe(n,t){let r;try{r=await fetch(n,{method:"POST",headers:{"Content-Type":"text/plain"},body:JSON.stringify(t),cache:"no-store",credentials:"omit"})}catch{throw new B("network","Can't reach TokShare Pick.",0)}if(!r.ok){let e=await r.json().catch(()=>({}));throw new B(e.error||"internal",e.message||`HTTP ${r.status}`,r.status)}return r}var ye=class n{constructor(t,r,e){M(this,"info");M(this,"relay");M(this,"ws",null);M(this,"lastSeq",0);M(this,"closed",!1);M(this,"attempt",0);M(this,"pinger");M(this,"onEvent");this.relay=t,this.info=r,this.onEvent=e}static async create(t,r,e,i){let o=await oe(`${t}/v1/sessions`,{key:r,options:e,client:`sdk/${Ne}`}),a=new n(t,await o.json(),i);return a.connect(),a}connect(){if(this.closed)return;let t=new WebSocket(this.info.wsUrl);this.ws=t,t.addEventListener("open",()=>{this.attempt=0,t.send(JSON.stringify({t:"auth",token:this.info.desktopToken,lastSeq:this.lastSeq})),this.pinger=setInterval(()=>{t.readyState===WebSocket.OPEN&&t.send("ping")},25e3)}),t.addEventListener("message",r=>{if(r.data==="pong")return;let e;try{e=JSON.parse(r.data)}catch{return}if("seq"in e&&e.t!=="hello"){if(e.seq<=this.lastSeq)return;this.lastSeq=e.seq}e.t==="closed"&&(this.closed=!0),this.onEvent(e)}),t.addEventListener("close",r=>{clearInterval(this.pinger),!(this.closed||r.code===4401)&&setTimeout(()=>this.connect(),Math.min(1e4,400*2**this.attempt++))})}send(t){this.ws?.readyState===WebSocket.OPEN&&this.ws.send(JSON.stringify(t))}async download(t,r){for(let e=0;;e++)try{let o=(await oe(`${this.relay}/v1/sessions/${this.info.sid}/files/${t.id}/download`,{token:this.info.desktopToken})).body.getReader(),a=[],s=0;for(;;){let{done:p,value:f}=await o.read();if(p)break;a.push(f),s+=f.byteLength,r(s)}if(s!==t.size)throw new B("network","Incomplete download.",0);return new File(a,t.name,{type:t.type||t.sniffed||"",lastModified:t.lastModified})}catch(i){if(!(i instanceof B&&i.code==="network")||e>=2)throw i;await new Promise(o=>setTimeout(o,600*(e+1)))}}directResult(t,r,e){return oe(`${this.relay}/v1/sessions/${this.info.sid}/files/${t}/direct`,{token:this.info.desktopToken,ok:r,...e?{code:e}:{}}).catch(()=>{})}ack(t){return oe(`${this.relay}/v1/sessions/${this.info.sid}/files/${t}/ack`,{token:this.info.desktopToken}).catch(()=>{})}async rekey(){let r=await(await oe(`${this.relay}/v1/sessions/${this.info.sid}/rekey`,{token:this.info.desktopToken})).json();return Object.assign(this.info,r),r}close(t=!1){if(this.closed)return;this.closed=!0,clearInterval(this.pinger);let r=`${this.relay}/v1/sessions/${this.info.sid}/close`,e=JSON.stringify({token:this.info.desktopToken});t&&typeof navigator<"u"&&navigator.sendBeacon?navigator.sendBeacon(r,new Blob([e],{type:"text/plain"})):oe(r,{token:this.info.desktopToken}).catch(()=>{});try{this.ws?.close(1e3,"closed")}catch{}}get isClosed(){return this.closed}};function se(n){if(!n||typeof n.key!="string")throw new B("key_invalid","Pass your publishable key: open({ key: 'pk_live_\u2026' }).");let t=(n.relay||He).replace(/\/+$/,""),r=new Map,e=(c,b)=>{for(let T of r.get(c)??[])try{T(b)}catch(k){console.error(k)}},i=[],o=new Set,a=new Map,s=new Set,p=new Set,f=new Map,v=null,g=null,y=!1,S,z=new Promise(c=>{S=c}),P=n.multiple!==!1,m={...n.accept!==void 0?{accept:n.accept}:{},multiple:P,...n.maxFiles!==void 0?{maxFiles:n.maxFiles}:{},...n.maxFileBytes!==void 0?{maxFileBytes:n.maxFileBytes}:{},...n.resizeImages?{resizeImages:n.resizeImages}:{},...n.confirmPhone?{confirmPhone:!0}:{},...n.siteName?{siteName:n.siteName}:{},...n.locale==="ar"||n.locale==="en"?{locale:n.locale}:{},...n.direct===!1?{direct:!1}:{}},L=P?n.maxFiles??20:1,A=(c,b)=>{y||(y=!0,removeEventListener("pagehide",Q),g?.close(),v?.close(),e("close",c),S(b))},Q=()=>v?.close(!0),G=c=>{if(p.has(c.id)){v?.ack(c.id);return}if(o.has(c.id)||!v)return;o.add(c.id);let b=v,T=b.download(c,k=>e("progress",{id:c.id,name:c.name,sent:k,total:c.size,phase:"download"})).then(async k=>{await b.ack(c.id),!y&&(i.push(k),e("received",{id:c.id,file:k}),e("file",k),i.length>=L&&R.finish())}).catch(k=>e("file_failed",{id:c.id,code:k instanceof B?k.code:"network"})).finally(()=>s.delete(T));s.add(T)},C=c=>{let b=a.get(c);return b?Promise.resolve(b):new Promise(T=>{let k=setTimeout(()=>{f.delete(c),T(null)},1e4);f.set(c,H=>{clearTimeout(k),f.delete(c),T(H)})})},J=async(c,b,T)=>{let k=v,H=await C(c);if(!k||!H||y||o.has(c))return{ok:!1,code:"failed"};let N=$e(H,b,T,k.info.options.accept,k.info.options.maxFileBytes);return N.ok?(o.add(c),p.add(c),k.directResult(c,!0),i.push(N.file),e("received",{id:c,file:N.file}),e("file",N.file),i.length>=L&&R.finish(),{ok:!0}):(k.directResult(c,!1,N.code),N)},D=c=>n.direct===!1||!le.supported()?null:(g||(g=new le(b=>c.send({t:"rtc",d:b}),{progress:(b,T,k)=>e("progress",{id:b,name:a.get(b)?.name??"",sent:T,total:k,phase:"upload"}),complete:J,state:b=>e("direct",{connected:b})})),g),$=c=>{switch(c.t){case"rtc":v&&D(v)?.onSignal(c.d);break;case"hello":for(let b of c.files)o.has(b.id)||(a.set(b.id,b),e("file_started",b)),G(b);break;case"phone":e("phone",{phone:c.phone,needsApproval:c.needsApproval,...c.match?{match:c.match}:{}});break;case"phone_left":g?.close(),e("phone_left",void 0);break;case"file_started":a.set(c.file.id,c.file),f.get(c.file.id)?.(c.file),e("file_started",c.file);break;case"progress":e("progress",{id:c.id,name:a.get(c.id)?.name??"",sent:c.sent,total:c.total,phase:"upload"});break;case"file_ready":G(c.file);break;case"file_failed":e("file_failed",{id:c.id,code:c.code});break;case"phone_done":(i.length||s.size)&&R.finish();break;case"closed":i.length?A(c.reason,[...i]):e("close",c.reason);break}},U=()=>{ye.create(t,n.key,m,$).then(c=>{if(y){c.close();return}v=c,L=c.info.options.maxFiles,e("ready",{claimUrl:c.info.claimUrl,code:c.info.code})},c=>e("error",c))},R={done:z,get files(){return i},get claimUrl(){return v?.info.claimUrl??null},get code(){return v?.info.code??null},on(c,b){return r.has(c)||r.set(c,new Set),r.get(c).add(b),()=>r.get(c)?.delete(b)},finish(){y||Promise.allSettled([...s]).then(()=>A("finished",[...i]))},cancel(){A("canceled",[])},approve(){v?.send({t:"approve"})},reject(){v?.send({t:"reject"})},async disconnect(){if(!v)return;g?.close();let c=await v.rekey();e("ready",c)},restart(){y||(g?.close(),g=null,v?.close(),v=null,U())}};return addEventListener("pagehide",Q),n.signal?.addEventListener("abort",()=>R.cancel(),{once:!0}),n.ui!==!1&&et(R,n),U(),R}function Ae(n){return se(n).done}function Fe(n,t){if(!(n instanceof HTMLInputElement)||n.type!=="file")throw new B("bad_request",'attach() needs an <input type="file">.');return async()=>{let r=await Ae({...t,accept:n.accept,multiple:n.multiple});if(!r.length)return r;let e=new DataTransfer;if(t.mode==="append"&&n.multiple)for(let i of Array.from(n.files??[]))e.items.add(i);for(let i of n.multiple?r:r.slice(0,1))e.items.add(i);return n.files=e.files,n.dispatchEvent(new Event("input",{bubbles:!0})),n.dispatchEvent(new Event("change",{bubbles:!0})),r}}var de={upload:'<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 15V4m0 0L7.5 8.5M12 4l4.5 4.5M5 14v4a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-4"/></svg>',folder:'<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M3.5 7.5a2 2 0 0 1 2-2h4l2 2h7a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2h-13a2 2 0 0 1-2-2z"/></svg>',phone:'<svg viewBox="0 0 24 24" aria-hidden="true"><rect x="7" y="2.5" width="10" height="19" rx="2.5"/><path d="M11 18.5h2"/></svg>',close:'<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M7 7l10 10M17 7 7 17"/></svg>',back:'<svg viewBox="0 0 24 24" aria-hidden="true" class="flip"><path d="M14.5 6 8.5 12l6 6"/></svg>'};function Rt(n){if(n==null||n==="")return;if(typeof n=="number")return n>0?n:void 0;let t=/^\s*([\d.]+)\s*(b|kb|mb|gb)?\s*$/i.exec(n);if(!t)return;let r={b:1,kb:1e3,mb:1e6,gb:1e9},e=Number(t[1])*r[(t[2]??"b").toLowerCase()];return e>0?Math.round(e):void 0}function _t(n){return n.split(",").map(t=>t.trim()).filter(Boolean).map(t=>{if(t.endsWith("/*"))return t.slice(0,-2).replace(/^./,e=>e.toUpperCase())+"s";if(t.startsWith("."))return t.slice(1).toUpperCase();let r=t.split("/")[1]??t;return r==="jpeg"?"JPG":r.replace(/^(x-|vnd\.)/,"").split(/[.+-]/)[0].toUpperCase()}).filter((t,r,e)=>e.indexOf(t)===r).join(", ")}var It=()=>typeof matchMedia=="function"&&matchMedia("(pointer: coarse)").matches&&innerWidth<820;function ze(n,t){let r=typeof n=="string"?document.querySelector(n):n;if(!r)throw new Error(`TokShare Pick: ${String(n)} not found`);let e=he(t.locale),i=me(e,t.strings),o=t.multiple!==!1,a=o?Math.min(t.maxFiles??te.maxFiles,te.maxFiles):1,s=Math.min(t.maxFileBytes??te.maxFileBytes,te.maxFileBytes),p=t.accept??"",f=t.phone===!1?!1:t.phone??"inline",v=f!==!1&&(t.phoneOnMobile||!It()),g=document.createElement("input");g.type="file",g.hidden=!0,g.multiple=o,p&&(g.accept=p),t.name&&(g.name=t.name);let y=document.createElement("div");y.setAttribute("data-tokshare-pick-field",""),r.append(y,g);let S=y.attachShadow({mode:"open"});if("adoptedStyleSheets"in Document.prototype&&"replaceSync"in CSSStyleSheet.prototype){let l=new CSSStyleSheet;l.replaceSync(we),S.adoptedStyleSheets=[l]}else{let l=document.createElement("style");l.textContent=we,S.append(l)}let z=[p?i("hintTypes",{types:_t(p),size:ne(s,e)}):i("hintAny",{size:ne(s,e)}),o?i("hintCount",{count:a}):""].filter(Boolean).join(" \xB7 "),P=document.createElement("div");P.className="wrap",P.dir=e==="ar"?"rtl":"ltr",P.lang=e,P.dataset.theme=ve(t.theme,r),P.innerHTML=`
221
+ <div class="zone" data-state="idle" role="group">
222
+ <div class="idle">
223
+ <div class="tile">${de.upload}</div>
224
+ <p class="title"></p>
225
+ <p class="hint"></p>
226
+ <div class="actions">
227
+ <button type="button" class="primary browse">${de.folder}<span></span></button>
228
+ <span class="or"></span>
229
+ <button type="button" class="ghost phone">${de.phone}<span></span></button>
230
+ </div>
231
+ </div>
232
+ <div class="phone-view" hidden>
233
+ <div class="qr-box"><canvas class="qr" role="img"></canvas><div class="qr-loading"></div></div>
234
+ <div class="phone-info">
235
+ <p class="title phone-title"></p>
236
+ <ol class="steps"><li></li><li></li><li></li></ol>
237
+ <p class="code-line"></p>
238
+ <p class="status" role="status" aria-live="polite"><i></i><span></span></p>
239
+ <div class="phone-actions">
240
+ <button type="button" class="link back">${de.back}<span></span></button>
241
+ <button type="button" class="primary small done" hidden></button>
242
+ </div>
243
+ </div>
244
+ <div class="announce-slot"></div>
245
+ </div>
246
+ <input type="file" class="native" hidden>
247
+ </div>
248
+ <p class="message" role="alert" hidden></p>
249
+ <div class="list-head" hidden><span class="count"></span><button type="button" class="link clear"></button></div>
250
+ <ul class="list"></ul>`,S.append(P);let m=l=>P.querySelector(l),L=m(".zone"),A=m(".native");A.multiple=o,p&&(A.accept=p),m(".idle .title").textContent=t.label??i(o?"dropTitle":"dropTitleOne"),m(".hint").textContent=z,m(".browse span").textContent=i("browse"),m(".or").textContent=i("or"),m(".phone span").textContent=i("usePhone"),m(".phone-title").textContent=i("phoneTitle");let Q=P.querySelectorAll(".steps li");["phoneStep1","phoneStep2","phoneStep3"].forEach((l,u)=>{Q[u].textContent=i(l)}),m(".back span").textContent=i("back"),m(".done").textContent=i("doneWithPhone"),m(".clear").textContent=i("clearAll"),v||(m(".phone").hidden=!0,m(".or").hidden=!0);let G=fe(t.announce,i);G?m(".announce-slot").append(G):m(".announce-slot").remove();let C=[],J=new Set,D=null,$,U=()=>C.filter(l=>l.file&&!l.failed).map(l=>l.file),R=l=>{let u=m(".message");u.textContent=l,u.hidden=!l,clearTimeout($),l&&($=setTimeout(()=>{u.hidden=!0},6e3))},c=()=>{let l=new DataTransfer;for(let u of U())l.items.add(u);g.files=l.files,g.dispatchEvent(new Event("input",{bubbles:!0})),g.dispatchEvent(new Event("change",{bubbles:!0}));for(let u of J)u(U())},b=()=>{let l=m(".list"),u=C.length;m(".list-head").hidden=u<2,m(".count").textContent=i("fileCount",{count:u});for(let E of C)E.element||(E.element=document.createElement("li"),l.append(E.element)),T(E)},T=l=>{let u=l.element,E=(l.name.split(".").pop()??"").slice(0,4).toUpperCase(),x=!l.file&&!l.failed;u.className=`item${x?" pending":""}${l.failed?" failed":""}`,u.replaceChildren();let w=document.createElement("div");if(w.className="thumb",l.url){let K=document.createElement("img");K.alt="",K.src=l.url,K.addEventListener("error",()=>{K.remove(),w.textContent=E}),w.append(K)}else w.textContent=E||"FILE";let _=document.createElement("div");_.className="body";let I=document.createElement("span");I.className="name",I.textContent=l.name;let W=document.createElement("span");W.className="meta";let ie=l.failed?i("failed"):x?i(l.phase==="download"?"receiving":"sending",{percent:l.percent}):"";if(W.textContent=[ne(l.size,e),l.source==="phone"?i("sourcePhone"):i("sourceDevice"),ie].filter(Boolean).join(" \xB7 "),_.append(I,W),x){let K=document.createElement("span");K.className="bar";let Re=document.createElement("i");Re.style.width=`${l.percent}%`,K.append(Re),_.append(K)}let ee=document.createElement("button");ee.type="button",ee.className="remove",ee.innerHTML=de.close,ee.setAttribute("aria-label",i("remove",{name:l.name})),ee.hidden=x,ee.addEventListener("click",()=>k(l)),u.append(w,_,ee)},k=l=>{let u=C.indexOf(l);u<0||(C.splice(u,1),l.url&&URL.revokeObjectURL(l.url),l.element?.remove(),b(),c())},H=(l,u)=>({key:Math.random().toString(36).slice(2),file:l,name:l.name,size:l.size,source:u,percent:100,...l.type.startsWith("image/")?{url:URL.createObjectURL(l)}:{}}),N=(l,u)=>{let E=[];if(!o&&l.length){for(let x of[...C])k(x);l=l.slice(0,1)}for(let x of l){if(C.filter(w=>!w.failed).length>=a){E.push(i("tooMany",{count:a}));break}if(x.size>s){E.push(i("tooLarge",{name:x.name,size:ne(s,e)}));continue}if(!Ie(p,x.name,x.type)){E.push(i("wrongType",{name:x.name}));continue}C.push(H(x,u))}R(E.join(" ")),b(),c()};m(".browse").addEventListener("click",()=>A.click()),A.addEventListener("change",()=>{N(Array.from(A.files??[]),"device"),A.value=""});let Z=0;L.addEventListener("dragenter",l=>{l.preventDefault(),Z++,L.dataset.state==="idle"&&(L.dataset.drag="true")}),L.addEventListener("dragover",l=>{l.preventDefault(),l.dataTransfer&&(l.dataTransfer.dropEffect="copy")}),L.addEventListener("dragleave",()=>{--Z<=0&&(Z=0,delete L.dataset.drag)}),L.addEventListener("drop",l=>{l.preventDefault(),Z=0,delete L.dataset.drag,L.dataset.state==="idle"&&N(Array.from(l.dataTransfer?.files??[]),"device")}),m(".clear").addEventListener("click",()=>{for(let l of[...C])k(l)});let q=(l,u=!1)=>{m(".status span").textContent=l,m(".status").classList.toggle("live",u)},ae=()=>{L.dataset.state="idle",m(".idle").hidden=!1,m(".phone-view").hidden=!0,m(".phone").focus()},j=new Map,d=()=>{L.dataset.state="phone",m(".idle").hidden=!0,m(".phone-view").hidden=!1,m(".qr-box").classList.add("loading"),m(".done").hidden=!0,m(".code-line").textContent="",q(i("loading"));let l=Math.max(1,a-U().length),u=se({...t,ui:!1,multiple:o,maxFiles:o?l:1,maxFileBytes:s,accept:p});D=u,u.on("ready",({claimUrl:x,code:w})=>{be(m(".qr"),x,168),m(".qr").setAttribute("aria-label",i("phoneTitle")),m(".qr-box").classList.remove("loading","dim");let _=m(".code-line"),I=document.createElement("b");I.textContent=Qe(w),_.replaceChildren(document.createTextNode(`${i("phoneCode",{host:new URL(x).host})} `),I),q(i("waiting"))});let E="";u.on("phone",({phone:x,needsApproval:w})=>{E=x.label,m(".qr-box").classList.add("dim"),q(i("connected",{label:x.label}),!0),w&&u.approve()}),u.on("direct",({connected:x})=>{E&&q(i(x?"connectedDirect":"connected",{label:E}),!0)}),u.on("phone_left",()=>q(i("phoneLeft"))),u.on("file_started",x=>{let w={key:x.id,file:null,name:x.name,size:x.size,source:"phone",percent:0};j.set(x.id,w),C.push(w),b()}),u.on("progress",({id:x,sent:w,total:_,phase:I})=>{let W=j.get(x);if(!W)return;let ie=_?w/_:0;W.phase=I,W.percent=Math.min(99,Math.floor(I==="upload"?ie*90:90+ie*10)),T(W)}),u.on("received",({id:x,file:w})=>{let _=j.get(x);j.delete(x);let I=H(w,"phone");if(_){if(Object.assign(_,{file:w,name:w.name,size:w.size,percent:100,...I.url?{url:I.url}:{}}),!o)for(let W of C.filter(ie=>ie!==_))k(W);T(_)}else C.push(I);b(),c(),m(".done").hidden=!1}),u.on("file_failed",({id:x})=>{let w=j.get(x);w&&(w.failed=!0,T(w))}),u.on("error",x=>q(i("error",{message:x.message}))),u.on("close",x=>{for(let w of j.values())w.failed=!0,T(w);j.clear(),D===u&&(D=null),x==="finished"||x==="canceled"?ae():(m(".qr-box").classList.add("dim"),q(i("expired")))})},h=()=>{D?D.finish():ae()};return m(".phone").addEventListener("click",()=>{if(f==="modal"){let l=Math.max(1,a-U().length);se({...t,ui:!0,multiple:o,maxFiles:o?l:1,maxFileBytes:s,accept:p}).done.then(u=>N(u,"phone"))}else d()}),m(".back").addEventListener("click",h),m(".done").addEventListener("click",h),P.addEventListener("keydown",l=>{l.key==="Escape"&&L.dataset.state==="phone"&&h()}),{get files(){return U()},input:g,on(l,u){return J.add(u),()=>J.delete(u)},remove(l){let u=C.find(E=>E.file===l);u&&k(u)},clear(){for(let l of[...C])k(l)},destroy(){D?.cancel();for(let l of C)l.url&&URL.revokeObjectURL(l.url);y.remove(),g.remove()}}}function tt(n={},t="tokshare-pick-field"){typeof customElements>"u"||customElements.get(t)||customElements.define(t,class extends HTMLElement{constructor(){super(...arguments);M(this,"controller",null)}connectedCallback(){if(this.controller)return;let e=p=>this.getAttribute(p)??void 0,i=e("phone"),o=Number(e("max-files")),a=Number(e("resize")),s=Rt(e("max-size"));this.controller=ze(this,{...n,key:e("key")??n.key??"",...e("relay")??n.relay?{relay:e("relay")??n.relay}:{},...e("name")?{name:e("name")}:{},...e("accept")?{accept:e("accept")}:{},multiple:this.hasAttribute("multiple"),...o>0?{maxFiles:o}:{},...s?{maxFileBytes:s}:{},...a>0?{resizeImages:{maxDimension:a}}:{},...i==="off"?{phone:!1}:i==="modal"?{phone:"modal"}:{},...e("locale")?{locale:e("locale")}:{},...e("theme")?{theme:e("theme")}:{},...e("label")?{label:e("label")}:{},...e("direct")==="off"?{direct:!1}:{},...e("announce")==="off"?{announce:!1}:{}}),this.controller.on("change",p=>this.dispatchEvent(new CustomEvent("files",{detail:p,bubbles:!0})))}disconnectedCallback(){this.controller?.destroy(),this.controller=null}get files(){return this.controller?.files??[]}clear(){this.controller?.clear()}})}var pe=document.currentScript,X={key:pe?.dataset.key??"",relay:pe?.dataset.relay,locale:pe?.dataset.locale??"auto",...pe?.dataset.direct==="off"?{direct:!1}:{},...pe?.dataset.announce==="off"?{announce:!1}:{}},ue=n=>({...X,...n}),Bt={pick:n=>Ae(ue(n)),open:n=>se(ue(n)),attach:(n,t)=>Fe(n,ue(t)),mountField:(n,t={})=>ze(n,ue(t)),PickError:B};window.TokSharePick=Bt;tt({key:X.key,...X.relay?{relay:X.relay}:{},locale:X.locale,...X.direct===!1?{direct:!1}:{},...X.announce===!1?{announce:!1}:{}});document.addEventListener("click",n=>{let t=n.target?.closest?.("[data-tokshare-pick-for]");if(!t)return;let r=document.getElementById(t.getAttribute("data-tokshare-pick-for")??"");if(!(r instanceof HTMLInputElement)||r.type!=="file"){console.warn("TokShare Pick: no <input type=file> with that id");return}if(n.preventDefault(),!X.key){console.warn('TokShare Pick: add data-key="pk_\u2026" to the script tag');return}Fe(r,ue({mode:t.getAttribute("data-mode")==="append"?"append":"replace"}))()});})();
package/dist/react.cjs ADDED
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ "use client";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/react.tsx
22
+ var react_exports = {};
23
+ __export(react_exports, {
24
+ TokSharePick: () => TokSharePick,
25
+ TokSharePickButton: () => TokSharePickButton,
26
+ TokShareProvider: () => TokShareProvider,
27
+ useTokSharePick: () => useTokSharePick
28
+ });
29
+ module.exports = __toCommonJS(react_exports);
30
+ var import_pick = require("@tokshare/pick");
31
+ var import_react = require("react");
32
+ var import_jsx_runtime = require("react/jsx-runtime");
33
+ var TokShareContext = (0, import_react.createContext)({});
34
+ function TokShareProvider({ children, ...settings }) {
35
+ const parent = (0, import_react.useContext)(TokShareContext);
36
+ const { pickKey, relay, locale, theme } = settings;
37
+ const value = (0, import_react.useMemo)(() => ({ ...parent, ...defined({ pickKey, relay, locale, theme }) }), [parent, pickKey, relay, locale, theme]);
38
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TokShareContext.Provider, { value, children });
39
+ }
40
+ function defined(value) {
41
+ return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== void 0));
42
+ }
43
+ function toCoreOptions(settings, props, component) {
44
+ const { pickKey, maxFileBytes, resize, ...rest } = props;
45
+ const key = pickKey ?? settings.pickKey;
46
+ if (!key) throw new Error(`${component}: pass pickKey, or wrap your app in <TokShareProvider pickKey="pk_\u2026">.`);
47
+ const bytes = (0, import_pick.parseSize)(maxFileBytes);
48
+ return {
49
+ ...defined({ relay: settings.relay, locale: settings.locale, theme: settings.theme }),
50
+ ...defined(rest),
51
+ key,
52
+ ...bytes ? { maxFileBytes: bytes } : {},
53
+ ...resize && resize > 0 && rest.resizeImages === void 0 ? { resizeImages: { maxDimension: resize } } : {}
54
+ };
55
+ }
56
+ function useTokSharePick(defaults = {}) {
57
+ const settings = (0, import_react.useContext)(TokShareContext);
58
+ const latest = (0, import_react.useRef)({ settings, defaults });
59
+ latest.current = { settings, defaults };
60
+ return (0, import_react.useMemo)(() => ({
61
+ /** Opens the phone window; resolves with the files, or [] if the person cancels. */
62
+ pick: (options = {}) => (0, import_pick.pick)(toCoreOptions(latest.current.settings, { ...latest.current.defaults, ...options }, "useTokSharePick")),
63
+ /** The same with live events (phone, progress, file) and your own UI if you pass ui: false. */
64
+ open: (options = {}) => {
65
+ const { ui, ...rest } = options;
66
+ return (0, import_pick.open)({ ...toCoreOptions(latest.current.settings, { ...latest.current.defaults, ...rest }, "useTokSharePick"), ...ui === void 0 ? {} : { ui } });
67
+ }
68
+ }), []);
69
+ }
70
+ var TokSharePick = (0, import_react.forwardRef)(function TokSharePick2(props, ref) {
71
+ const { onChange, className, style, id, ...options } = props;
72
+ const settings = (0, import_react.useContext)(TokShareContext);
73
+ const core = toCoreOptions(settings, options, "<TokSharePick>");
74
+ const signature = JSON.stringify(core);
75
+ const container = (0, import_react.useRef)(null);
76
+ const controller = (0, import_react.useRef)(null);
77
+ const onChangeRef = (0, import_react.useRef)(onChange);
78
+ onChangeRef.current = onChange;
79
+ (0, import_react.useEffect)(() => {
80
+ const field = (0, import_pick.mountField)(container.current, JSON.parse(signature));
81
+ controller.current = field;
82
+ const off = field.on("change", (files) => onChangeRef.current?.(files));
83
+ return () => {
84
+ off();
85
+ field.destroy();
86
+ if (controller.current === field) controller.current = null;
87
+ };
88
+ }, [signature]);
89
+ (0, import_react.useImperativeHandle)(ref, () => ({
90
+ get files() {
91
+ return controller.current?.files ?? [];
92
+ },
93
+ get input() {
94
+ return controller.current?.input ?? null;
95
+ },
96
+ remove: (file) => controller.current?.remove(file),
97
+ clear: () => controller.current?.clear()
98
+ }), []);
99
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: container, className, style, id });
100
+ });
101
+ var PICK_OPTION_NAMES = [
102
+ "pickKey",
103
+ "maxFileBytes",
104
+ "resize",
105
+ "accept",
106
+ "multiple",
107
+ "maxFiles",
108
+ "resizeImages",
109
+ "confirmPhone",
110
+ "siteName",
111
+ "relay",
112
+ "locale",
113
+ "theme",
114
+ "strings",
115
+ "direct",
116
+ "announce"
117
+ ];
118
+ var TokSharePickButton = (0, import_react.forwardRef)(function TokSharePickButton2(props, ref) {
119
+ const { onFiles, onError, onClick, children, disabled, type, ...rest } = props;
120
+ const options = {};
121
+ const buttonProps = {};
122
+ for (const [name, value] of Object.entries(rest)) {
123
+ (PICK_OPTION_NAMES.includes(name) ? options : buttonProps)[name] = value;
124
+ }
125
+ const { pick: pickFiles } = useTokSharePick(options);
126
+ const [busy, setBusy] = (0, import_react.useState)(false);
127
+ const mounted = (0, import_react.useRef)(true);
128
+ (0, import_react.useEffect)(() => {
129
+ mounted.current = true;
130
+ return () => {
131
+ mounted.current = false;
132
+ };
133
+ }, []);
134
+ const handleClick = (0, import_react.useCallback)(async (event) => {
135
+ onClick?.(event);
136
+ if (event.defaultPrevented) return;
137
+ setBusy(true);
138
+ try {
139
+ const files = await pickFiles();
140
+ if (files.length) onFiles?.(files);
141
+ } catch (error) {
142
+ if (onError) onError(error);
143
+ else console.error(error);
144
+ } finally {
145
+ if (mounted.current) setBusy(false);
146
+ }
147
+ }, [onClick, onFiles, onError, pickFiles]);
148
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { ref, type: type ?? "button", disabled: disabled || busy, "aria-busy": busy || void 0, onClick: handleClick, ...buttonProps, children: children ?? "From my phone" });
149
+ });
150
+ // Annotate the CommonJS export names for ESM import in node:
151
+ 0 && (module.exports = {
152
+ TokSharePick,
153
+ TokSharePickButton,
154
+ TokShareProvider,
155
+ useTokSharePick
156
+ });
157
+ //# sourceMappingURL=react.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/react.tsx"],"sourcesContent":["\"use client\";\n// @tokshare/pick/react: the upload field, a phone button and a hook, as React components.\n//\n// <TokShareProvider pickKey=\"pk_live_…\"> once, near the top of the app\n// <TokSharePick name=\"photos\" accept=\"image/*\" maxFileBytes=\"5MB\" onChange={setFiles} />\n// <TokSharePickButton accept=\"image/*\" onFiles={addFiles}>From my phone</TokSharePickButton>\n// </TokShareProvider>\n//\n// The core is imported from \"@tokshare/pick\" (not bundled in), so an app that uses both gets one copy.\nimport { mountField, open, parseSize, pick, type FieldController, type FieldOptions, type PickController, type PickOptions } from \"@tokshare/pick\";\nimport {\n createContext, forwardRef, useCallback, useContext, useEffect, useImperativeHandle, useMemo, useRef, useState,\n type ButtonHTMLAttributes, type CSSProperties, type MouseEvent, type ReactNode,\n} from \"react\";\n\n// ---- Shared settings ----------------------------------------------------------------------------\n\nexport interface TokShareSettings {\n /** Your publishable key (pk_live_… or pk_test_…). React reserves `key`, hence `pickKey`. */\n pickKey?: string;\n /** Relay URL. Defaults to the hosted relay. */\n relay?: string;\n locale?: PickOptions[\"locale\"];\n theme?: PickOptions[\"theme\"];\n}\n\nconst TokShareContext = createContext<TokShareSettings>({});\n\n/** Sets the key (and optionally relay, locale, theme) once for every TokShare component inside it. */\nexport function TokShareProvider({ children, ...settings }: TokShareSettings & { children?: ReactNode }) {\n const parent = useContext(TokShareContext);\n const { pickKey, relay, locale, theme } = settings;\n const value = useMemo(() => ({ ...parent, ...defined({ pickKey, relay, locale, theme }) }), [parent, pickKey, relay, locale, theme]);\n return <TokShareContext.Provider value={value}>{children}</TokShareContext.Provider>;\n}\n\n/** Options shared by the field, the button and the hook. Sizes take bytes or \"5MB\", \"500KB\". */\nexport interface TokSharePickOptions extends Omit<PickOptions, \"key\" | \"ui\" | \"maxFileBytes\" | \"signal\"> {\n /** Overrides the provider's key. */\n pickKey?: string;\n maxFileBytes?: number | string;\n /** Phone shrinks photos so the longest side is at most this many pixels. Short for resizeImages. */\n resize?: number;\n}\n\nfunction defined<T extends object>(value: T): Partial<T> {\n return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined)) as Partial<T>;\n}\n\n/** Provider settings + component props → core options. Throws early if no key was given anywhere. */\nfunction toCoreOptions(settings: TokShareSettings, props: TokSharePickOptions, component: string): PickOptions {\n const { pickKey, maxFileBytes, resize, ...rest } = props;\n const key = pickKey ?? settings.pickKey;\n if (!key) throw new Error(`${component}: pass pickKey, or wrap your app in <TokShareProvider pickKey=\"pk_…\">.`);\n const bytes = parseSize(maxFileBytes);\n return {\n ...defined({ relay: settings.relay, locale: settings.locale, theme: settings.theme }),\n ...defined(rest),\n key,\n ...(bytes ? { maxFileBytes: bytes } : {}),\n ...(resize && resize > 0 && rest.resizeImages === undefined ? { resizeImages: { maxDimension: resize } } : {}),\n };\n}\n\n// ---- Hook ---------------------------------------------------------------------------------------\n\n/**\n * `const { pick } = useTokSharePick({ accept: \"image/*\" })`, then `const files = await pick()` in a click\n * handler. Options given to pick() override the hook's, which override the provider's.\n */\nexport function useTokSharePick(defaults: TokSharePickOptions = {}) {\n const settings = useContext(TokShareContext);\n const latest = useRef({ settings, defaults });\n latest.current = { settings, defaults };\n return useMemo(() => ({\n /** Opens the phone window; resolves with the files, or [] if the person cancels. */\n pick: (options: TokSharePickOptions = {}): Promise<File[]> =>\n pick(toCoreOptions(latest.current.settings, { ...latest.current.defaults, ...options }, \"useTokSharePick\")),\n /** The same with live events (phone, progress, file) and your own UI if you pass ui: false. */\n open: (options: TokSharePickOptions & { ui?: boolean } = {}): PickController => {\n const { ui, ...rest } = options;\n return open({ ...toCoreOptions(latest.current.settings, { ...latest.current.defaults, ...rest }, \"useTokSharePick\"), ...(ui === undefined ? {} : { ui }) });\n },\n }), []);\n}\n\n// ---- Upload field -------------------------------------------------------------------------------\n\nexport interface TokSharePickProps extends TokSharePickOptions, Pick<FieldOptions, \"name\" | \"phone\" | \"phoneOnMobile\" | \"label\"> {\n /** Every time the list changes: files from this computer and from the phone, in order. */\n onChange?: (files: File[]) => void;\n className?: string;\n style?: CSSProperties;\n id?: string;\n}\n\nexport interface TokSharePickHandle {\n /** The files in the field right now. */\n readonly files: readonly File[];\n /** The hidden <input type=\"file\" name> the files are kept in, for forms. */\n readonly input: HTMLInputElement | null;\n remove(file: File): void;\n clear(): void;\n}\n\n/**\n * The complete upload field: drop zone, \"Browse files\" and \"Use your phone\". With `name`, a normal\n * form submit includes the files. Changing an option rebuilds the field (and empties it).\n */\nexport const TokSharePick = forwardRef<TokSharePickHandle, TokSharePickProps>(function TokSharePick(props, ref) {\n const { onChange, className, style, id, ...options } = props;\n const settings = useContext(TokShareContext);\n // name, phone, phoneOnMobile and label ride along with the pick options.\n const core = toCoreOptions(settings, options, \"<TokSharePick>\") as FieldOptions;\n // Inline objects (strings={{…}}) are new on every render: rebuild only when the values change.\n const signature = JSON.stringify(core);\n const container = useRef<HTMLDivElement>(null);\n const controller = useRef<FieldController | null>(null);\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n\n useEffect(() => {\n const field = mountField(container.current!, JSON.parse(signature) as FieldOptions);\n controller.current = field;\n const off = field.on(\"change\", (files) => onChangeRef.current?.(files));\n return () => {\n off();\n field.destroy();\n if (controller.current === field) controller.current = null;\n };\n }, [signature]);\n\n useImperativeHandle(ref, () => ({\n get files() { return controller.current?.files ?? []; },\n get input() { return controller.current?.input ?? null; },\n remove: (file: File) => controller.current?.remove(file),\n clear: () => controller.current?.clear(),\n }), []);\n\n return <div ref={container} className={className} style={style} id={id} />;\n});\n\n// ---- Button -------------------------------------------------------------------------------------\n\nexport interface TokSharePickButtonProps\n extends TokSharePickOptions, Omit<ButtonHTMLAttributes<HTMLButtonElement>, keyof TokSharePickOptions | \"onError\"> {\n /** The files the person sent (not called if they cancel). */\n onFiles?: (files: File[]) => void;\n onError?: (error: unknown) => void;\n}\n\nconst PICK_OPTION_NAMES = [\n \"pickKey\", \"maxFileBytes\", \"resize\", \"accept\", \"multiple\", \"maxFiles\", \"resizeImages\", \"confirmPhone\",\n \"siteName\", \"relay\", \"locale\", \"theme\", \"strings\", \"direct\", \"announce\",\n] as const satisfies readonly (keyof TokSharePickOptions)[];\n\n/** A button that opens the phone window and hands you the files. Takes every <button> prop too. */\nexport const TokSharePickButton = forwardRef<HTMLButtonElement, TokSharePickButtonProps>(function TokSharePickButton(props, ref) {\n const { onFiles, onError, onClick, children, disabled, type, ...rest } = props;\n const options: Record<string, unknown> = {};\n const buttonProps: Record<string, unknown> = {};\n for (const [name, value] of Object.entries(rest)) {\n ((PICK_OPTION_NAMES as readonly string[]).includes(name) ? options : buttonProps)[name] = value;\n }\n const { pick: pickFiles } = useTokSharePick(options as TokSharePickOptions);\n const [busy, setBusy] = useState(false);\n const mounted = useRef(true);\n useEffect(() => { mounted.current = true; return () => { mounted.current = false; }; }, []);\n\n const handleClick = useCallback(async (event: MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n if (event.defaultPrevented) return;\n setBusy(true);\n try {\n const files = await pickFiles();\n if (files.length) onFiles?.(files);\n } catch (error) {\n if (onError) onError(error);\n else console.error(error);\n } finally {\n if (mounted.current) setBusy(false);\n }\n }, [onClick, onFiles, onError, pickFiles]);\n\n return (\n <button ref={ref} type={type ?? \"button\"} disabled={disabled || busy} aria-busy={busy || undefined} onClick={handleClick} {...buttonProps}>\n {children ?? \"From my phone\"}\n </button>\n );\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASA,kBAAkI;AAClI,mBAGO;AAoBE;AAPT,IAAM,sBAAkB,4BAAgC,CAAC,CAAC;AAGnD,SAAS,iBAAiB,EAAE,UAAU,GAAG,SAAS,GAAgD;AACvG,QAAM,aAAS,yBAAW,eAAe;AACzC,QAAM,EAAE,SAAS,OAAO,QAAQ,MAAM,IAAI;AAC1C,QAAM,YAAQ,sBAAQ,OAAO,EAAE,GAAG,QAAQ,GAAG,QAAQ,EAAE,SAAS,OAAO,QAAQ,MAAM,CAAC,EAAE,IAAI,CAAC,QAAQ,SAAS,OAAO,QAAQ,KAAK,CAAC;AACnI,SAAO,4CAAC,gBAAgB,UAAhB,EAAyB,OAAe,UAAS;AAC3D;AAWA,SAAS,QAA0B,OAAsB;AACvD,SAAO,OAAO,YAAY,OAAO,QAAQ,KAAK,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,MAAM,UAAU,MAAS,CAAC;AAC5F;AAGA,SAAS,cAAc,UAA4B,OAA4B,WAAgC;AAC7G,QAAM,EAAE,SAAS,cAAc,QAAQ,GAAG,KAAK,IAAI;AACnD,QAAM,MAAM,WAAW,SAAS;AAChC,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,GAAG,SAAS,6EAAwE;AAC9G,QAAM,YAAQ,uBAAU,YAAY;AACpC,SAAO;AAAA,IACL,GAAG,QAAQ,EAAE,OAAO,SAAS,OAAO,QAAQ,SAAS,QAAQ,OAAO,SAAS,MAAM,CAAC;AAAA,IACpF,GAAG,QAAQ,IAAI;AAAA,IACf;AAAA,IACA,GAAI,QAAQ,EAAE,cAAc,MAAM,IAAI,CAAC;AAAA,IACvC,GAAI,UAAU,SAAS,KAAK,KAAK,iBAAiB,SAAY,EAAE,cAAc,EAAE,cAAc,OAAO,EAAE,IAAI,CAAC;AAAA,EAC9G;AACF;AAQO,SAAS,gBAAgB,WAAgC,CAAC,GAAG;AAClE,QAAM,eAAW,yBAAW,eAAe;AAC3C,QAAM,aAAS,qBAAO,EAAE,UAAU,SAAS,CAAC;AAC5C,SAAO,UAAU,EAAE,UAAU,SAAS;AACtC,aAAO,sBAAQ,OAAO;AAAA;AAAA,IAEpB,MAAM,CAAC,UAA+B,CAAC,UACrC,kBAAK,cAAc,OAAO,QAAQ,UAAU,EAAE,GAAG,OAAO,QAAQ,UAAU,GAAG,QAAQ,GAAG,iBAAiB,CAAC;AAAA;AAAA,IAE5G,MAAM,CAAC,UAAkD,CAAC,MAAsB;AAC9E,YAAM,EAAE,IAAI,GAAG,KAAK,IAAI;AACxB,iBAAO,kBAAK,EAAE,GAAG,cAAc,OAAO,QAAQ,UAAU,EAAE,GAAG,OAAO,QAAQ,UAAU,GAAG,KAAK,GAAG,iBAAiB,GAAG,GAAI,OAAO,SAAY,CAAC,IAAI,EAAE,GAAG,EAAG,CAAC;AAAA,IAC5J;AAAA,EACF,IAAI,CAAC,CAAC;AACR;AAyBO,IAAM,mBAAe,yBAAkD,SAASA,cAAa,OAAO,KAAK;AAC9G,QAAM,EAAE,UAAU,WAAW,OAAO,IAAI,GAAG,QAAQ,IAAI;AACvD,QAAM,eAAW,yBAAW,eAAe;AAE3C,QAAM,OAAO,cAAc,UAAU,SAAS,gBAAgB;AAE9D,QAAM,YAAY,KAAK,UAAU,IAAI;AACrC,QAAM,gBAAY,qBAAuB,IAAI;AAC7C,QAAM,iBAAa,qBAA+B,IAAI;AACtD,QAAM,kBAAc,qBAAO,QAAQ;AACnC,cAAY,UAAU;AAEtB,8BAAU,MAAM;AACd,UAAM,YAAQ,wBAAW,UAAU,SAAU,KAAK,MAAM,SAAS,CAAiB;AAClF,eAAW,UAAU;AACrB,UAAM,MAAM,MAAM,GAAG,UAAU,CAAC,UAAU,YAAY,UAAU,KAAK,CAAC;AACtE,WAAO,MAAM;AACX,UAAI;AACJ,YAAM,QAAQ;AACd,UAAI,WAAW,YAAY,MAAO,YAAW,UAAU;AAAA,IACzD;AAAA,EACF,GAAG,CAAC,SAAS,CAAC;AAEd,wCAAoB,KAAK,OAAO;AAAA,IAC9B,IAAI,QAAQ;AAAE,aAAO,WAAW,SAAS,SAAS,CAAC;AAAA,IAAG;AAAA,IACtD,IAAI,QAAQ;AAAE,aAAO,WAAW,SAAS,SAAS;AAAA,IAAM;AAAA,IACxD,QAAQ,CAAC,SAAe,WAAW,SAAS,OAAO,IAAI;AAAA,IACvD,OAAO,MAAM,WAAW,SAAS,MAAM;AAAA,EACzC,IAAI,CAAC,CAAC;AAEN,SAAO,4CAAC,SAAI,KAAK,WAAW,WAAsB,OAAc,IAAQ;AAC1E,CAAC;AAWD,IAAM,oBAAoB;AAAA,EACxB;AAAA,EAAW;AAAA,EAAgB;AAAA,EAAU;AAAA,EAAU;AAAA,EAAY;AAAA,EAAY;AAAA,EAAgB;AAAA,EACvF;AAAA,EAAY;AAAA,EAAS;AAAA,EAAU;AAAA,EAAS;AAAA,EAAW;AAAA,EAAU;AAC/D;AAGO,IAAM,yBAAqB,yBAAuD,SAASC,oBAAmB,OAAO,KAAK;AAC/H,QAAM,EAAE,SAAS,SAAS,SAAS,UAAU,UAAU,MAAM,GAAG,KAAK,IAAI;AACzE,QAAM,UAAmC,CAAC;AAC1C,QAAM,cAAuC,CAAC;AAC9C,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AAChD,KAAE,kBAAwC,SAAS,IAAI,IAAI,UAAU,aAAa,IAAI,IAAI;AAAA,EAC5F;AACA,QAAM,EAAE,MAAM,UAAU,IAAI,gBAAgB,OAA8B;AAC1E,QAAM,CAAC,MAAM,OAAO,QAAI,uBAAS,KAAK;AACtC,QAAM,cAAU,qBAAO,IAAI;AAC3B,8BAAU,MAAM;AAAE,YAAQ,UAAU;AAAM,WAAO,MAAM;AAAE,cAAQ,UAAU;AAAA,IAAO;AAAA,EAAG,GAAG,CAAC,CAAC;AAE1F,QAAM,kBAAc,0BAAY,OAAO,UAAyC;AAC9E,cAAU,KAAK;AACf,QAAI,MAAM,iBAAkB;AAC5B,YAAQ,IAAI;AACZ,QAAI;AACF,YAAM,QAAQ,MAAM,UAAU;AAC9B,UAAI,MAAM,OAAQ,WAAU,KAAK;AAAA,IACnC,SAAS,OAAO;AACd,UAAI,QAAS,SAAQ,KAAK;AAAA,UACrB,SAAQ,MAAM,KAAK;AAAA,IAC1B,UAAE;AACA,UAAI,QAAQ,QAAS,SAAQ,KAAK;AAAA,IACpC;AAAA,EACF,GAAG,CAAC,SAAS,SAAS,SAAS,SAAS,CAAC;AAEzC,SACE,4CAAC,YAAO,KAAU,MAAM,QAAQ,UAAU,UAAU,YAAY,MAAM,aAAW,QAAQ,QAAW,SAAS,aAAc,GAAG,aAC3H,sBAAY,iBACf;AAEJ,CAAC;","names":["TokSharePick","TokSharePickButton"]}