@useupup/core 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +8 -0
  3. package/README.md +75 -0
  4. package/dist/browser-SXR426OQ.cjs +10 -0
  5. package/dist/browser-WD6T5ABJ.js +1 -0
  6. package/dist/chunk-2H5ICKFT.cjs +122 -0
  7. package/dist/chunk-6HF3I2JS.cjs +39 -0
  8. package/dist/chunk-6S5DQDQH.js +212 -0
  9. package/dist/chunk-BMQC27OE.cjs +92 -0
  10. package/dist/chunk-BSGQGINR.cjs +219 -0
  11. package/dist/chunk-CPKZ2CXD.cjs +179 -0
  12. package/dist/chunk-DTKDIMKT.cjs +573 -0
  13. package/dist/chunk-DYE5XJ6Z.cjs +2134 -0
  14. package/dist/chunk-E3ZCNOXG.cjs +74 -0
  15. package/dist/chunk-FEQY2WYY.cjs +2377 -0
  16. package/dist/chunk-FMURBCZ7.js +120 -0
  17. package/dist/chunk-FYQQRULL.js +37 -0
  18. package/dist/chunk-GE4LIVXP.js +133 -0
  19. package/dist/chunk-HFR5HZJZ.js +56 -0
  20. package/dist/chunk-I7ULPCA2.js +72 -0
  21. package/dist/chunk-MHYXDLZR.js +569 -0
  22. package/dist/chunk-N2SLHVAW.cjs +61 -0
  23. package/dist/chunk-OOPDEOTM.js +169 -0
  24. package/dist/chunk-PMBR3OUW.js +2359 -0
  25. package/dist/chunk-QK7HZIVY.cjs +144 -0
  26. package/dist/chunk-T2AQHY7V.cjs +59 -0
  27. package/dist/chunk-TRCP5FUR.js +90 -0
  28. package/dist/chunk-U7KL5M2H.cjs +374 -0
  29. package/dist/chunk-UXNPM54W.js +2108 -0
  30. package/dist/chunk-VV6QCQLL.js +365 -0
  31. package/dist/chunk-ZMS2HXLB.js +56 -0
  32. package/dist/context-shapes-123dd3b6.d.cts +207 -0
  33. package/dist/context-shapes-27b24c8f.d.ts +207 -0
  34. package/dist/contracts-pipeline-cf177270.d.cts +78 -0
  35. package/dist/contracts-pipeline-cf177270.d.ts +78 -0
  36. package/dist/contracts-strategies-378a16b7.d.cts +168 -0
  37. package/dist/contracts-strategies-378a16b7.d.ts +168 -0
  38. package/dist/contracts.cjs +181 -0
  39. package/dist/contracts.d.cts +11 -0
  40. package/dist/contracts.d.ts +11 -0
  41. package/dist/contracts.js +4 -0
  42. package/dist/core-141335ac.d.ts +651 -0
  43. package/dist/core-bea2ceca.d.cts +651 -0
  44. package/dist/create-worker-provider-AA5SRII6.js +58 -0
  45. package/dist/create-worker-provider-KJNUSSTW.cjs +60 -0
  46. package/dist/eligibility-ONLNJ6FB.cjs +10 -0
  47. package/dist/eligibility-ULFC3E4G.js +8 -0
  48. package/dist/error-code-map-9c44a425.d.ts +62 -0
  49. package/dist/error-code-map-dd5becfa.d.cts +62 -0
  50. package/dist/i18n/index.cjs +90 -0
  51. package/dist/i18n/index.d.cts +3 -0
  52. package/dist/i18n/index.d.ts +3 -0
  53. package/dist/i18n/index.js +1 -0
  54. package/dist/index.cjs +1770 -0
  55. package/dist/index.d.cts +280 -0
  56. package/dist/index.d.ts +280 -0
  57. package/dist/index.js +1589 -0
  58. package/dist/internal.cjs +2407 -0
  59. package/dist/internal.d.cts +595 -0
  60. package/dist/internal.d.ts +595 -0
  61. package/dist/internal.js +2275 -0
  62. package/dist/pipeline/index.cjs +10 -0
  63. package/dist/pipeline/index.d.cts +11 -0
  64. package/dist/pipeline/index.d.ts +11 -0
  65. package/dist/pipeline/index.js +1 -0
  66. package/dist/pipeline-worker.cjs +199 -0
  67. package/dist/pipeline-worker.d.cts +2 -0
  68. package/dist/pipeline-worker.d.ts +2 -0
  69. package/dist/pipeline-worker.js +197 -0
  70. package/dist/resolve-locale-81feef21.d.ts +20 -0
  71. package/dist/resolve-locale-9cb63600.d.cts +20 -0
  72. package/dist/resolve-theme-01758105.d.ts +53 -0
  73. package/dist/resolve-theme-66cf8d98.d.cts +53 -0
  74. package/dist/server-mode-drive-controller-b5f8ee12.d.cts +180 -0
  75. package/dist/server-mode-drive-controller-b5f8ee12.d.ts +180 -0
  76. package/dist/steps/compress.cjs +66 -0
  77. package/dist/steps/compress.d.cts +10 -0
  78. package/dist/steps/compress.d.ts +10 -0
  79. package/dist/steps/compress.js +64 -0
  80. package/dist/steps/exif.cjs +44 -0
  81. package/dist/steps/exif.d.cts +5 -0
  82. package/dist/steps/exif.d.ts +5 -0
  83. package/dist/steps/exif.js +42 -0
  84. package/dist/steps/hash.cjs +44 -0
  85. package/dist/steps/hash.d.cts +5 -0
  86. package/dist/steps/hash.d.ts +5 -0
  87. package/dist/steps/hash.js +42 -0
  88. package/dist/steps/heic.cjs +59 -0
  89. package/dist/steps/heic.d.cts +5 -0
  90. package/dist/steps/heic.d.ts +5 -0
  91. package/dist/steps/heic.js +57 -0
  92. package/dist/steps/thumbnail.cjs +54 -0
  93. package/dist/steps/thumbnail.d.cts +10 -0
  94. package/dist/steps/thumbnail.d.ts +10 -0
  95. package/dist/steps/thumbnail.js +52 -0
  96. package/dist/strategies/index.cjs +82 -0
  97. package/dist/strategies/index.d.cts +187 -0
  98. package/dist/strategies/index.d.ts +187 -0
  99. package/dist/strategies/index.js +60 -0
  100. package/dist/strategies/tus-upload.cjs +14 -0
  101. package/dist/strategies/tus-upload.d.cts +15 -0
  102. package/dist/strategies/tus-upload.d.ts +15 -0
  103. package/dist/strategies/tus-upload.js +5 -0
  104. package/dist/theme/index.cjs +38 -0
  105. package/dist/theme/index.d.cts +3 -0
  106. package/dist/theme/index.d.ts +3 -0
  107. package/dist/theme/index.js +1 -0
  108. package/dist/theme-store-2e56a674.d.cts +39 -0
  109. package/dist/theme-store-f13e0315.d.ts +39 -0
  110. package/dist/token-endpoint-5fdb4a35.d.ts +20 -0
  111. package/dist/token-endpoint-a7d15ab6.d.cts +20 -0
  112. package/dist/ui-translations-c5d00392.d.cts +455 -0
  113. package/dist/ui-translations-c5d00392.d.ts +455 -0
  114. package/dist/uploader-props-72242002.d.ts +340 -0
  115. package/dist/uploader-props-7f956e60.d.cts +340 -0
  116. package/dist/vars-d3421f6c.d.cts +240 -0
  117. package/dist/vars-d3421f6c.d.ts +240 -0
  118. package/package.json +182 -0
@@ -0,0 +1,144 @@
1
+ 'use strict';
2
+
3
+ // src/errors.ts
4
+ var UpupErrorCode = /* @__PURE__ */ ((UpupErrorCode2) => {
5
+ UpupErrorCode2["AUTH_EXPIRED"] = "AUTH_EXPIRED";
6
+ UpupErrorCode2["AUTH_DENIED"] = "AUTH_DENIED";
7
+ UpupErrorCode2["AUTH_PROVIDER_ERROR"] = "AUTH_PROVIDER_ERROR";
8
+ UpupErrorCode2["FILE_TOO_LARGE"] = "FILE_TOO_LARGE";
9
+ UpupErrorCode2["FILE_TOO_SMALL"] = "FILE_TOO_SMALL";
10
+ UpupErrorCode2["TYPE_MISMATCH"] = "TYPE_MISMATCH";
11
+ UpupErrorCode2["LIMIT_EXCEEDED"] = "LIMIT_EXCEEDED";
12
+ UpupErrorCode2["TOTAL_SIZE_EXCEEDED"] = "TOTAL_SIZE_EXCEEDED";
13
+ UpupErrorCode2["DUPLICATE"] = "DUPLICATE";
14
+ UpupErrorCode2["MIN_FILES_NOT_MET"] = "MIN_FILES_NOT_MET";
15
+ UpupErrorCode2["UPLOAD_FAILED"] = "UPLOAD_FAILED";
16
+ UpupErrorCode2["UPLOAD_ABORTED"] = "UPLOAD_ABORTED";
17
+ UpupErrorCode2["PRESIGN_FAILED"] = "PRESIGN_FAILED";
18
+ UpupErrorCode2["CORS_ERROR"] = "CORS_ERROR";
19
+ UpupErrorCode2["PIPELINE_STEP_FAILED"] = "PIPELINE_STEP_FAILED";
20
+ UpupErrorCode2["HEIC_CONVERSION_FAILED"] = "HEIC_CONVERSION_FAILED";
21
+ UpupErrorCode2["NETWORK_ERROR"] = "NETWORK_ERROR";
22
+ UpupErrorCode2["TIMEOUT"] = "TIMEOUT";
23
+ UpupErrorCode2["STORAGE_ERROR"] = "STORAGE_ERROR";
24
+ UpupErrorCode2["QUOTA_EXCEEDED"] = "QUOTA_EXCEEDED";
25
+ UpupErrorCode2["NO_UPLOAD_TARGET"] = "NO_UPLOAD_TARGET";
26
+ UpupErrorCode2["BAD_REQUEST"] = "BAD_REQUEST";
27
+ UpupErrorCode2["AUTH_REQUIRED"] = "AUTH_REQUIRED";
28
+ UpupErrorCode2["NOT_FOUND"] = "NOT_FOUND";
29
+ return UpupErrorCode2;
30
+ })(UpupErrorCode || {});
31
+ var UpupError = class extends Error {
32
+ constructor(message, code, retryable = false) {
33
+ super(message);
34
+ this.name = "UpupError";
35
+ this.code = code;
36
+ this.retryable = retryable;
37
+ }
38
+ };
39
+ var UpupAuthError = class extends UpupError {
40
+ constructor(message, provider) {
41
+ super(message, "AUTH_PROVIDER_ERROR" /* AUTH_PROVIDER_ERROR */, false);
42
+ this.name = "UpupAuthError";
43
+ this.provider = provider;
44
+ }
45
+ };
46
+ var UpupNetworkError = class extends UpupError {
47
+ constructor(message, status) {
48
+ super(message, "NETWORK_ERROR" /* NETWORK_ERROR */, true);
49
+ this.name = "UpupNetworkError";
50
+ if (status !== void 0) this.status = status;
51
+ }
52
+ };
53
+ var UpupValidationError = class extends UpupError {
54
+ constructor(message, reason, file) {
55
+ super(message, reason, false);
56
+ this.name = "UpupValidationError";
57
+ this.reason = reason;
58
+ this.file = file;
59
+ }
60
+ };
61
+ var UpupQuotaError = class extends UpupError {
62
+ constructor(message, limit, used) {
63
+ super(message, "QUOTA_EXCEEDED" /* QUOTA_EXCEEDED */, false);
64
+ this.name = "UpupQuotaError";
65
+ this.limit = limit;
66
+ this.used = used;
67
+ }
68
+ };
69
+ var UpupStorageError = class extends UpupError {
70
+ constructor(message, provider, operation) {
71
+ super(message, "STORAGE_ERROR" /* STORAGE_ERROR */, false);
72
+ this.name = "UpupStorageError";
73
+ this.provider = provider;
74
+ this.operation = operation;
75
+ }
76
+ };
77
+ var UpupConfigError = class extends UpupError {
78
+ constructor(message, code = "NO_UPLOAD_TARGET" /* NO_UPLOAD_TARGET */) {
79
+ super(message, code, false);
80
+ this.name = "UpupConfigError";
81
+ }
82
+ };
83
+ var MAX_ERROR_BODY_SNIPPET = 200;
84
+ function parseErrorBody(body) {
85
+ if (!body) return { message: "" };
86
+ try {
87
+ const parsed = JSON.parse(body);
88
+ if (parsed && typeof parsed === "object") {
89
+ const {
90
+ code,
91
+ error,
92
+ message: msg
93
+ } = parsed;
94
+ const message = typeof error === "string" ? error : msg;
95
+ if (typeof message === "string" || typeof code === "string") {
96
+ return {
97
+ message: message ?? "",
98
+ ...code !== void 0 ? { code } : {}
99
+ };
100
+ }
101
+ }
102
+ } catch {
103
+ }
104
+ const xmlCode = /<Code>([^<]*)<\/Code>/.exec(body)?.[1];
105
+ const xmlMessage = /<Message>([^<]*)<\/Message>/.exec(body)?.[1];
106
+ if (xmlCode || xmlMessage) {
107
+ return {
108
+ message: xmlMessage ?? "",
109
+ ...xmlCode !== void 0 ? { code: xmlCode } : {}
110
+ };
111
+ }
112
+ return { message: body.slice(0, MAX_ERROR_BODY_SNIPPET) };
113
+ }
114
+ function uploadErrorFromResponse(args) {
115
+ const { status, statusText, body, kind, operation, provider } = args;
116
+ const parsed = parseErrorBody(body);
117
+ const message = parsed.message || `${status} ${statusText}`.trim();
118
+ let err;
119
+ if (kind === "auth") {
120
+ err = new UpupAuthError(message, provider ?? "server");
121
+ } else if (kind === "storage") {
122
+ err = new UpupStorageError(
123
+ message,
124
+ provider ?? "server",
125
+ operation ?? "upload"
126
+ );
127
+ } else {
128
+ err = new UpupNetworkError(message, status);
129
+ }
130
+ if (parsed.code) err.code = parsed.code;
131
+ err.status = status;
132
+ return err;
133
+ }
134
+
135
+ exports.UpupAuthError = UpupAuthError;
136
+ exports.UpupConfigError = UpupConfigError;
137
+ exports.UpupError = UpupError;
138
+ exports.UpupErrorCode = UpupErrorCode;
139
+ exports.UpupNetworkError = UpupNetworkError;
140
+ exports.UpupQuotaError = UpupQuotaError;
141
+ exports.UpupStorageError = UpupStorageError;
142
+ exports.UpupValidationError = UpupValidationError;
143
+ exports.parseErrorBody = parseErrorBody;
144
+ exports.uploadErrorFromResponse = uploadErrorFromResponse;
@@ -0,0 +1,59 @@
1
+ 'use strict';
2
+
3
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
4
+ // src/runtime/browser.ts
5
+ var BrowserRuntime = {
6
+ async computeHash(data) {
7
+ const hashBuffer = await crypto.subtle.digest("SHA-256", data);
8
+ return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
9
+ },
10
+ createImageBitmap: typeof createImageBitmap !== "undefined" ? (blob) => createImageBitmap(blob) : void 0,
11
+ createWorker: typeof Worker !== "undefined" ? () => {
12
+ try {
13
+ return new Worker(
14
+ new URL("./pipeline-worker.js", (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-T2AQHY7V.cjs', document.baseURI).href))),
15
+ {
16
+ type: "module"
17
+ }
18
+ );
19
+ } catch {
20
+ return null;
21
+ }
22
+ } : void 0,
23
+ async upload(url, body, options) {
24
+ return new Promise((resolve, reject) => {
25
+ const xhr = new XMLHttpRequest();
26
+ xhr.upload.addEventListener("progress", (e) => {
27
+ if (e.lengthComputable) options.onProgress(e.loaded, e.total);
28
+ });
29
+ xhr.addEventListener("load", () => {
30
+ const headers = {};
31
+ xhr.getAllResponseHeaders().split("\r\n").forEach((line) => {
32
+ const [key, ...vals] = line.split(": ");
33
+ if (key) headers[key.toLowerCase()] = vals.join(": ");
34
+ });
35
+ resolve({ status: xhr.status, headers, body: xhr.responseText });
36
+ });
37
+ xhr.addEventListener("error", () => {
38
+ reject(new Error("Network error"));
39
+ });
40
+ options.signal.addEventListener("abort", () => {
41
+ xhr.abort();
42
+ });
43
+ xhr.open(options.method, url);
44
+ for (const [k, v] of Object.entries(options.headers)) {
45
+ xhr.setRequestHeader(k, v);
46
+ }
47
+ xhr.send(body);
48
+ });
49
+ },
50
+ async readAsArrayBuffer(file) {
51
+ return file.arrayBuffer();
52
+ },
53
+ createObjectURL: typeof URL !== "undefined" && typeof URL.createObjectURL === "function" ? (blob) => URL.createObjectURL(blob) : void 0,
54
+ revokeObjectURL: typeof URL !== "undefined" && typeof URL.revokeObjectURL === "function" ? (url) => {
55
+ URL.revokeObjectURL(url);
56
+ } : void 0
57
+ };
58
+
59
+ exports.BrowserRuntime = BrowserRuntime;
@@ -0,0 +1,90 @@
1
+ import { UpupError, UpupNetworkError } from './chunk-GE4LIVXP.js';
2
+
3
+ // src/strategies/tus-upload.ts
4
+ var TusUpload = class {
5
+ constructor(options) {
6
+ this.options = options;
7
+ }
8
+ async upload(file, _credentials, options) {
9
+ let tus;
10
+ try {
11
+ tus = await import('tus-js-client');
12
+ } catch {
13
+ throw new UpupError(
14
+ 'Resumable (tus) uploads require the optional dependency "tus-js-client". Install it: npm i tus-js-client',
15
+ "UPLOAD_FAILED" /* UPLOAD_FAILED */
16
+ );
17
+ }
18
+ const fileName = file instanceof File ? file.name : "blob";
19
+ const fileType = file.type || "application/octet-stream";
20
+ return new Promise((resolve, reject) => {
21
+ let settled = false;
22
+ let upload = null;
23
+ const finishReject = (error) => {
24
+ if (settled) return;
25
+ settled = true;
26
+ reject(error);
27
+ };
28
+ const abortUpload = () => {
29
+ upload?.abort().catch((error) => {
30
+ finishReject(
31
+ error instanceof Error ? error : new UpupNetworkError("Tus upload abort failed")
32
+ );
33
+ });
34
+ finishReject(new UpupNetworkError("Upload aborted"));
35
+ };
36
+ if (options.signal.aborted) {
37
+ finishReject(new UpupNetworkError("Upload aborted"));
38
+ return;
39
+ }
40
+ options.signal.addEventListener("abort", abortUpload, {
41
+ once: true
42
+ });
43
+ const uploadOptions = {
44
+ endpoint: this.options.endpoint,
45
+ metadata: {
46
+ filename: fileName,
47
+ filetype: fileType,
48
+ ...this.options.metadata
49
+ },
50
+ onProgress: (bytesUploaded, bytesTotal) => {
51
+ options.onProgress(bytesUploaded, bytesTotal);
52
+ },
53
+ onError: (error) => {
54
+ options.signal.removeEventListener("abort", abortUpload);
55
+ finishReject(
56
+ error instanceof Error ? error : new UpupNetworkError("Tus upload failed")
57
+ );
58
+ },
59
+ onSuccess: () => {
60
+ if (settled) return;
61
+ settled = true;
62
+ options.signal.removeEventListener("abort", abortUpload);
63
+ resolve({
64
+ key: upload?.url ?? fileName,
65
+ publicUrl: upload?.url ?? void 0
66
+ });
67
+ }
68
+ };
69
+ const legacyChunkSize = this.options.chunkSize;
70
+ const chunkSize = this.options.chunkSizeBytes ?? legacyChunkSize;
71
+ if (this.options.headers !== void 0)
72
+ uploadOptions.headers = this.options.headers;
73
+ if (chunkSize !== void 0) uploadOptions.chunkSize = chunkSize;
74
+ if (this.options.retryDelays !== void 0)
75
+ uploadOptions.retryDelays = this.options.retryDelays;
76
+ if (this.options.storeFingerprintForResuming !== void 0) {
77
+ uploadOptions.storeFingerprintForResuming = this.options.storeFingerprintForResuming;
78
+ }
79
+ if (this.options.removeFingerprintOnSuccess !== void 0) {
80
+ uploadOptions.removeFingerprintOnSuccess = this.options.removeFingerprintOnSuccess;
81
+ }
82
+ if (this.options.parallelUploads !== void 0)
83
+ uploadOptions.parallelUploads = this.options.parallelUploads;
84
+ upload = new tus.Upload(file, uploadOptions);
85
+ upload.start();
86
+ });
87
+ }
88
+ };
89
+
90
+ export { TusUpload };
@@ -0,0 +1,374 @@
1
+ 'use strict';
2
+
3
+ // src/theme/presets.ts
4
+ var lightPreset = {
5
+ color: {
6
+ surface: "#FFFFFF",
7
+ surfaceAlt: "#F7F7F8",
8
+ primary: "#0284c7",
9
+ primaryHover: "#0369a1",
10
+ text: "#0B0B0B",
11
+ textMuted: "#6D6D6D",
12
+ border: "#D1D5DB",
13
+ borderActive: "#0ea5e9",
14
+ danger: "#DC2626",
15
+ success: "#16A34A",
16
+ dragBg: "#e0f2fe",
17
+ overlay: "rgba(0, 0, 0, 0.5)"
18
+ },
19
+ radius: {
20
+ sm: "4px",
21
+ md: "8px",
22
+ lg: "12px",
23
+ full: "9999px"
24
+ },
25
+ shadow: {
26
+ sm: "0 1px 2px rgba(0, 0, 0, 0.05)",
27
+ md: "0 4px 6px rgba(0, 0, 0, 0.07)",
28
+ lg: "0 10px 15px rgba(0, 0, 0, 0.1)"
29
+ },
30
+ spacing: {
31
+ xs: "4px",
32
+ sm: "8px",
33
+ md: "12px",
34
+ lg: "16px"
35
+ }
36
+ };
37
+ var darkPreset = {
38
+ color: {
39
+ surface: "#1A1A2E",
40
+ surfaceAlt: "#252540",
41
+ primary: "#38bdf8",
42
+ primaryHover: "#7dd3fc",
43
+ text: "#FFFFFF",
44
+ textMuted: "#D1D5DB",
45
+ border: "#4B5563",
46
+ borderActive: "#38bdf8",
47
+ danger: "#EF4444",
48
+ success: "#22C55E",
49
+ dragBg: "#0b2a3a",
50
+ overlay: "rgba(0, 0, 0, 0.7)"
51
+ },
52
+ radius: {
53
+ sm: "4px",
54
+ md: "8px",
55
+ lg: "12px",
56
+ full: "9999px"
57
+ },
58
+ shadow: {
59
+ sm: "0 1px 2px rgba(0, 0, 0, 0.2)",
60
+ md: "0 4px 6px rgba(0, 0, 0, 0.3)",
61
+ lg: "0 10px 15px rgba(0, 0, 0, 0.4)"
62
+ },
63
+ spacing: {
64
+ xs: "4px",
65
+ sm: "8px",
66
+ md: "12px",
67
+ lg: "16px"
68
+ }
69
+ };
70
+
71
+ // src/theme/resolve-theme.ts
72
+ function deepMerge(base, overrides) {
73
+ if (!overrides) return base;
74
+ const result = { ...base };
75
+ const over = overrides;
76
+ for (const key of Object.keys(over)) {
77
+ const val = over[key];
78
+ if (val !== void 0 && typeof val === "object" && val !== null && !Array.isArray(val) && typeof result[key] === "object" && result[key] !== null) {
79
+ result[key] = deepMerge(
80
+ result[key],
81
+ val
82
+ );
83
+ } else if (val !== void 0) {
84
+ result[key] = val;
85
+ }
86
+ }
87
+ return result;
88
+ }
89
+ function detectSystemMode() {
90
+ if (typeof window !== "undefined" && // matchMedia is absent in jsdom/SSR — keep the optional call. (The
91
+ // no-unnecessary-condition disable that used to sit here became
92
+ // unused when the rule was demoted to off in F-784's warning purge.)
93
+ window.matchMedia?.("(prefers-color-scheme: dark)").matches) {
94
+ return "dark";
95
+ }
96
+ return "light";
97
+ }
98
+ function resolveTheme(config, providerTokens, providerSlots) {
99
+ const mode = config?.mode ?? "light";
100
+ const effectiveMode = mode === "system" ? detectSystemMode() : mode;
101
+ const base = effectiveMode === "dark" ? darkPreset : lightPreset;
102
+ const withProvider = deepMerge(base, providerTokens);
103
+ const final = deepMerge(withProvider, config?.tokens);
104
+ const mergedSlots = deepMerge(
105
+ providerSlots ?? {},
106
+ config?.slots
107
+ );
108
+ return { mode, tokens: final, slots: mergedSlots };
109
+ }
110
+
111
+ // src/theme/vars.ts
112
+ var UPUP_VAR_PREFIX = "--upup-";
113
+ function toKebab(str) {
114
+ return str.replace(/[A-Z]/g, (m) => "-" + m.toLowerCase());
115
+ }
116
+ function tokensToVars(tokens) {
117
+ const vars = {};
118
+ for (const [group, groupTokens] of Object.entries(tokens)) {
119
+ for (const [key, value] of Object.entries(
120
+ groupTokens
121
+ )) {
122
+ const varName = `${UPUP_VAR_PREFIX}${group}-${toKebab(key)}`;
123
+ vars[varName] = value;
124
+ }
125
+ }
126
+ return vars;
127
+ }
128
+ function tokensToVarRefs() {
129
+ const groups = {
130
+ color: [
131
+ "surface",
132
+ "surfaceAlt",
133
+ "primary",
134
+ "primaryHover",
135
+ "text",
136
+ "textMuted",
137
+ "border",
138
+ "borderActive",
139
+ "danger",
140
+ "success",
141
+ "dragBg",
142
+ "overlay"
143
+ ],
144
+ radius: ["sm", "md", "lg", "full"],
145
+ shadow: ["sm", "md", "lg"],
146
+ spacing: ["xs", "sm", "md", "lg"]
147
+ };
148
+ const result = {};
149
+ for (const [group, keys] of Object.entries(groups)) {
150
+ result[group] = {};
151
+ for (const key of keys) {
152
+ result[group][key] = `var(${UPUP_VAR_PREFIX}${group}-${toKebab(key)})`;
153
+ }
154
+ }
155
+ return result;
156
+ }
157
+
158
+ // src/theme/slots.ts
159
+ var SLOT_TO_FLAT = {
160
+ uploader: {
161
+ root: "containerFull",
162
+ container: "containerFull"
163
+ },
164
+ dropZone: {
165
+ root: "containerFull"
166
+ },
167
+ sourceSelector: {
168
+ root: "containerFull",
169
+ sourceList: "sourceButtonList",
170
+ sourceButton: "sourceButton",
171
+ sourceButtonIcon: "sourceButtonIcon",
172
+ sourceButtonText: "sourceButtonText",
173
+ browseText: "sourceButtonText",
174
+ dragText: "sourceButtonText"
175
+ },
176
+ sourceView: {
177
+ root: "sourceView",
178
+ header: "sourceViewHeader",
179
+ cancelButton: "sourceViewCancelButton"
180
+ },
181
+ fileList: {
182
+ root: "fileListContainer",
183
+ header: "containerHeader",
184
+ cancelButton: "containerCancelButton",
185
+ addMoreButton: "containerAddMoreButton",
186
+ fileCount: "containerHeader",
187
+ body: [
188
+ "fileListContainerInnerSingle",
189
+ "fileListContainerInnerMultiple"
190
+ ],
191
+ footer: "fileListFooter",
192
+ uploadButton: "uploadButton",
193
+ doneButton: "uploadDoneButton"
194
+ },
195
+ filePreview: {
196
+ root: ["fileItemSingle", "fileItemMultiple"],
197
+ thumbnail: ["fileThumbnailSingle", "fileThumbnailMultiple"],
198
+ icon: "fileIcon",
199
+ info: "fileInfo",
200
+ name: "fileName",
201
+ size: "fileSize",
202
+ previewButton: "filePreviewButton",
203
+ deleteButton: "fileDeleteButton"
204
+ },
205
+ progressBar: {
206
+ root: "progressBarContainer",
207
+ track: "progressBar",
208
+ fill: "progressBarInner",
209
+ text: "progressBarText"
210
+ },
211
+ notifier: {
212
+ root: "containerFull",
213
+ message: "containerFull"
214
+ },
215
+ urlUploader: {
216
+ input: "urlInput",
217
+ fetchButton: "urlFetchButton"
218
+ },
219
+ cameraUploader: {
220
+ previewContainer: "cameraPreviewContainer",
221
+ deleteButton: "cameraDeleteButton",
222
+ captureButton: "cameraCaptureButton",
223
+ rotateButton: "cameraRotateButton",
224
+ mirrorButton: "cameraRotateButton",
225
+ addButton: "cameraAddButton",
226
+ modeToggle: "cameraRotateButton",
227
+ videoRecordButton: "cameraCaptureButton",
228
+ videoStopButton: "cameraCaptureButton",
229
+ videoPreview: "cameraPreviewContainer",
230
+ videoAddButton: "cameraAddButton",
231
+ videoDeleteButton: "cameraDeleteButton"
232
+ },
233
+ audioUploader: {
234
+ root: "containerFull",
235
+ playbackContainer: "cameraPreviewContainer",
236
+ deleteButton: "cameraDeleteButton",
237
+ addButton: "cameraAddButton"
238
+ },
239
+ screenCaptureUploader: {
240
+ root: "containerFull",
241
+ preview: "cameraPreviewContainer",
242
+ addButton: "cameraAddButton",
243
+ deleteButton: "cameraDeleteButton"
244
+ },
245
+ driveBrowser: {
246
+ root: "containerFull",
247
+ header: "driveHeader",
248
+ searchContainer: "driveSearchContainer",
249
+ searchInput: "driveSearchInput",
250
+ body: "driveBody",
251
+ footer: "driveFooter",
252
+ itemDefault: "driveItemContainerDefault",
253
+ itemSelected: "driveItemContainerSelected",
254
+ itemInner: "driveItemContainerInner",
255
+ itemInnerText: "driveItemInnerText",
256
+ addFilesButton: "driveAddFilesButton",
257
+ cancelFilesButton: "driveCancelFilesButton",
258
+ logoutButton: "driveLogoutButton",
259
+ loading: "driveLoading"
260
+ },
261
+ driveAuthFallback: {
262
+ root: "containerFull"
263
+ },
264
+ filePreviewPortal: {
265
+ root: "filePreviewPortal"
266
+ },
267
+ imageEditor: {
268
+ root: "containerFull",
269
+ modal: "containerFull"
270
+ }
271
+ };
272
+ function flattenSlotsToClassNames(slots) {
273
+ if (!slots) return {};
274
+ const out = {};
275
+ for (const componentKey of Object.keys(slots)) {
276
+ const component = slots[componentKey];
277
+ if (!component) continue;
278
+ const mapping = SLOT_TO_FLAT[componentKey];
279
+ if (!mapping) continue;
280
+ for (const slotName of Object.keys(component)) {
281
+ const value = component[slotName];
282
+ if (typeof value !== "string" || value.length === 0) continue;
283
+ const target = mapping[slotName];
284
+ if (!target) continue;
285
+ const keys = Array.isArray(target) ? target : [target];
286
+ for (const key of keys) {
287
+ out[key] = out[key] ? `${out[key]} ${value}` : value;
288
+ }
289
+ }
290
+ }
291
+ return out;
292
+ }
293
+
294
+ // src/theme/theme-store.ts
295
+ function themeConfigEqual(a, b) {
296
+ if (a === b) return true;
297
+ return a?.mode === b?.mode && JSON.stringify(a?.tokens) === JSON.stringify(b?.tokens) && JSON.stringify(a?.slots) === JSON.stringify(b?.slots);
298
+ }
299
+ var ThemeStore = class {
300
+ constructor(config) {
301
+ this.listeners = /* @__PURE__ */ new Set();
302
+ this.systemMode = "light";
303
+ this.mediaCleanup = null;
304
+ this.subscribe = (listener) => {
305
+ this.listeners.add(listener);
306
+ return () => this.listeners.delete(listener);
307
+ };
308
+ this.getSnapshot = () => this.state;
309
+ this.config = config;
310
+ this.state = this.compute();
311
+ }
312
+ /** Start the `system` matchMedia subscription (no-op for explicit modes / SSR). */
313
+ init() {
314
+ const requested = this.config?.mode ?? "light";
315
+ if (requested !== "system") return;
316
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function")
317
+ return;
318
+ const media = window.matchMedia("(prefers-color-scheme: dark)");
319
+ const update = () => {
320
+ this.systemMode = media.matches ? "dark" : "light";
321
+ this.recompute();
322
+ };
323
+ update();
324
+ media.addEventListener("change", update);
325
+ this.mediaCleanup = () => {
326
+ media.removeEventListener("change", update);
327
+ };
328
+ }
329
+ /** Re-resolve when the host's theme config prop changes. */
330
+ setThemeConfig(config) {
331
+ if (themeConfigEqual(this.config, config)) return;
332
+ this.config = config;
333
+ this.recompute();
334
+ }
335
+ compute() {
336
+ const requested = this.config?.mode ?? "light";
337
+ const effective = requested === "system" ? this.systemMode : requested;
338
+ const resolved = resolveTheme({
339
+ ...this.config ?? {},
340
+ mode: effective
341
+ });
342
+ return {
343
+ themeMode: effective,
344
+ isDark: effective === "dark",
345
+ tokens: resolved.tokens,
346
+ resolved,
347
+ slotOverrides: flattenSlotsToClassNames(resolved.slots),
348
+ slots: resolved.slots
349
+ };
350
+ }
351
+ recompute() {
352
+ this.state = this.compute();
353
+ this.notify();
354
+ }
355
+ notify() {
356
+ this.listeners.forEach((fn) => {
357
+ fn();
358
+ });
359
+ }
360
+ destroy() {
361
+ this.mediaCleanup?.();
362
+ this.mediaCleanup = null;
363
+ this.listeners.clear();
364
+ }
365
+ };
366
+
367
+ exports.ThemeStore = ThemeStore;
368
+ exports.UPUP_VAR_PREFIX = UPUP_VAR_PREFIX;
369
+ exports.darkPreset = darkPreset;
370
+ exports.flattenSlotsToClassNames = flattenSlotsToClassNames;
371
+ exports.lightPreset = lightPreset;
372
+ exports.resolveTheme = resolveTheme;
373
+ exports.tokensToVarRefs = tokensToVarRefs;
374
+ exports.tokensToVars = tokensToVars;