dexie-cloud-addon 4.2.4 → 4.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 (35) hide show
  1. package/TODO-SOCIALAUTH.md +545 -0
  2. package/dexie-cloud-import.json +2 -1
  3. package/dist/modern/DexieCloudAPI.d.ts +4 -0
  4. package/dist/modern/DexieCloudOptions.d.ts +20 -0
  5. package/dist/modern/authentication/exchangeOAuthCode.d.ts +23 -0
  6. package/dist/modern/authentication/fetchAuthProviders.d.ts +14 -0
  7. package/dist/modern/authentication/handleOAuthCallback.d.ts +57 -0
  8. package/dist/modern/authentication/interactWithUser.d.ts +19 -0
  9. package/dist/modern/authentication/oauthLogin.d.ts +37 -0
  10. package/dist/modern/default-ui/AuthProviderButton.d.ts +21 -0
  11. package/dist/modern/default-ui/LoginDialog.d.ts +5 -2
  12. package/dist/modern/default-ui/ProviderSelectionDialog.d.ts +7 -0
  13. package/dist/modern/dexie-cloud-addon.js +719 -169
  14. package/dist/modern/dexie-cloud-addon.js.map +1 -1
  15. package/dist/modern/dexie-cloud-addon.min.js +1 -1
  16. package/dist/modern/dexie-cloud-addon.min.js.gz +0 -0
  17. package/dist/modern/dexie-cloud-addon.min.js.map +1 -1
  18. package/dist/modern/errors/OAuthError.d.ts +10 -0
  19. package/dist/modern/service-worker.js +720 -170
  20. package/dist/modern/service-worker.js.map +1 -1
  21. package/dist/modern/service-worker.min.js +1 -1
  22. package/dist/modern/service-worker.min.js.map +1 -1
  23. package/dist/modern/types/DXCUserInteraction.d.ts +24 -1
  24. package/dist/umd/dexie-cloud-addon.js +2181 -2444
  25. package/dist/umd/dexie-cloud-addon.js.gz +0 -0
  26. package/dist/umd/dexie-cloud-addon.js.map +1 -1
  27. package/dist/umd/dexie-cloud-addon.min.js +1 -1
  28. package/dist/umd/dexie-cloud-addon.min.js.gz +0 -0
  29. package/dist/umd/dexie-cloud-addon.min.js.map +1 -1
  30. package/dist/umd/service-worker.js +2029 -2292
  31. package/dist/umd/service-worker.js.map +1 -1
  32. package/dist/umd/service-worker.min.js +1 -1
  33. package/dist/umd/service-worker.min.js.map +1 -1
  34. package/oauth_flow.md +299 -0
  35. package/package.json +10 -7
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * ==========================================================================
10
10
  *
11
- * Version 4.2.4, Tue Dec 09 2025
11
+ * Version 4.3.0, Tue Jan 20 2026
12
12
  *
13
13
  * https://dexie.org
14
14
  *
@@ -39,7 +39,7 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
39
39
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
40
40
  PERFORMANCE OF THIS SOFTWARE.
41
41
  ***************************************************************************** */
42
- /* global Reflect, Promise */
42
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
43
43
 
44
44
 
45
45
  function __rest(s, e) {
@@ -83,8 +83,9 @@ function __await(v) {
83
83
  function __asyncGenerator(thisArg, _arguments, generator) {
84
84
  if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
85
85
  var g = generator.apply(thisArg, _arguments || []), i, q = [];
86
- return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
87
- function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
86
+ return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
87
+ function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
88
+ function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
88
89
  function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
89
90
  function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
90
91
  function fulfill(value) { resume("next", value); }
@@ -98,7 +99,12 @@ function __asyncValues(o) {
98
99
  return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
99
100
  function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
100
101
  function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
101
- }
102
+ }
103
+
104
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
105
+ var e = new Error(message);
106
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
107
+ };
102
108
 
103
109
  const UNAUTHORIZED_USER = {
104
110
  userId: "unauthorized",
@@ -475,10 +481,17 @@ function removeRedundantUpdateOps(muts) {
475
481
  return true;
476
482
  if (mut.keys.length !== 1 || mut.changeSpecs.length !== 1)
477
483
  return true;
484
+ // Check if this has PropModifications - if so, skip optimization
485
+ const changeSpecs = mut.changeSpecs[0];
486
+ if (Object.values(changeSpecs).some(v => typeof v === "object" && v && "@@propmod" in v)) {
487
+ return true; // Cannot optimize if any PropModification is present
488
+ }
478
489
  // Keep track of properties that aren't overlapped by later transactions
479
490
  const unoverlappedProps = new Set(Object.keys(mut.changeSpecs[0]));
480
491
  const strKey = '' + mut.keys[0];
481
492
  const keyCoverage = updateCoverage.get(strKey);
493
+ if (!keyCoverage)
494
+ return true; // No coverage info - cannot optimize
482
495
  for (let i = keyCoverage.length - 1; i >= 0; --i) {
483
496
  const { txid, updateSpec } = keyCoverage[i];
484
497
  if (txid === mut.txid)
@@ -532,6 +545,15 @@ function randomString$1(bytes) {
532
545
  }
533
546
  }
534
547
 
548
+ /** Type guard to check if a message is an OAuthResultMessage */
549
+ function isOAuthResultMessage(msg) {
550
+ return (typeof msg === 'object' &&
551
+ msg !== null &&
552
+ msg.type === 'dexie:oauthResult' &&
553
+ typeof msg.provider === 'string' &&
554
+ typeof msg.state === 'string');
555
+ }
556
+
535
557
  function assert(b) {
536
558
  if (!b)
537
559
  throw new Error('Assertion Failed');
@@ -711,13 +733,12 @@ function applyOperations(target, ops) {
711
733
  function subtractChanges(target, // Server change set
712
734
  changesToSubtract // additional mutations on client during syncWithServer()
713
735
  ) {
714
- var _a, _b, _c;
715
736
  for (const [table, mutationSet] of Object.entries(changesToSubtract)) {
716
737
  for (const [key, mut] of Object.entries(mutationSet)) {
717
738
  switch (mut.type) {
718
739
  case 'ups':
719
740
  {
720
- const targetMut = (_a = target[table]) === null || _a === void 0 ? void 0 : _a[key];
741
+ const targetMut = target[table]?.[key];
721
742
  if (targetMut) {
722
743
  switch (targetMut.type) {
723
744
  case 'ups':
@@ -735,10 +756,10 @@ changesToSubtract // additional mutations on client during syncWithServer()
735
756
  }
736
757
  break;
737
758
  case 'del':
738
- (_b = target[table]) === null || _b === void 0 ? true : delete _b[key];
759
+ delete target[table]?.[key];
739
760
  break;
740
761
  case 'upd': {
741
- const targetMut = (_c = target[table]) === null || _c === void 0 ? void 0 : _c[key];
762
+ const targetMut = target[table]?.[key];
742
763
  if (targetMut) {
743
764
  switch (targetMut.type) {
744
765
  case 'ups':
@@ -771,17 +792,14 @@ changesToSubtract // additional mutations on client during syncWithServer()
771
792
  * @param inSet
772
793
  * @returns DBOperationsSet representing inSet
773
794
  */
774
- function toDBOperationSet(inSet, txid = "") {
775
- // Fictive transaction:
776
- if (!txid)
777
- txid = randomString(16);
795
+ function toDBOperationSet(inSet, txid) {
778
796
  // Convert data into a temporary map to collect mutations of same table and type
779
797
  const map = {};
780
798
  for (const [table, ops] of Object.entries(inSet)) {
781
799
  for (const [key, op] of Object.entries(ops)) {
782
800
  const mapEntry = map[table] || (map[table] = {});
783
801
  const ops = mapEntry[op.type] || (mapEntry[op.type] = []);
784
- ops.push(Object.assign({ key }, op)); // DBKeyMutation doesn't contain key, so we need to bring it in.
802
+ ops.push({ key, ...op }); // DBKeyMutation doesn't contain key, so we need to bring it in.
785
803
  }
786
804
  }
787
805
  // Start computing the resulting format:
@@ -959,142 +977,111 @@ function decodeYMessage(a) {
959
977
  }
960
978
 
961
979
  async function asyncIterablePipeline(source, ...stages) {
962
- var _a, e_1, _b, _c;
963
980
  // Chain generators by sending outdata from one to another
964
981
  let result = source(); // Start with the source generator
965
982
  for (let i = 0; i < stages.length; i++) {
966
983
  result = stages[i](result); // Pass on the result to next generator
967
984
  }
968
- try {
969
- // Start running the machine. If the last stage is a sink, it will consume the data and never emit anything
970
- // to us here...
971
- for (var _d = true, result_1 = __asyncValues(result), result_1_1; result_1_1 = await result_1.next(), _a = result_1_1.done, !_a; _d = true) {
972
- _c = result_1_1.value;
973
- _d = false;
974
- const chunk = _c;
975
- }
976
- }
977
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
978
- finally {
979
- try {
980
- if (!_d && !_a && (_b = result_1.return)) await _b.call(result_1);
981
- }
982
- finally { if (e_1) throw e_1.error; }
983
- }
984
- }
985
-
986
- function consumeChunkedBinaryStream(source) {
987
- return __asyncGenerator(this, arguments, function* consumeChunkedBinaryStream_1() {
988
- var _a, e_1, _b, _c;
989
- let state = 0;
990
- let sizeBuf = new Uint8Array(4);
991
- let sizeBufPos = 0;
992
- let bufs = [];
993
- let len = 0;
994
- try {
995
- for (var _d = true, source_1 = __asyncValues(source), source_1_1; source_1_1 = yield __await(source_1.next()), _a = source_1_1.done, !_a; _d = true) {
996
- _c = source_1_1.value;
997
- _d = false;
998
- const chunk = _c;
999
- const dw = new DataView(chunk.buffer, chunk.byteOffset, chunk.byteLength);
1000
- let pos = 0;
1001
- while (pos < chunk.byteLength) {
1002
- switch (state) {
1003
- case 0:
1004
- // Beginning of a size header
1005
- if (pos + 4 > chunk.byteLength) {
1006
- for (const b of chunk.slice(pos)) {
1007
- if (sizeBufPos === 4)
1008
- break;
1009
- sizeBuf[sizeBufPos++] = b;
1010
- ++pos;
1011
- }
1012
- if (sizeBufPos < 4) {
1013
- // Need more bytes in order to read length.
1014
- // Will go out from while loop as well because pos is defenitely = chunk.byteLength here.
1015
- break;
1016
- }
1017
- }
1018
- else if (sizeBufPos > 0 && sizeBufPos < 4) {
1019
- for (const b of chunk.slice(pos, pos + 4 - sizeBufPos)) {
1020
- sizeBuf[sizeBufPos++] = b;
1021
- ++pos;
1022
- }
1023
- }
1024
- // Intentional fall-through...
1025
- case 1:
1026
- len =
1027
- sizeBufPos === 4
1028
- ? new DataView(sizeBuf.buffer, 0, 4).getUint32(0, false)
1029
- : dw.getUint32(pos, false);
1030
- if (sizeBufPos)
1031
- sizeBufPos = 0; // in this case pos is already forwarded
1032
- else
1033
- pos += 4; // else pos is not yet forwarded - that's why we do it now
1034
- // Intentional fall-through...
1035
- case 2:
1036
- // Eat the chunk
1037
- if (pos >= chunk.byteLength) {
1038
- state = 2;
985
+ // Start running the machine. If the last stage is a sink, it will consume the data and never emit anything
986
+ // to us here...
987
+ for await (const chunk of result) { }
988
+ }
989
+
990
+ async function* consumeChunkedBinaryStream(source) {
991
+ let state = 0;
992
+ let sizeBuf = new Uint8Array(4);
993
+ let sizeBufPos = 0;
994
+ let bufs = [];
995
+ let len = 0;
996
+ for await (const chunk of source) {
997
+ const dw = new DataView(chunk.buffer, chunk.byteOffset, chunk.byteLength);
998
+ let pos = 0;
999
+ while (pos < chunk.byteLength) {
1000
+ switch (state) {
1001
+ case 0:
1002
+ // Beginning of a size header
1003
+ if (pos + 4 > chunk.byteLength) {
1004
+ for (const b of chunk.slice(pos)) {
1005
+ if (sizeBufPos === 4)
1039
1006
  break;
1040
- }
1041
- if (pos + len > chunk.byteLength) {
1042
- bufs.push(chunk.slice(pos));
1043
- len -= (chunk.byteLength - pos);
1044
- state = 2;
1045
- pos = chunk.byteLength; // will break while loop.
1046
- }
1047
- else {
1048
- if (bufs.length > 0) {
1049
- const concats = new Uint8Array(bufs.reduce((p, c) => p + c.byteLength, len));
1050
- let p = 0;
1051
- for (const buf of bufs) {
1052
- concats.set(buf, p);
1053
- p += buf.byteLength;
1054
- }
1055
- concats.set(chunk.slice(pos, pos + len), p);
1056
- bufs = [];
1057
- yield yield __await(concats);
1058
- }
1059
- else {
1060
- yield yield __await(chunk.slice(pos, pos + len));
1061
- }
1062
- pos += len;
1063
- state = 0;
1064
- }
1007
+ sizeBuf[sizeBufPos++] = b;
1008
+ ++pos;
1009
+ }
1010
+ if (sizeBufPos < 4) {
1011
+ // Need more bytes in order to read length.
1012
+ // Will go out from while loop as well because pos is defenitely = chunk.byteLength here.
1065
1013
  break;
1014
+ }
1066
1015
  }
1067
- }
1068
- }
1069
- }
1070
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
1071
- finally {
1072
- try {
1073
- if (!_d && !_a && (_b = source_1.return)) yield __await(_b.call(source_1));
1016
+ else if (sizeBufPos > 0 && sizeBufPos < 4) {
1017
+ for (const b of chunk.slice(pos, pos + 4 - sizeBufPos)) {
1018
+ sizeBuf[sizeBufPos++] = b;
1019
+ ++pos;
1020
+ }
1021
+ }
1022
+ // Intentional fall-through...
1023
+ case 1:
1024
+ len =
1025
+ sizeBufPos === 4
1026
+ ? new DataView(sizeBuf.buffer, 0, 4).getUint32(0, false)
1027
+ : dw.getUint32(pos, false);
1028
+ if (sizeBufPos)
1029
+ sizeBufPos = 0; // in this case pos is already forwarded
1030
+ else
1031
+ pos += 4; // else pos is not yet forwarded - that's why we do it now
1032
+ // Intentional fall-through...
1033
+ case 2:
1034
+ // Eat the chunk
1035
+ if (pos >= chunk.byteLength) {
1036
+ state = 2;
1037
+ break;
1038
+ }
1039
+ if (pos + len > chunk.byteLength) {
1040
+ bufs.push(chunk.slice(pos));
1041
+ len -= (chunk.byteLength - pos);
1042
+ state = 2;
1043
+ pos = chunk.byteLength; // will break while loop.
1044
+ }
1045
+ else {
1046
+ if (bufs.length > 0) {
1047
+ const concats = new Uint8Array(bufs.reduce((p, c) => p + c.byteLength, len));
1048
+ let p = 0;
1049
+ for (const buf of bufs) {
1050
+ concats.set(buf, p);
1051
+ p += buf.byteLength;
1052
+ }
1053
+ concats.set(chunk.slice(pos, pos + len), p);
1054
+ bufs = [];
1055
+ yield concats;
1056
+ }
1057
+ else {
1058
+ yield chunk.slice(pos, pos + len);
1059
+ }
1060
+ pos += len;
1061
+ state = 0;
1062
+ }
1063
+ break;
1074
1064
  }
1075
- finally { if (e_1) throw e_1.error; }
1076
1065
  }
1077
- });
1066
+ }
1078
1067
  }
1079
1068
 
1080
1069
  function getFetchResponseBodyGenerator(res) {
1081
- return function () {
1082
- return __asyncGenerator(this, arguments, function* () {
1083
- if (!res.body)
1084
- throw new Error("Response body is not readable");
1085
- const reader = res.body.getReader();
1086
- try {
1087
- while (true) {
1088
- const { done, value } = yield __await(reader.read());
1089
- if (done)
1090
- return yield __await(void 0);
1091
- yield yield __await(value);
1092
- }
1093
- }
1094
- finally {
1095
- reader.releaseLock();
1070
+ return async function* () {
1071
+ if (!res.body)
1072
+ throw new Error("Response body is not readable");
1073
+ const reader = res.body.getReader();
1074
+ try {
1075
+ while (true) {
1076
+ const { done, value } = await reader.read();
1077
+ if (done)
1078
+ return;
1079
+ yield value;
1096
1080
  }
1097
- });
1081
+ }
1082
+ finally {
1083
+ reader.releaseLock();
1084
+ }
1098
1085
  };
1099
1086
  }
1100
1087
 
@@ -1301,6 +1288,43 @@ function confirmLogout(userInteraction, currentUserId, numUnsyncedChanges) {
1301
1288
  .catch(() => false);
1302
1289
  });
1303
1290
  }
1291
+ /**
1292
+ * Prompts the user to select an authentication method (OAuth provider or OTP).
1293
+ *
1294
+ * @param userInteraction - The user interaction BehaviorSubject
1295
+ * @param providers - Available OAuth providers
1296
+ * @param otpEnabled - Whether OTP is available
1297
+ * @param title - Dialog title
1298
+ * @param alerts - Optional alerts to display
1299
+ * @returns Promise resolving to the user's selection
1300
+ */
1301
+ function promptForProvider(userInteraction, providers, otpEnabled, title = 'Choose login method', alerts = []) {
1302
+ return new Promise((resolve, reject) => {
1303
+ const interactionProps = {
1304
+ type: 'provider-selection',
1305
+ title,
1306
+ alerts,
1307
+ providers,
1308
+ otpEnabled,
1309
+ fields: {},
1310
+ submitLabel: undefined,
1311
+ cancelLabel: 'Cancel',
1312
+ onSelectProvider: (providerName) => {
1313
+ userInteraction.next(undefined);
1314
+ resolve({ type: 'provider', provider: providerName });
1315
+ },
1316
+ onSelectOtp: () => {
1317
+ userInteraction.next(undefined);
1318
+ resolve({ type: 'otp' });
1319
+ },
1320
+ onCancel: () => {
1321
+ userInteraction.next(undefined);
1322
+ reject(new Dexie.AbortError('User cancelled'));
1323
+ },
1324
+ };
1325
+ userInteraction.next(interactionProps);
1326
+ });
1327
+ }
1304
1328
 
1305
1329
  function loadAccessToken(db) {
1306
1330
  return __awaiter(this, void 0, void 0, function* () {
@@ -2071,7 +2095,8 @@ const defs = Object.assign(Object.assign(Object.assign(Object.assign({}, undefin
2071
2095
  return Object.assign({ $t: 'PropModification' }, propModification['@@propmod']);
2072
2096
  },
2073
2097
  revive: (_a) => {
2074
- var propModSpec = __rest(_a, ["$t"]) // keep the rest
2098
+ var { $t } = _a, // strip '$t'
2099
+ propModSpec = __rest(_a, ["$t"]) // keep the rest
2075
2100
  ;
2076
2101
  return new PropModification(propModSpec);
2077
2102
  },
@@ -3563,15 +3588,313 @@ function _logout(db_1) {
3563
3588
  });
3564
3589
  }
3565
3590
 
3591
+ /** User-friendly messages for OAuth error codes */
3592
+ const ERROR_MESSAGES = {
3593
+ popup_blocked: 'The login popup was blocked by your browser. Please allow popups for this site and try again.',
3594
+ popup_closed: 'The login popup was closed before completing authentication.',
3595
+ access_denied: 'Access was denied by the authentication provider.',
3596
+ invalid_state: 'The authentication response could not be verified. Please try again.',
3597
+ email_not_verified: 'Your email address must be verified before you can log in.',
3598
+ expired_code: 'The authentication code has expired. Please try again.',
3599
+ provider_error: 'An error occurred with the authentication provider.',
3600
+ network_error: 'A network error occurred during authentication. Please check your connection and try again.',
3601
+ };
3602
+ /** Error class for OAuth-specific errors */
3603
+ class OAuthError extends Error {
3604
+ constructor(code, provider, customMessage) {
3605
+ super(customMessage || ERROR_MESSAGES[code]);
3606
+ this.name = 'OAuthError';
3607
+ this.code = code;
3608
+ this.provider = provider;
3609
+ }
3610
+ /** Get user-friendly message for this error */
3611
+ get userMessage() {
3612
+ return ERROR_MESSAGES[this.code] || this.message;
3613
+ }
3614
+ }
3615
+
3616
+ /**
3617
+ * Exchanges a Dexie Cloud authorization code for access and refresh tokens.
3618
+ *
3619
+ * This is called after the OAuth callback delivers the authorization code
3620
+ * via postMessage (popup flow) or redirect.
3621
+ *
3622
+ * @param options - Exchange options
3623
+ * @returns Promise resolving to TokenFinalResponse
3624
+ * @throws OAuthError or TokenErrorResponseError on failure
3625
+ */
3626
+ function exchangeOAuthCode(options) {
3627
+ return __awaiter(this, void 0, void 0, function* () {
3628
+ const { databaseUrl, code, publicKey, scopes = ['ACCESS_DB'] } = options;
3629
+ const tokenRequest = {
3630
+ grant_type: 'authorization_code',
3631
+ code,
3632
+ public_key: publicKey,
3633
+ scopes,
3634
+ };
3635
+ try {
3636
+ const res = yield fetch(`${databaseUrl}/token`, {
3637
+ method: 'POST',
3638
+ headers: { 'Content-Type': 'application/json' },
3639
+ body: JSON.stringify(tokenRequest),
3640
+ mode: 'cors',
3641
+ });
3642
+ if (!res.ok) {
3643
+ if (res.status === 400 || res.status === 401) {
3644
+ // Try to parse error response
3645
+ try {
3646
+ const errorResponse = yield res.json();
3647
+ if (errorResponse.type === 'error') {
3648
+ // Check for specific error codes
3649
+ if (errorResponse.messageCode === 'INVALID_OTP') {
3650
+ // In the context of OAuth, this likely means expired code
3651
+ throw new OAuthError('expired_code', undefined, errorResponse.message);
3652
+ }
3653
+ throw new TokenErrorResponseError(errorResponse);
3654
+ }
3655
+ }
3656
+ catch (e) {
3657
+ if (e instanceof OAuthError || e instanceof TokenErrorResponseError) {
3658
+ throw e;
3659
+ }
3660
+ // Fall through to generic error
3661
+ }
3662
+ }
3663
+ const errorText = yield res.text().catch(() => res.statusText);
3664
+ throw new OAuthError('provider_error', undefined, `Token exchange failed: ${res.status} ${errorText}`);
3665
+ }
3666
+ const response = yield res.json();
3667
+ if (response.type === 'error') {
3668
+ throw new TokenErrorResponseError(response);
3669
+ }
3670
+ if (response.type !== 'tokens') {
3671
+ throw new OAuthError('provider_error', undefined, `Unexpected response type: ${response.type}`);
3672
+ }
3673
+ return response;
3674
+ }
3675
+ catch (error) {
3676
+ if (error instanceof OAuthError || error instanceof TokenErrorResponseError) {
3677
+ throw error;
3678
+ }
3679
+ if (error instanceof TypeError) {
3680
+ // Network error
3681
+ throw new OAuthError('network_error');
3682
+ }
3683
+ throw error;
3684
+ }
3685
+ });
3686
+ }
3687
+
3688
+ /** Default response when OAuth is disabled or unavailable */
3689
+ const OTP_ONLY_RESPONSE = {
3690
+ providers: [],
3691
+ otpEnabled: true,
3692
+ };
3693
+ /**
3694
+ * Fetches available authentication providers from the Dexie Cloud server.
3695
+ *
3696
+ * @param databaseUrl - The Dexie Cloud database URL
3697
+ * @param socialAuthEnabled - Whether social auth is enabled in client config (default: true)
3698
+ * @returns Promise resolving to AuthProvidersResponse
3699
+ *
3700
+ * Handles failures gracefully:
3701
+ * - 404 → Returns OTP-only (old server version)
3702
+ * - Network error → Returns OTP-only
3703
+ * - socialAuthEnabled: false → Returns OTP-only without fetching
3704
+ */
3705
+ function fetchAuthProviders(databaseUrl_1) {
3706
+ return __awaiter(this, arguments, void 0, function* (databaseUrl, socialAuthEnabled = true) {
3707
+ // If social auth is disabled, return OTP-only without fetching
3708
+ if (!socialAuthEnabled) {
3709
+ return OTP_ONLY_RESPONSE;
3710
+ }
3711
+ try {
3712
+ const res = yield fetch(`${databaseUrl}/auth-providers`, {
3713
+ method: 'GET',
3714
+ headers: { 'Accept': 'application/json' },
3715
+ mode: 'cors',
3716
+ });
3717
+ if (res.status === 404) {
3718
+ // Old server version without OAuth support
3719
+ console.debug('[dexie-cloud] Server does not support /auth-providers endpoint. Using OTP-only authentication.');
3720
+ return OTP_ONLY_RESPONSE;
3721
+ }
3722
+ if (!res.ok) {
3723
+ console.warn(`[dexie-cloud] Failed to fetch auth providers: ${res.status} ${res.statusText}`);
3724
+ return OTP_ONLY_RESPONSE;
3725
+ }
3726
+ return yield res.json();
3727
+ }
3728
+ catch (error) {
3729
+ // Network error or other failure - fall back to OTP
3730
+ console.debug('[dexie-cloud] Could not fetch auth providers, falling back to OTP:', error);
3731
+ return OTP_ONLY_RESPONSE;
3732
+ }
3733
+ });
3734
+ }
3735
+
3736
+ /** Generate a random state string for CSRF protection */
3737
+ function generateState() {
3738
+ const array = new Uint8Array(32);
3739
+ crypto.getRandomValues(array);
3740
+ return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');
3741
+ }
3742
+ /** Build the OAuth login URL */
3743
+ function buildOAuthLoginUrl(options, state) {
3744
+ const url = new URL(`${options.databaseUrl}/oauth/login/${options.provider}`);
3745
+ url.searchParams.set('state', state);
3746
+ // Set the redirect URI for postMessage or custom scheme
3747
+ const redirectUri = options.redirectUri ||
3748
+ (typeof window !== 'undefined' ? window.location.origin : '');
3749
+ if (redirectUri) {
3750
+ url.searchParams.set('redirect_uri', redirectUri);
3751
+ }
3752
+ return url.toString();
3753
+ }
3754
+ /** Calculate centered popup position */
3755
+ function getPopupPosition(width, height) {
3756
+ var _a, _b, _c, _d, _e, _f;
3757
+ const screenLeft = (_a = window.screenLeft) !== null && _a !== void 0 ? _a : window.screenX;
3758
+ const screenTop = (_b = window.screenTop) !== null && _b !== void 0 ? _b : window.screenY;
3759
+ const screenWidth = (_d = (_c = window.innerWidth) !== null && _c !== void 0 ? _c : document.documentElement.clientWidth) !== null && _d !== void 0 ? _d : screen.width;
3760
+ const screenHeight = (_f = (_e = window.innerHeight) !== null && _e !== void 0 ? _e : document.documentElement.clientHeight) !== null && _f !== void 0 ? _f : screen.height;
3761
+ const left = screenLeft + (screenWidth - width) / 2;
3762
+ const top = screenTop + (screenHeight - height) / 2;
3763
+ return { left: Math.max(0, left), top: Math.max(0, top) };
3764
+ }
3765
+ /**
3766
+ * Initiates OAuth login flow using a popup window.
3767
+ *
3768
+ * Opens a popup to the OAuth provider, listens for postMessage with the result,
3769
+ * and returns the Dexie Cloud authorization code.
3770
+ *
3771
+ * @param options - OAuth login options
3772
+ * @returns Promise resolving to OAuthLoginResult
3773
+ * @throws OAuthError on failure
3774
+ */
3775
+ function oauthLogin(options) {
3776
+ return __awaiter(this, void 0, void 0, function* () {
3777
+ const { databaseUrl, provider, usePopup = true } = options;
3778
+ if (!usePopup) {
3779
+ // For redirect flows, we can't return a promise - the page will navigate away
3780
+ throw new Error('Non-popup OAuth flow requires handleOAuthCallback after redirect');
3781
+ }
3782
+ const state = generateState();
3783
+ const loginUrl = buildOAuthLoginUrl(options, state);
3784
+ // Calculate popup dimensions and position
3785
+ const width = 500;
3786
+ const height = 600;
3787
+ const { left, top } = getPopupPosition(width, height);
3788
+ // Open popup window
3789
+ const popup = window.open(loginUrl, 'dexie-cloud-oauth', `width=${width},height=${height},left=${left},top=${top},menubar=no,toolbar=no,location=yes,status=no`);
3790
+ if (!popup) {
3791
+ throw new OAuthError('popup_blocked', provider);
3792
+ }
3793
+ return new Promise((resolve, reject) => {
3794
+ let resolved = false;
3795
+ // Listen for postMessage from the popup
3796
+ const handleMessage = (event) => {
3797
+ // Validate origin - must be from the Dexie Cloud server
3798
+ const expectedOrigin = new URL(databaseUrl).origin;
3799
+ if (event.origin !== expectedOrigin) {
3800
+ return; // Ignore messages from other origins
3801
+ }
3802
+ // Check if this is our OAuth result message
3803
+ if (!isOAuthResultMessage(event.data)) {
3804
+ return;
3805
+ }
3806
+ const message = event.data;
3807
+ // Validate state to prevent CSRF
3808
+ if (message.state !== state) {
3809
+ console.warn('[dexie-cloud] OAuth state mismatch, ignoring message');
3810
+ return;
3811
+ }
3812
+ // Clean up
3813
+ cleanup();
3814
+ resolved = true;
3815
+ // Handle error from OAuth flow
3816
+ if (message.error) {
3817
+ const errorCode = mapOAuthError(message.error);
3818
+ reject(new OAuthError(errorCode, provider, message.error));
3819
+ return;
3820
+ }
3821
+ // Success - return the authorization code
3822
+ if (message.code) {
3823
+ resolve({
3824
+ code: message.code,
3825
+ provider: message.provider,
3826
+ state: message.state,
3827
+ });
3828
+ }
3829
+ else {
3830
+ reject(new OAuthError('provider_error', provider, 'No authorization code received'));
3831
+ }
3832
+ };
3833
+ // Check if popup was closed without completing
3834
+ const checkPopupClosed = setInterval(() => {
3835
+ if (popup.closed && !resolved) {
3836
+ cleanup();
3837
+ reject(new OAuthError('popup_closed', provider));
3838
+ }
3839
+ }, 500);
3840
+ // Cleanup function
3841
+ const cleanup = () => {
3842
+ window.removeEventListener('message', handleMessage);
3843
+ clearInterval(checkPopupClosed);
3844
+ try {
3845
+ if (!popup.closed) {
3846
+ popup.close();
3847
+ }
3848
+ }
3849
+ catch (_a) {
3850
+ // Ignore errors when closing popup
3851
+ }
3852
+ };
3853
+ // Start listening for messages
3854
+ window.addEventListener('message', handleMessage);
3855
+ });
3856
+ });
3857
+ }
3858
+ /** Map OAuth error strings to error codes */
3859
+ function mapOAuthError(error) {
3860
+ const lowerError = error.toLowerCase();
3861
+ if (lowerError.includes('access_denied') || lowerError.includes('access denied')) {
3862
+ return 'access_denied';
3863
+ }
3864
+ if (lowerError.includes('email') && lowerError.includes('verif')) {
3865
+ return 'email_not_verified';
3866
+ }
3867
+ if (lowerError.includes('expired')) {
3868
+ return 'expired_code';
3869
+ }
3870
+ if (lowerError.includes('state')) {
3871
+ return 'invalid_state';
3872
+ }
3873
+ return 'provider_error';
3874
+ }
3875
+
3566
3876
  function otpFetchTokenCallback(db) {
3567
3877
  const { userInteraction } = db.cloud;
3568
3878
  return function otpAuthenticate(_a) {
3569
3879
  return __awaiter(this, arguments, void 0, function* ({ public_key, hints }) {
3570
- var _b;
3880
+ var _b, _c;
3571
3881
  let tokenRequest;
3572
3882
  const url = (_b = db.cloud.options) === null || _b === void 0 ? void 0 : _b.databaseUrl;
3573
3883
  if (!url)
3574
3884
  throw new Error(`No database URL given.`);
3885
+ // Handle OAuth code exchange (from redirect/deep link flows)
3886
+ if ((hints === null || hints === void 0 ? void 0 : hints.oauthCode) && hints.provider) {
3887
+ return yield exchangeOAuthCode({
3888
+ databaseUrl: url,
3889
+ code: hints.oauthCode,
3890
+ publicKey: public_key,
3891
+ scopes: ['ACCESS_DB'],
3892
+ });
3893
+ }
3894
+ // Handle OAuth provider login (popup flow)
3895
+ if (hints === null || hints === void 0 ? void 0 : hints.provider) {
3896
+ return yield handleOAuthFlow(db, public_key, hints.provider);
3897
+ }
3575
3898
  if ((hints === null || hints === void 0 ? void 0 : hints.grant_type) === 'demo') {
3576
3899
  const demo_user = yield promptForEmail(userInteraction, 'Enter a demo user email', (hints === null || hints === void 0 ? void 0 : hints.email) || (hints === null || hints === void 0 ? void 0 : hints.userId));
3577
3900
  tokenRequest = {
@@ -3595,6 +3918,18 @@ function otpFetchTokenCallback(db) {
3595
3918
  };
3596
3919
  }
3597
3920
  else {
3921
+ // Check for available auth providers (OAuth + OTP)
3922
+ const socialAuthEnabled = ((_c = db.cloud.options) === null || _c === void 0 ? void 0 : _c.socialAuth) !== false;
3923
+ const authProviders = yield fetchAuthProviders(url, socialAuthEnabled);
3924
+ // If we have OAuth providers available, prompt for selection
3925
+ if (authProviders.providers.length > 0) {
3926
+ const selection = yield promptForProvider(userInteraction, authProviders.providers, authProviders.otpEnabled, 'Sign in');
3927
+ if (selection.type === 'provider') {
3928
+ // User selected an OAuth provider
3929
+ return yield handleOAuthFlow(db, public_key, selection.provider);
3930
+ }
3931
+ // User chose OTP - continue with email prompt below
3932
+ }
3598
3933
  const email = yield promptForEmail(userInteraction, 'Enter email address', hints === null || hints === void 0 ? void 0 : hints.email);
3599
3934
  if (/@demo.local$/.test(email)) {
3600
3935
  tokenRequest = {
@@ -3672,6 +4007,49 @@ function otpFetchTokenCallback(db) {
3672
4007
  });
3673
4008
  };
3674
4009
  }
4010
+ /**
4011
+ * Handles the OAuth popup flow and token exchange.
4012
+ */
4013
+ function handleOAuthFlow(db, publicKey, provider) {
4014
+ return __awaiter(this, void 0, void 0, function* () {
4015
+ var _a, _b, _c;
4016
+ const url = (_a = db.cloud.options) === null || _a === void 0 ? void 0 : _a.databaseUrl;
4017
+ if (!url)
4018
+ throw new Error(`No database URL given.`);
4019
+ const { userInteraction } = db.cloud;
4020
+ const usePopup = ((_b = db.cloud.options) === null || _b === void 0 ? void 0 : _b.oauthPopup) !== false;
4021
+ const redirectUri = ((_c = db.cloud.options) === null || _c === void 0 ? void 0 : _c.oauthRedirectUri) ||
4022
+ (typeof window !== 'undefined' ? window.location.origin : undefined);
4023
+ try {
4024
+ // Start OAuth popup flow
4025
+ const result = yield oauthLogin({
4026
+ databaseUrl: url,
4027
+ provider,
4028
+ redirectUri,
4029
+ usePopup,
4030
+ });
4031
+ // Exchange the auth code for tokens
4032
+ return yield exchangeOAuthCode({
4033
+ databaseUrl: url,
4034
+ code: result.code,
4035
+ publicKey,
4036
+ scopes: ['ACCESS_DB'],
4037
+ });
4038
+ }
4039
+ catch (error) {
4040
+ if (error instanceof OAuthError) {
4041
+ // Show user-friendly error message
4042
+ yield alertUser(userInteraction, 'Authentication Failed', {
4043
+ type: 'error',
4044
+ messageCode: 'GENERIC_ERROR',
4045
+ message: error.userMessage,
4046
+ messageParams: {},
4047
+ }).catch(() => { });
4048
+ }
4049
+ throw error;
4050
+ }
4051
+ });
4052
+ }
3675
4053
 
3676
4054
  /** A way to log to console in production without terser stripping out
3677
4055
  * it from the release bundle.
@@ -4494,7 +4872,8 @@ function overrideParseStoresSpec(origFunc, dexie) {
4494
4872
  const cloudSchema = dexie.cloud.schema || (dexie.cloud.schema = {});
4495
4873
  const allPrefixes = new Set();
4496
4874
  Object.keys(storesClone).forEach(tableName => {
4497
- const schemaSrc = storesClone[tableName];
4875
+ var _a;
4876
+ const schemaSrc = (_a = storesClone[tableName]) === null || _a === void 0 ? void 0 : _a.trim();
4498
4877
  const cloudTableSchema = cloudSchema[tableName] || (cloudSchema[tableName] = {});
4499
4878
  if (schemaSrc != null) {
4500
4879
  if (/^\@/.test(schemaSrc)) {
@@ -4535,7 +4914,8 @@ function performGuardedJob(db, jobName, job) {
4535
4914
  // No support for guarding jobs. IE11, node.js, etc.
4536
4915
  return job();
4537
4916
  }
4538
- return navigator.locks.request(db.name + '|' + jobName, () => job());
4917
+ // @ts-expect-error - LockManager callback type inference issue with generics
4918
+ return navigator.locks.request(db.name + '|' + jobName, job);
4539
4919
  }
4540
4920
 
4541
4921
  function performInitialSync(db, cloudOptions, cloudSchema) {
@@ -5290,12 +5670,9 @@ function verifySchema(db) {
5290
5670
  }
5291
5671
  }
5292
5672
 
5293
- var n,l$1,u$1,t$1,o$1,f$1={},e$1=[],c$1=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function s$1(n,l){for(var u in l)n[u]=l[u];return n}function a$1(n){var l=n.parentNode;l&&l.removeChild(n);}function h(l,u,i){var t,o,r,f={};for(r in u)"key"==r?t=u[r]:"ref"==r?o=u[r]:f[r]=u[r];if(arguments.length>2&&(f.children=arguments.length>3?n.call(arguments,2):i),"function"==typeof l&&null!=l.defaultProps)for(r in l.defaultProps)void 0===f[r]&&(f[r]=l.defaultProps[r]);return v$1(l,f,t,o,null)}function v$1(n,i,t,o,r){var f={type:n,props:i,key:t,ref:o,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==r?++u$1:r};return null==r&&null!=l$1.vnode&&l$1.vnode(f),f}function p$1(n){return n.children}function d$1(n,l){this.props=n,this.context=l;}function _$1(n,l){if(null==l)return n.__?_$1(n.__,n.__.__k.indexOf(n)+1):null;for(var u;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e)return u.__e;return "function"==typeof n.type?_$1(n):null}function k$1(n){var l,u;if(null!=(n=n.__)&&null!=n.__c){for(n.__e=n.__c.base=null,l=0;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e){n.__e=n.__c.base=u.__e;break}return k$1(n)}}function b$1(n){(!n.__d&&(n.__d=!0)&&t$1.push(n)&&!g$1.__r++||o$1!==l$1.debounceRendering)&&((o$1=l$1.debounceRendering)||setTimeout)(g$1);}function g$1(){for(var n;g$1.__r=t$1.length;)n=t$1.sort(function(n,l){return n.__v.__b-l.__v.__b}),t$1=[],n.some(function(n){var l,u,i,t,o,r;n.__d&&(o=(t=(l=n).__v).__e,(r=l.__P)&&(u=[],(i=s$1({},t)).__v=t.__v+1,j$1(r,t,i,l.__n,void 0!==r.ownerSVGElement,null!=t.__h?[o]:null,u,null==o?_$1(t):o,t.__h),z$1(u,t),t.__e!=o&&k$1(t)));});}function w$1(n,l,u,i,t,o,r,c,s,a){var h,y,d,k,b,g,w,x=i&&i.__k||e$1,C=x.length;for(u.__k=[],h=0;h<l.length;h++)if(null!=(k=u.__k[h]=null==(k=l[h])||"boolean"==typeof k?null:"string"==typeof k||"number"==typeof k||"bigint"==typeof k?v$1(null,k,null,null,k):Array.isArray(k)?v$1(p$1,{children:k},null,null,null):k.__b>0?v$1(k.type,k.props,k.key,null,k.__v):k)){if(k.__=u,k.__b=u.__b+1,null===(d=x[h])||d&&k.key==d.key&&k.type===d.type)x[h]=void 0;else for(y=0;y<C;y++){if((d=x[y])&&k.key==d.key&&k.type===d.type){x[y]=void 0;break}d=null;}j$1(n,k,d=d||f$1,t,o,r,c,s,a),b=k.__e,(y=k.ref)&&d.ref!=y&&(w||(w=[]),d.ref&&w.push(d.ref,null,k),w.push(y,k.__c||b,k)),null!=b?(null==g&&(g=b),"function"==typeof k.type&&k.__k===d.__k?k.__d=s=m$1(k,s,n):s=A(n,k,d,x,b,s),"function"==typeof u.type&&(u.__d=s)):s&&d.__e==s&&s.parentNode!=n&&(s=_$1(d));}for(u.__e=g,h=C;h--;)null!=x[h]&&("function"==typeof u.type&&null!=x[h].__e&&x[h].__e==u.__d&&(u.__d=_$1(i,h+1)),N(x[h],x[h]));if(w)for(h=0;h<w.length;h++)M(w[h],w[++h],w[++h]);}function m$1(n,l,u){for(var i,t=n.__k,o=0;t&&o<t.length;o++)(i=t[o])&&(i.__=n,l="function"==typeof i.type?m$1(i,l,u):A(u,i,i,t,i.__e,l));return l}function A(n,l,u,i,t,o){var r,f,e;if(void 0!==l.__d)r=l.__d,l.__d=void 0;else if(null==u||t!=o||null==t.parentNode)n:if(null==o||o.parentNode!==n)n.appendChild(t),r=null;else {for(f=o,e=0;(f=f.nextSibling)&&e<i.length;e+=2)if(f==t)break n;n.insertBefore(t,o),r=o;}return void 0!==r?r:t.nextSibling}function C(n,l,u,i,t){var o;for(o in u)"children"===o||"key"===o||o in l||H(n,o,null,u[o],i);for(o in l)t&&"function"!=typeof l[o]||"children"===o||"key"===o||"value"===o||"checked"===o||u[o]===l[o]||H(n,o,l[o],u[o],i);}function $(n,l,u){"-"===l[0]?n.setProperty(l,u):n[l]=null==u?"":"number"!=typeof u||c$1.test(l)?u:u+"px";}function H(n,l,u,i,t){var o;n:if("style"===l)if("string"==typeof u)n.style.cssText=u;else {if("string"==typeof i&&(n.style.cssText=i=""),i)for(l in i)u&&l in u||$(n.style,l,"");if(u)for(l in u)i&&u[l]===i[l]||$(n.style,l,u[l]);}else if("o"===l[0]&&"n"===l[1])o=l!==(l=l.replace(/Capture$/,"")),l=l.toLowerCase()in n?l.toLowerCase().slice(2):l.slice(2),n.l||(n.l={}),n.l[l+o]=u,u?i||n.addEventListener(l,o?T:I,o):n.removeEventListener(l,o?T:I,o);else if("dangerouslySetInnerHTML"!==l){if(t)l=l.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if("href"!==l&&"list"!==l&&"form"!==l&&"tabIndex"!==l&&"download"!==l&&l in n)try{n[l]=null==u?"":u;break n}catch(n){}"function"==typeof u||(null!=u&&(!1!==u||"a"===l[0]&&"r"===l[1])?n.setAttribute(l,u):n.removeAttribute(l));}}function I(n){this.l[n.type+!1](l$1.event?l$1.event(n):n);}function T(n){this.l[n.type+!0](l$1.event?l$1.event(n):n);}function j$1(n,u,i,t,o,r,f,e,c){var a,h,v,y,_,k,b,g,m,x,A,C,$,H=u.type;if(void 0!==u.constructor)return null;null!=i.__h&&(c=i.__h,e=u.__e=i.__e,u.__h=null,r=[e]),(a=l$1.__b)&&a(u);try{n:if("function"==typeof H){if(g=u.props,m=(a=H.contextType)&&t[a.__c],x=a?m?m.props.value:a.__:t,i.__c?b=(h=u.__c=i.__c).__=h.__E:("prototype"in H&&H.prototype.render?u.__c=h=new H(g,x):(u.__c=h=new d$1(g,x),h.constructor=H,h.render=O),m&&m.sub(h),h.props=g,h.state||(h.state={}),h.context=x,h.__n=t,v=h.__d=!0,h.__h=[]),null==h.__s&&(h.__s=h.state),null!=H.getDerivedStateFromProps&&(h.__s==h.state&&(h.__s=s$1({},h.__s)),s$1(h.__s,H.getDerivedStateFromProps(g,h.__s))),y=h.props,_=h.state,v)null==H.getDerivedStateFromProps&&null!=h.componentWillMount&&h.componentWillMount(),null!=h.componentDidMount&&h.__h.push(h.componentDidMount);else {if(null==H.getDerivedStateFromProps&&g!==y&&null!=h.componentWillReceiveProps&&h.componentWillReceiveProps(g,x),!h.__e&&null!=h.shouldComponentUpdate&&!1===h.shouldComponentUpdate(g,h.__s,x)||u.__v===i.__v){h.props=g,h.state=h.__s,u.__v!==i.__v&&(h.__d=!1),h.__v=u,u.__e=i.__e,u.__k=i.__k,u.__k.forEach(function(n){n&&(n.__=u);}),h.__h.length&&f.push(h);break n}null!=h.componentWillUpdate&&h.componentWillUpdate(g,h.__s,x),null!=h.componentDidUpdate&&h.__h.push(function(){h.componentDidUpdate(y,_,k);});}if(h.context=x,h.props=g,h.__v=u,h.__P=n,A=l$1.__r,C=0,"prototype"in H&&H.prototype.render)h.state=h.__s,h.__d=!1,A&&A(u),a=h.render(h.props,h.state,h.context);else do{h.__d=!1,A&&A(u),a=h.render(h.props,h.state,h.context),h.state=h.__s;}while(h.__d&&++C<25);h.state=h.__s,null!=h.getChildContext&&(t=s$1(s$1({},t),h.getChildContext())),v||null==h.getSnapshotBeforeUpdate||(k=h.getSnapshotBeforeUpdate(y,_)),$=null!=a&&a.type===p$1&&null==a.key?a.props.children:a,w$1(n,Array.isArray($)?$:[$],u,i,t,o,r,f,e,c),h.base=u.__e,u.__h=null,h.__h.length&&f.push(h),b&&(h.__E=h.__=null),h.__e=!1;}else null==r&&u.__v===i.__v?(u.__k=i.__k,u.__e=i.__e):u.__e=L(i.__e,u,i,t,o,r,f,c);(a=l$1.diffed)&&a(u);}catch(n){u.__v=null,(c||null!=r)&&(u.__e=e,u.__h=!!c,r[r.indexOf(e)]=null),l$1.__e(n,u,i);}}function z$1(n,u){l$1.__c&&l$1.__c(u,n),n.some(function(u){try{n=u.__h,u.__h=[],n.some(function(n){n.call(u);});}catch(n){l$1.__e(n,u.__v);}});}function L(l,u,i,t,o,r,e,c){var s,h,v,y=i.props,p=u.props,d=u.type,k=0;if("svg"===d&&(o=!0),null!=r)for(;k<r.length;k++)if((s=r[k])&&"setAttribute"in s==!!d&&(d?s.localName===d:3===s.nodeType)){l=s,r[k]=null;break}if(null==l){if(null===d)return document.createTextNode(p);l=o?document.createElementNS("http://www.w3.org/2000/svg",d):document.createElement(d,p.is&&p),r=null,c=!1;}if(null===d)y===p||c&&l.data===p||(l.data=p);else {if(r=r&&n.call(l.childNodes),h=(y=i.props||f$1).dangerouslySetInnerHTML,v=p.dangerouslySetInnerHTML,!c){if(null!=r)for(y={},k=0;k<l.attributes.length;k++)y[l.attributes[k].name]=l.attributes[k].value;(v||h)&&(v&&(h&&v.__html==h.__html||v.__html===l.innerHTML)||(l.innerHTML=v&&v.__html||""));}if(C(l,p,y,o,c),v)u.__k=[];else if(k=u.props.children,w$1(l,Array.isArray(k)?k:[k],u,i,t,o&&"foreignObject"!==d,r,e,r?r[0]:i.__k&&_$1(i,0),c),null!=r)for(k=r.length;k--;)null!=r[k]&&a$1(r[k]);c||("value"in p&&void 0!==(k=p.value)&&(k!==l.value||"progress"===d&&!k||"option"===d&&k!==y.value)&&H(l,"value",k,y.value,!1),"checked"in p&&void 0!==(k=p.checked)&&k!==l.checked&&H(l,"checked",k,y.checked,!1));}return l}function M(n,u,i){try{"function"==typeof n?n(u):n.current=u;}catch(n){l$1.__e(n,i);}}function N(n,u,i){var t,o;if(l$1.unmount&&l$1.unmount(n),(t=n.ref)&&(t.current&&t.current!==n.__e||M(t,null,u)),null!=(t=n.__c)){if(t.componentWillUnmount)try{t.componentWillUnmount();}catch(n){l$1.__e(n,u);}t.base=t.__P=null;}if(t=n.__k)for(o=0;o<t.length;o++)t[o]&&N(t[o],u,"function"!=typeof n.type);i||null==n.__e||a$1(n.__e),n.__e=n.__d=void 0;}function O(n,l,u){return this.constructor(n,u)}function P(u,i,t){var o,r,e;l$1.__&&l$1.__(u,i),r=(o="function"==typeof t)?null:t&&t.__k||i.__k,e=[],j$1(i,u=(!o&&t||i).__k=h(p$1,null,[u]),r||f$1,f$1,void 0!==i.ownerSVGElement,!o&&t?[t]:r?null:i.firstChild?n.call(i.childNodes):null,e,!o&&t?t:r?r.__e:i.firstChild,o),z$1(e,u);}n=e$1.slice,l$1={__e:function(n,l,u,i){for(var t,o,r;l=l.__;)if((t=l.__c)&&!t.__)try{if((o=t.constructor)&&null!=o.getDerivedStateFromError&&(t.setState(o.getDerivedStateFromError(n)),r=t.__d),null!=t.componentDidCatch&&(t.componentDidCatch(n,i||{}),r=t.__d),r)return t.__E=t}catch(l){n=l;}throw n}},u$1=0,d$1.prototype.setState=function(n,l){var u;u=null!=this.__s&&this.__s!==this.state?this.__s:this.__s=s$1({},this.state),"function"==typeof n&&(n=n(s$1({},u),this.props)),n&&s$1(u,n),null!=n&&this.__v&&(l&&this.__h.push(l),b$1(this));},d$1.prototype.forceUpdate=function(n){this.__v&&(this.__e=!0,n&&this.__h.push(n),b$1(this));},d$1.prototype.render=p$1,t$1=[],g$1.__r=0;
5673
+ var n,l$1,u$1,i$1,r$1,o$1,e$1,f$1,c$1,s$1,a$1,p$1={},v$1=[],y=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,w$1=Array.isArray;function d$1(n,l){for(var u in l)n[u]=l[u];return n}function g(n){n&&n.parentNode&&n.parentNode.removeChild(n);}function _$1(l,u,t){var i,r,o,e={};for(o in u)"key"==o?i=u[o]:"ref"==o?r=u[o]:e[o]=u[o];if(arguments.length>2&&(e.children=arguments.length>3?n.call(arguments,2):t),"function"==typeof l&&null!=l.defaultProps)for(o in l.defaultProps) void 0===e[o]&&(e[o]=l.defaultProps[o]);return m$1(l,e,i,r,null)}function m$1(n,t,i,r,o){var e={type:n,props:t,key:i,ref:r,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:null==o?++u$1:o,__i:-1,__u:0};return null==o&&null!=l$1.vnode&&l$1.vnode(e),e}function k$1(n){return n.children}function x(n,l){this.props=n,this.context=l;}function S(n,l){if(null==l)return n.__?S(n.__,n.__i+1):null;for(var u;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e)return u.__e;return "function"==typeof n.type?S(n):null}function C$1(n){var l,u;if(null!=(n=n.__)&&null!=n.__c){for(n.__e=n.__c.base=null,l=0;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e){n.__e=n.__c.base=u.__e;break}return C$1(n)}}function M(n){(!n.__d&&(n.__d=true)&&i$1.push(n)&&!$.__r++||r$1!=l$1.debounceRendering)&&((r$1=l$1.debounceRendering)||o$1)($);}function $(){for(var n,u,t,r,o,f,c,s=1;i$1.length;)i$1.length>s&&i$1.sort(e$1),n=i$1.shift(),s=i$1.length,n.__d&&(t=void 0,r=void 0,o=(r=(u=n).__v).__e,f=[],c=[],u.__P&&((t=d$1({},r)).__v=r.__v+1,l$1.vnode&&l$1.vnode(t),O(u.__P,t,r,u.__n,u.__P.namespaceURI,32&r.__u?[o]:null,f,null==o?S(r):o,!!(32&r.__u),c),t.__v=r.__v,t.__.__k[t.__i]=t,N(f,t,c),r.__e=r.__=null,t.__e!=o&&C$1(t)));$.__r=0;}function I(n,l,u,t,i,r,o,e,f,c,s){var a,h,y,w,d,g,_,m=t&&t.__k||v$1,b=l.length;for(f=P(u,l,m,f,b),a=0;a<b;a++)null!=(y=u.__k[a])&&(h=-1==y.__i?p$1:m[y.__i]||p$1,y.__i=a,g=O(n,y,h,i,r,o,e,f,c,s),w=y.__e,y.ref&&h.ref!=y.ref&&(h.ref&&B$1(h.ref,null,y),s.push(y.ref,y.__c||w,y)),null==d&&null!=w&&(d=w),(_=!!(4&y.__u))||h.__k===y.__k?f=A$1(y,f,n,_):"function"==typeof y.type&&void 0!==g?f=g:w&&(f=w.nextSibling),y.__u&=-7);return u.__e=d,f}function P(n,l,u,t,i){var r,o,e,f,c,s=u.length,a=s,h=0;for(n.__k=new Array(i),r=0;r<i;r++)null!=(o=l[r])&&"boolean"!=typeof o&&"function"!=typeof o?("string"==typeof o||"number"==typeof o||"bigint"==typeof o||o.constructor==String?o=n.__k[r]=m$1(null,o,null,null,null):w$1(o)?o=n.__k[r]=m$1(k$1,{children:o},null,null,null):null==o.constructor&&o.__b>0?o=n.__k[r]=m$1(o.type,o.props,o.key,o.ref?o.ref:null,o.__v):n.__k[r]=o,f=r+h,o.__=n,o.__b=n.__b+1,-1!=(c=o.__i=L(o,u,f,a))&&(a--,(e=u[c])&&(e.__u|=2)),null==e||null==e.__v?(-1==c&&(i>s?h--:i<s&&h++),"function"!=typeof o.type&&(o.__u|=4)):c!=f&&(c==f-1?h--:c==f+1?h++:(c>f?h--:h++,o.__u|=4))):n.__k[r]=null;if(a)for(r=0;r<s;r++)null!=(e=u[r])&&0==(2&e.__u)&&(e.__e==t&&(t=S(e)),D$1(e,e));return t}function A$1(n,l,u,t){var i,r;if("function"==typeof n.type){for(i=n.__k,r=0;i&&r<i.length;r++)i[r]&&(i[r].__=n,l=A$1(i[r],l,u,t));return l}n.__e!=l&&(t&&(l&&n.type&&!l.parentNode&&(l=S(n)),u.insertBefore(n.__e,l||null)),l=n.__e);do{l=l&&l.nextSibling;}while(null!=l&&8==l.nodeType);return l}function L(n,l,u,t){var i,r,o,e=n.key,f=n.type,c=l[u],s=null!=c&&0==(2&c.__u);if(null===c&&null==e||s&&e==c.key&&f==c.type)return u;if(t>(s?1:0))for(i=u-1,r=u+1;i>=0||r<l.length;)if(null!=(c=l[o=i>=0?i--:r++])&&0==(2&c.__u)&&e==c.key&&f==c.type)return o;return -1}function T$1(n,l,u){"-"==l[0]?n.setProperty(l,null==u?"":u):n[l]=null==u?"":"number"!=typeof u||y.test(l)?u:u+"px";}function j$1(n,l,u,t,i){var r,o;n:if("style"==l)if("string"==typeof u)n.style.cssText=u;else {if("string"==typeof t&&(n.style.cssText=t=""),t)for(l in t)u&&l in u||T$1(n.style,l,"");if(u)for(l in u)t&&u[l]==t[l]||T$1(n.style,l,u[l]);}else if("o"==l[0]&&"n"==l[1])r=l!=(l=l.replace(f$1,"$1")),o=l.toLowerCase(),l=o in n||"onFocusOut"==l||"onFocusIn"==l?o.slice(2):l.slice(2),n.l||(n.l={}),n.l[l+r]=u,u?t?u.u=t.u:(u.u=c$1,n.addEventListener(l,r?a$1:s$1,r)):n.removeEventListener(l,r?a$1:s$1,r);else {if("http://www.w3.org/2000/svg"==i)l=l.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if("width"!=l&&"height"!=l&&"href"!=l&&"list"!=l&&"form"!=l&&"tabIndex"!=l&&"download"!=l&&"rowSpan"!=l&&"colSpan"!=l&&"role"!=l&&"popover"!=l&&l in n)try{n[l]=null==u?"":u;break n}catch(n){}"function"==typeof u||(null==u||false===u&&"-"!=l[4]?n.removeAttribute(l):n.setAttribute(l,"popover"==l&&1==u?"":u));}}function F(n){return function(u){if(this.l){var t=this.l[u.type+n];if(null==u.t)u.t=c$1++;else if(u.t<t.u)return;return t(l$1.event?l$1.event(u):u)}}}function O(n,u,t,i,r,o,e,f,c,s){var a,h,p,v,y,_,m,b,S,C,M,$,P,A,H,L,T,j=u.type;if(null!=u.constructor)return null;128&t.__u&&(c=!!(32&t.__u),o=[f=u.__e=t.__e]),(a=l$1.__b)&&a(u);n:if("function"==typeof j)try{if(b=u.props,S="prototype"in j&&j.prototype.render,C=(a=j.contextType)&&i[a.__c],M=a?C?C.props.value:a.__:i,t.__c?m=(h=u.__c=t.__c).__=h.__E:(S?u.__c=h=new j(b,M):(u.__c=h=new x(b,M),h.constructor=j,h.render=E),C&&C.sub(h),h.state||(h.state={}),h.__n=i,p=h.__d=!0,h.__h=[],h._sb=[]),S&&null==h.__s&&(h.__s=h.state),S&&null!=j.getDerivedStateFromProps&&(h.__s==h.state&&(h.__s=d$1({},h.__s)),d$1(h.__s,j.getDerivedStateFromProps(b,h.__s))),v=h.props,y=h.state,h.__v=u,p)S&&null==j.getDerivedStateFromProps&&null!=h.componentWillMount&&h.componentWillMount(),S&&null!=h.componentDidMount&&h.__h.push(h.componentDidMount);else {if(S&&null==j.getDerivedStateFromProps&&b!==v&&null!=h.componentWillReceiveProps&&h.componentWillReceiveProps(b,M),u.__v==t.__v||!h.__e&&null!=h.shouldComponentUpdate&&!1===h.shouldComponentUpdate(b,h.__s,M)){for(u.__v!=t.__v&&(h.props=b,h.state=h.__s,h.__d=!1),u.__e=t.__e,u.__k=t.__k,u.__k.some(function(n){n&&(n.__=u);}),$=0;$<h._sb.length;$++)h.__h.push(h._sb[$]);h._sb=[],h.__h.length&&e.push(h);break n}null!=h.componentWillUpdate&&h.componentWillUpdate(b,h.__s,M),S&&null!=h.componentDidUpdate&&h.__h.push(function(){h.componentDidUpdate(v,y,_);});}if(h.context=M,h.props=b,h.__P=n,h.__e=!1,P=l$1.__r,A=0,S){for(h.state=h.__s,h.__d=!1,P&&P(u),a=h.render(h.props,h.state,h.context),H=0;H<h._sb.length;H++)h.__h.push(h._sb[H]);h._sb=[];}else do{h.__d=!1,P&&P(u),a=h.render(h.props,h.state,h.context),h.state=h.__s;}while(h.__d&&++A<25);h.state=h.__s,null!=h.getChildContext&&(i=d$1(d$1({},i),h.getChildContext())),S&&!p&&null!=h.getSnapshotBeforeUpdate&&(_=h.getSnapshotBeforeUpdate(v,y)),L=a,null!=a&&a.type===k$1&&null==a.key&&(L=V(a.props.children)),f=I(n,w$1(L)?L:[L],u,t,i,r,o,e,f,c,s),h.base=u.__e,u.__u&=-161,h.__h.length&&e.push(h),m&&(h.__E=h.__=null);}catch(n){if(u.__v=null,c||null!=o)if(n.then){for(u.__u|=c?160:128;f&&8==f.nodeType&&f.nextSibling;)f=f.nextSibling;o[o.indexOf(f)]=null,u.__e=f;}else {for(T=o.length;T--;)g(o[T]);z$1(u);}else u.__e=t.__e,u.__k=t.__k,n.then||z$1(u);l$1.__e(n,u,t);}else null==o&&u.__v==t.__v?(u.__k=t.__k,u.__e=t.__e):f=u.__e=q(t.__e,u,t,i,r,o,e,c,s);return (a=l$1.diffed)&&a(u),128&u.__u?void 0:f}function z$1(n){n&&n.__c&&(n.__c.__e=true),n&&n.__k&&n.__k.forEach(z$1);}function N(n,u,t){for(var i=0;i<t.length;i++)B$1(t[i],t[++i],t[++i]);l$1.__c&&l$1.__c(u,n),n.some(function(u){try{n=u.__h,u.__h=[],n.some(function(n){n.call(u);});}catch(n){l$1.__e(n,u.__v);}});}function V(n){return "object"!=typeof n||null==n||n.__b&&n.__b>0?n:w$1(n)?n.map(V):d$1({},n)}function q(u,t,i,r,o,e,f,c,s){var a,h,v,y,d,_,m,b=i.props||p$1,k=t.props,x=t.type;if("svg"==x?o="http://www.w3.org/2000/svg":"math"==x?o="http://www.w3.org/1998/Math/MathML":o||(o="http://www.w3.org/1999/xhtml"),null!=e)for(a=0;a<e.length;a++)if((d=e[a])&&"setAttribute"in d==!!x&&(x?d.localName==x:3==d.nodeType)){u=d,e[a]=null;break}if(null==u){if(null==x)return document.createTextNode(k);u=document.createElementNS(o,x,k.is&&k),c&&(l$1.__m&&l$1.__m(t,e),c=false),e=null;}if(null==x)b===k||c&&u.data==k||(u.data=k);else {if(e=e&&n.call(u.childNodes),!c&&null!=e)for(b={},a=0;a<u.attributes.length;a++)b[(d=u.attributes[a]).name]=d.value;for(a in b)if(d=b[a],"children"==a);else if("dangerouslySetInnerHTML"==a)v=d;else if(!(a in k)){if("value"==a&&"defaultValue"in k||"checked"==a&&"defaultChecked"in k)continue;j$1(u,a,null,d,o);}for(a in k)d=k[a],"children"==a?y=d:"dangerouslySetInnerHTML"==a?h=d:"value"==a?_=d:"checked"==a?m=d:c&&"function"!=typeof d||b[a]===d||j$1(u,a,d,b[a],o);if(h)c||v&&(h.__html==v.__html||h.__html==u.innerHTML)||(u.innerHTML=h.__html),t.__k=[];else if(v&&(u.innerHTML=""),I("template"==t.type?u.content:u,w$1(y)?y:[y],t,i,r,"foreignObject"==x?"http://www.w3.org/1999/xhtml":o,e,f,e?e[0]:i.__k&&S(i,0),c,s),null!=e)for(a=e.length;a--;)g(e[a]);c||(a="value","progress"==x&&null==_?u.removeAttribute("value"):null!=_&&(_!==u[a]||"progress"==x&&!_||"option"==x&&_!=b[a])&&j$1(u,a,_,b[a],o),a="checked",null!=m&&m!=u[a]&&j$1(u,a,m,b[a],o));}return u}function B$1(n,u,t){try{if("function"==typeof n){var i="function"==typeof n.__u;i&&n.__u(),i&&null==u||(n.__u=n(u));}else n.current=u;}catch(n){l$1.__e(n,t);}}function D$1(n,u,t){var i,r;if(l$1.unmount&&l$1.unmount(n),(i=n.ref)&&(i.current&&i.current!=n.__e||B$1(i,null,u)),null!=(i=n.__c)){if(i.componentWillUnmount)try{i.componentWillUnmount();}catch(n){l$1.__e(n,u);}i.base=i.__P=null;}if(i=n.__k)for(r=0;r<i.length;r++)i[r]&&D$1(i[r],u,t||"function"!=typeof n.type);t||g(n.__e),n.__c=n.__=n.__e=void 0;}function E(n,l,u){return this.constructor(n,u)}function G(u,t,i){var r,o,e,f;t==document&&(t=document.documentElement),l$1.__&&l$1.__(u,t),o=(r="function"=="undefined")?null:t.__k,e=[],f=[],O(t,u=(t).__k=_$1(k$1,null,[u]),o||p$1,p$1,t.namespaceURI,o?null:t.firstChild?n.call(t.childNodes):null,e,o?o.__e:t.firstChild,r,f),N(e,u,f);}n=v$1.slice,l$1={__e:function(n,l,u,t){for(var i,r,o;l=l.__;)if((i=l.__c)&&!i.__)try{if((r=i.constructor)&&null!=r.getDerivedStateFromError&&(i.setState(r.getDerivedStateFromError(n)),o=i.__d),null!=i.componentDidCatch&&(i.componentDidCatch(n,t||{}),o=i.__d),o)return i.__E=i}catch(l){n=l;}throw n}},u$1=0,x.prototype.setState=function(n,l){var u;u=null!=this.__s&&this.__s!=this.state?this.__s:this.__s=d$1({},this.state),"function"==typeof n&&(n=n(d$1({},u),this.props)),n&&d$1(u,n),null!=n&&this.__v&&(l&&this._sb.push(l),M(this));},x.prototype.forceUpdate=function(n){this.__v&&(this.__e=true,n&&this.__h.push(n),M(this));},x.prototype.render=k$1,i$1=[],o$1="function"==typeof Promise?Promise.prototype.then.bind(Promise.resolve()):setTimeout,e$1=function(n,l){return n.__v.__b-l.__v.__b},$.__r=0,f$1=/(PointerCapture)$|Capture$/i,c$1=0,s$1=F(false),a$1=F(true);
5294
5674
 
5295
5675
  const Styles = {
5296
- Error: {
5297
- color: "red",
5298
- },
5299
5676
  Alert: {
5300
5677
  error: {
5301
5678
  color: "red",
@@ -5410,17 +5787,110 @@ const Styles = {
5410
5787
  color: "#333",
5411
5788
  borderBottom: "1px solid #eee",
5412
5789
  paddingBottom: "10px"
5790
+ },
5791
+ // OAuth Provider Button Styles
5792
+ ProviderButton: {
5793
+ display: "flex",
5794
+ alignItems: "center",
5795
+ justifyContent: "center",
5796
+ width: "100%",
5797
+ padding: "12px 16px",
5798
+ marginBottom: "10px",
5799
+ border: "1px solid #d1d5db",
5800
+ borderRadius: "6px",
5801
+ backgroundColor: "#ffffff",
5802
+ cursor: "pointer",
5803
+ fontSize: "14px",
5804
+ fontWeight: "500",
5805
+ color: "#374151",
5806
+ transition: "all 0.2s ease",
5807
+ gap: "12px"
5808
+ },
5809
+ ProviderButtonIcon: {
5810
+ width: "20px",
5811
+ height: "20px",
5812
+ flexShrink: 0
5813
+ },
5814
+ ProviderButtonText: {
5815
+ flex: 1,
5816
+ textAlign: "left"
5817
+ },
5818
+ // Provider-specific colors
5819
+ ProviderGoogle: {
5820
+ backgroundColor: "#ffffff",
5821
+ border: "1px solid #dadce0",
5822
+ color: "#3c4043"
5823
+ },
5824
+ ProviderGitHub: {
5825
+ backgroundColor: "#24292e",
5826
+ border: "1px solid #24292e",
5827
+ color: "#ffffff"
5828
+ },
5829
+ ProviderMicrosoft: {
5830
+ backgroundColor: "#ffffff",
5831
+ border: "1px solid #8c8c8c",
5832
+ color: "#5e5e5e"
5833
+ },
5834
+ ProviderApple: {
5835
+ backgroundColor: "#000000",
5836
+ border: "1px solid #000000",
5837
+ color: "#ffffff"
5838
+ },
5839
+ ProviderCustom: {
5840
+ backgroundColor: "#4f46e5",
5841
+ border: "1px solid #4f46e5",
5842
+ color: "#ffffff"
5843
+ },
5844
+ // Divider styles
5845
+ Divider: {
5846
+ display: "flex",
5847
+ alignItems: "center",
5848
+ margin: "20px 0",
5849
+ color: "#6b7280",
5850
+ fontSize: "13px"
5851
+ },
5852
+ DividerLine: {
5853
+ flex: 1,
5854
+ height: "1px",
5855
+ backgroundColor: "#e5e7eb"
5856
+ },
5857
+ DividerText: {
5858
+ padding: "0 12px",
5859
+ color: "#9ca3af"
5860
+ },
5861
+ // OTP Button (Continue with email)
5862
+ OtpButton: {
5863
+ display: "flex",
5864
+ alignItems: "center",
5865
+ justifyContent: "center",
5866
+ width: "100%",
5867
+ padding: "12px 16px",
5868
+ border: "1px solid #d1d5db",
5869
+ borderRadius: "6px",
5870
+ backgroundColor: "#f9fafb",
5871
+ cursor: "pointer",
5872
+ fontSize: "14px",
5873
+ fontWeight: "500",
5874
+ color: "#374151",
5875
+ transition: "all 0.2s ease",
5876
+ gap: "12px"
5877
+ },
5878
+ // Cancel button for provider selection
5879
+ CancelButtonRow: {
5880
+ display: "flex",
5881
+ justifyContent: "center",
5882
+ marginTop: "16px"
5413
5883
  }
5414
5884
  };
5415
5885
 
5416
5886
  function Dialog({ children, className }) {
5417
- return (h("div", { className: `dexie-dialog ${className || ''}` },
5418
- h("div", { style: Styles.Darken }),
5419
- h("div", { style: Styles.DialogOuter },
5420
- h("div", { style: Styles.DialogInner }, children))));
5887
+ return (_$1("div", { className: `dexie-dialog ${className || ''}` },
5888
+ _$1("div", { style: Styles.Darken }),
5889
+ _$1("div", { style: Styles.DialogOuter },
5890
+ _$1("div", { style: Styles.DialogInner }, children))));
5421
5891
  }
5422
5892
 
5423
- var t,r,u,i,o=0,c=[],f=[],e=l$1.__b,a=l$1.__r,v=l$1.diffed,l=l$1.__c,m=l$1.unmount;function d(t,u){l$1.__h&&l$1.__h(r,t,o||u),o=0;var i=r.__H||(r.__H={__:[],__h:[]});return t>=i.__.length&&i.__.push({__V:f}),i.__[t]}function p(n){return o=1,y(z,n)}function y(n,u,i){var o=d(t++,2);if(o.t=n,!o.__c&&(o.__=[i?i(u):z(void 0,u),function(n){var t=o.__N?o.__N[0]:o.__[0],r=o.t(t,n);t!==r&&(o.__N=[r,o.__[1]],o.__c.setState({}));}],o.__c=r,!r.u)){r.u=!0;var c=r.shouldComponentUpdate;r.shouldComponentUpdate=function(n,t,r){if(!o.__c.__H)return !0;var u=o.__c.__H.__.filter(function(n){return n.__c});if(u.every(function(n){return !n.__N}))return !c||c.call(this,n,t,r);var i=!1;return u.forEach(function(n){if(n.__N){var t=n.__[0];n.__=n.__N,n.__N=void 0,t!==n.__[0]&&(i=!0);}}),!!i&&(!c||c.call(this,n,t,r))};}return o.__N||o.__}function s(u,i){var o=d(t++,4);!l$1.__s&&w(o.__H,i)&&(o.__=u,o.i=i,r.__h.push(o));}function _(n){return o=5,F(function(){return {current:n}},[])}function F(n,r){var u=d(t++,7);return w(u.__H,r)?(u.__V=n(),u.i=r,u.__h=n,u.__V):u.__}function b(){for(var t;t=c.shift();)if(t.__P&&t.__H)try{t.__H.__h.forEach(j),t.__H.__h.forEach(k),t.__H.__h=[];}catch(r){t.__H.__h=[],l$1.__e(r,t.__v);}}l$1.__b=function(n){r=null,e&&e(n);},l$1.__r=function(n){a&&a(n),t=0;var i=(r=n.__c).__H;i&&(u===r?(i.__h=[],r.__h=[],i.__.forEach(function(n){n.__N&&(n.__=n.__N),n.__V=f,n.__N=n.i=void 0;})):(i.__h.forEach(j),i.__h.forEach(k),i.__h=[])),u=r;},l$1.diffed=function(t){v&&v(t);var o=t.__c;o&&o.__H&&(o.__H.__h.length&&(1!==c.push(o)&&i===l$1.requestAnimationFrame||((i=l$1.requestAnimationFrame)||function(n){var t,r=function(){clearTimeout(u),g&&cancelAnimationFrame(t),setTimeout(n);},u=setTimeout(r,100);g&&(t=requestAnimationFrame(r));})(b)),o.__H.__.forEach(function(n){n.i&&(n.__H=n.i),n.__V!==f&&(n.__=n.__V),n.i=void 0,n.__V=f;})),u=r=null;},l$1.__c=function(t,r){r.some(function(t){try{t.__h.forEach(j),t.__h=t.__h.filter(function(n){return !n.__||k(n)});}catch(u){r.some(function(n){n.__h&&(n.__h=[]);}),r=[],l$1.__e(u,t.__v);}}),l&&l(t,r);},l$1.unmount=function(t){m&&m(t);var r,u=t.__c;u&&u.__H&&(u.__H.__.forEach(function(n){try{j(n);}catch(n){r=n;}}),r&&l$1.__e(r,u.__v));};var g="function"==typeof requestAnimationFrame;function j(n){var t=r,u=n.__c;"function"==typeof u&&(n.__c=void 0,u()),r=t;}function k(n){var t=r;n.__c=n.__(),r=t;}function w(n,t){return !n||n.length!==t.length||t.some(function(t,r){return t!==n[r]})}function z(n,t){return "function"==typeof t?t(n):t}
5893
+ var t,r,u,i,o=0,f=[],c=l$1,e=c.__b,a=c.__r,v=c.diffed,l=c.__c,m=c.unmount,s=c.__;function p(n,t){c.__h&&c.__h(r,n,o||t),o=0;var u=r.__H||(r.__H={__:[],__h:[]});return n>=u.__.length&&u.__.push({}),u.__[n]}function d(n){return o=1,h(D,n)}function h(n,u,i){var o=p(t++,2);if(o.t=n,!o.__c&&(o.__=[D(void 0,u),function(n){var t=o.__N?o.__N[0]:o.__[0],r=o.t(t,n);t!==r&&(o.__N=[r,o.__[1]],o.__c.setState({}));}],o.__c=r,!r.__f)){var f=function(n,t,r){if(!o.__c.__H)return true;var u=o.__c.__H.__.filter(function(n){return !!n.__c});if(u.every(function(n){return !n.__N}))return !c||c.call(this,n,t,r);var i=o.__c.props!==n;return u.forEach(function(n){if(n.__N){var t=n.__[0];n.__=n.__N,n.__N=void 0,t!==n.__[0]&&(i=true);}}),c&&c.call(this,n,t,r)||i};r.__f=true;var c=r.shouldComponentUpdate,e=r.componentWillUpdate;r.componentWillUpdate=function(n,t,r){if(this.__e){var u=c;c=void 0,f(n,t,r),c=u;}e&&e.call(this,n,t,r);},r.shouldComponentUpdate=f;}return o.__N||o.__}function _(n,u){var i=p(t++,4);!c.__s&&C(i.__H,u)&&(i.__=n,i.u=u,r.__h.push(i));}function A(n){return o=5,T(function(){return {current:n}},[])}function T(n,r){var u=p(t++,7);return C(u.__H,r)&&(u.__=n(),u.__H=r,u.__h=n),u.__}function j(){for(var n;n=f.shift();)if(n.__P&&n.__H)try{n.__H.__h.forEach(z),n.__H.__h.forEach(B),n.__H.__h=[];}catch(t){n.__H.__h=[],c.__e(t,n.__v);}}c.__b=function(n){r=null,e&&e(n);},c.__=function(n,t){n&&t.__k&&t.__k.__m&&(n.__m=t.__k.__m),s&&s(n,t);},c.__r=function(n){a&&a(n),t=0;var i=(r=n.__c).__H;i&&(u===r?(i.__h=[],r.__h=[],i.__.forEach(function(n){n.__N&&(n.__=n.__N),n.u=n.__N=void 0;})):(i.__h.forEach(z),i.__h.forEach(B),i.__h=[],t=0)),u=r;},c.diffed=function(n){v&&v(n);var t=n.__c;t&&t.__H&&(t.__H.__h.length&&(1!==f.push(t)&&i===c.requestAnimationFrame||((i=c.requestAnimationFrame)||w)(j)),t.__H.__.forEach(function(n){n.u&&(n.__H=n.u),n.u=void 0;})),u=r=null;},c.__c=function(n,t){t.some(function(n){try{n.__h.forEach(z),n.__h=n.__h.filter(function(n){return !n.__||B(n)});}catch(r){t.some(function(n){n.__h&&(n.__h=[]);}),t=[],c.__e(r,n.__v);}}),l&&l(n,t);},c.unmount=function(n){m&&m(n);var t,r=n.__c;r&&r.__H&&(r.__H.__.forEach(function(n){try{z(n);}catch(n){t=n;}}),r.__H=void 0,t&&c.__e(t,r.__v));};var k="function"==typeof requestAnimationFrame;function w(n){var t,r=function(){clearTimeout(u),k&&cancelAnimationFrame(t),setTimeout(n);},u=setTimeout(r,35);k&&(t=requestAnimationFrame(r));}function z(n){var t=r,u=n.__c;"function"==typeof u&&(n.__c=void 0,u()),r=t;}function B(n){var t=r;n.__c=n.__(),r=t;}function C(n,t){return !n||n.length!==t.length||t.some(function(t,r){return t!==n[r]})}function D(n,t){return "function"==typeof t?t(n):t}
5424
5894
 
5425
5895
  /** Resolve a message template with parameters.
5426
5896
  *
@@ -5442,19 +5912,19 @@ function resolveText({ message, messageCode, messageParams }) {
5442
5912
 
5443
5913
  const OTP_LENGTH = 8;
5444
5914
  function LoginDialog({ title, type, alerts, fields, submitLabel, cancelLabel, onCancel, onSubmit, }) {
5445
- const [params, setParams] = p({});
5446
- const firstFieldRef = _(null);
5447
- s(() => { var _a; return (_a = firstFieldRef.current) === null || _a === void 0 ? void 0 : _a.focus(); }, []);
5448
- return (h(Dialog, { className: "dxc-login-dlg" },
5449
- h(p$1, null,
5450
- h("h3", { style: Styles.WindowHeader }, title),
5451
- alerts.map((alert) => (h("p", { style: Styles.Alert[alert.type] }, resolveText(alert)))),
5452
- h("form", { onSubmit: (ev) => {
5915
+ const [params, setParams] = d({});
5916
+ const firstFieldRef = A(null);
5917
+ _(() => { var _a; return (_a = firstFieldRef.current) === null || _a === void 0 ? void 0 : _a.focus(); }, []);
5918
+ return (_$1(Dialog, { className: "dxc-login-dlg" },
5919
+ _$1(k$1, null,
5920
+ _$1("h3", { style: Styles.WindowHeader }, title),
5921
+ alerts.map((alert) => (_$1("p", { style: Styles.Alert[alert.type] }, resolveText(alert)))),
5922
+ _$1("form", { onSubmit: (ev) => {
5453
5923
  ev.preventDefault();
5454
5924
  onSubmit(params);
5455
- } }, Object.entries(fields).map(([fieldName, { type, label, placeholder }], idx) => (h("label", { style: Styles.Label, key: idx },
5925
+ } }, Object.entries(fields).map(([fieldName, { type, label, placeholder }], idx) => (_$1("label", { style: Styles.Label, key: idx },
5456
5926
  label ? `${label}: ` : '',
5457
- h("input", { ref: idx === 0 ? firstFieldRef : undefined, type: type, name: fieldName, autoComplete: "on", style: Styles.Input, autoFocus: true, placeholder: placeholder, value: params[fieldName] || '', onInput: (ev) => {
5927
+ _$1("input", { ref: idx === 0 ? firstFieldRef : undefined, type: type, name: fieldName, autoComplete: "on", style: Styles.Input, autoFocus: true, placeholder: placeholder, value: params[fieldName] || '', onInput: (ev) => {
5458
5928
  var _a;
5459
5929
  const value = valueTransformer(type, (_a = ev.target) === null || _a === void 0 ? void 0 : _a['value']);
5460
5930
  let updatedParams = Object.assign(Object.assign({}, params), { [fieldName]: value });
@@ -5464,10 +5934,10 @@ function LoginDialog({ title, type, alerts, fields, submitLabel, cancelLabel, on
5464
5934
  onSubmit(updatedParams);
5465
5935
  }
5466
5936
  } })))))),
5467
- h("div", { style: Styles.ButtonsDiv },
5468
- h(p$1, null,
5469
- h("button", { type: "submit", style: Styles.PrimaryButton, onClick: () => onSubmit(params) }, submitLabel),
5470
- cancelLabel && (h("button", { style: Styles.Button, onClick: onCancel }, cancelLabel))))));
5937
+ _$1("div", { style: Styles.ButtonsDiv },
5938
+ _$1(k$1, null,
5939
+ _$1("button", { type: "submit", style: Styles.PrimaryButton, onClick: () => onSubmit(params) }, submitLabel),
5940
+ cancelLabel && (_$1("button", { style: Styles.Button, onClick: onCancel }, cancelLabel))))));
5471
5941
  }
5472
5942
  function valueTransformer(type, value) {
5473
5943
  switch (type) {
@@ -5480,7 +5950,83 @@ function valueTransformer(type, value) {
5480
5950
  }
5481
5951
  }
5482
5952
 
5483
- class LoginGui extends d$1 {
5953
+ /** Default SVG icons for built-in providers */
5954
+ const ProviderIcons = {
5955
+ google: `<svg viewBox="0 0 24 24" width="20" height="20"><path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"/><path fill="#34A853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/><path fill="#FBBC05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/><path fill="#EA4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/></svg>`,
5956
+ github: `<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor"><path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0024 12c0-6.63-5.37-12-12-12z"/></svg>`,
5957
+ microsoft: `<svg viewBox="0 0 24 24" width="20" height="20"><rect fill="#F25022" x="1" y="1" width="10" height="10"/><rect fill="#00A4EF" x="1" y="13" width="10" height="10"/><rect fill="#7FBA00" x="13" y="1" width="10" height="10"/><rect fill="#FFB900" x="13" y="13" width="10" height="10"/></svg>`,
5958
+ apple: `<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor"><path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.81-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z"/></svg>`,
5959
+ };
5960
+ /** Get provider-specific button styles */
5961
+ function getProviderStyle(providerType) {
5962
+ const baseStyle = Object.assign({}, Styles.ProviderButton);
5963
+ switch (providerType) {
5964
+ case 'google':
5965
+ return Object.assign(Object.assign({}, baseStyle), Styles.ProviderGoogle);
5966
+ case 'github':
5967
+ return Object.assign(Object.assign({}, baseStyle), Styles.ProviderGitHub);
5968
+ case 'microsoft':
5969
+ return Object.assign(Object.assign({}, baseStyle), Styles.ProviderMicrosoft);
5970
+ case 'apple':
5971
+ return Object.assign(Object.assign({}, baseStyle), Styles.ProviderApple);
5972
+ default:
5973
+ return Object.assign(Object.assign({}, baseStyle), Styles.ProviderCustom);
5974
+ }
5975
+ }
5976
+ /**
5977
+ * Button component for OAuth provider login.
5978
+ * Displays the provider's icon and name following provider branding guidelines.
5979
+ */
5980
+ function AuthProviderButton({ provider, onClick }) {
5981
+ const { type, name, displayName, iconUrl } = provider;
5982
+ const style = getProviderStyle(type);
5983
+ // Determine button text
5984
+ const buttonText = `Continue with ${displayName}`;
5985
+ // Get icon - use custom iconUrl if provided, otherwise use built-in SVG
5986
+ const iconSvg = ProviderIcons[type] || '';
5987
+ return (_$1("button", { type: "button", style: style, onClick: onClick, class: `dxc-provider-btn dxc-provider-${type}`, "aria-label": buttonText },
5988
+ iconUrl ? (_$1("img", { src: iconUrl, alt: "", style: Styles.ProviderButtonIcon, "aria-hidden": "true" })) : iconSvg ? (_$1("span", { style: Styles.ProviderButtonIcon, "aria-hidden": "true", dangerouslySetInnerHTML: { __html: iconSvg } })) : null,
5989
+ _$1("span", { style: Styles.ProviderButtonText }, buttonText)));
5990
+ }
5991
+ /** Email/envelope icon for OTP button */
5992
+ const EmailIcon = `<svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="M22 6L12 13 2 6"/></svg>`;
5993
+ /**
5994
+ * Button for email/OTP authentication option.
5995
+ */
5996
+ function OtpButton({ onClick }) {
5997
+ return (_$1("button", { type: "button", style: Styles.OtpButton, onClick: onClick, class: "dxc-otp-btn", "aria-label": "Continue with email" },
5998
+ _$1("span", { style: Styles.ProviderButtonIcon, "aria-hidden": "true", dangerouslySetInnerHTML: { __html: EmailIcon } }),
5999
+ _$1("span", { style: Styles.ProviderButtonText }, "Continue with email")));
6000
+ }
6001
+ /**
6002
+ * Visual divider with "or" text.
6003
+ */
6004
+ function Divider() {
6005
+ return (_$1("div", { style: Styles.Divider },
6006
+ _$1("div", { style: Styles.DividerLine }),
6007
+ _$1("span", { style: Styles.DividerText }, "or"),
6008
+ _$1("div", { style: Styles.DividerLine })));
6009
+ }
6010
+
6011
+ /**
6012
+ * Dialog component for OAuth provider selection.
6013
+ * Displays available OAuth providers as buttons and optionally an email/OTP option.
6014
+ */
6015
+ function ProviderSelectionDialog({ title, alerts, providers, otpEnabled, cancelLabel, onSelectProvider, onSelectOtp, onCancel, }) {
6016
+ return (_$1(Dialog, { className: "dxc-provider-selection-dlg" },
6017
+ _$1(k$1, null,
6018
+ _$1("h3", { style: Styles.WindowHeader }, title),
6019
+ alerts.map((alert, idx) => (_$1("p", { key: idx, style: Styles.Alert[alert.type] }, resolveText(alert)))),
6020
+ _$1("div", { class: "dxc-providers" }, providers.map((provider) => (_$1(AuthProviderButton, { key: provider.name, provider: provider, onClick: () => onSelectProvider(provider.name) })))),
6021
+ otpEnabled && providers.length > 0 && (_$1(k$1, null,
6022
+ _$1(Divider, null),
6023
+ _$1(OtpButton, { onClick: onSelectOtp }))),
6024
+ otpEnabled && providers.length === 0 && (_$1(OtpButton, { onClick: onSelectOtp })),
6025
+ cancelLabel && (_$1("div", { style: Styles.CancelButtonRow },
6026
+ _$1("button", { type: "button", style: Styles.Button, onClick: onCancel }, cancelLabel))))));
6027
+ }
6028
+
6029
+ class LoginGui extends x {
5484
6030
  constructor(props) {
5485
6031
  super(props);
5486
6032
  this.observer = (userInteraction) => this.setState({ userInteraction });
@@ -5498,8 +6044,12 @@ class LoginGui extends d$1 {
5498
6044
  render(props, { userInteraction }) {
5499
6045
  if (!userInteraction)
5500
6046
  return null;
5501
- //if (props.db.cloud.userInteraction.observers.length > 1) return null; // Someone else subscribes.
5502
- return h(LoginDialog, Object.assign({}, userInteraction));
6047
+ // Render appropriate dialog based on interaction type
6048
+ if (userInteraction.type === 'provider-selection') {
6049
+ return _$1(ProviderSelectionDialog, Object.assign({}, userInteraction));
6050
+ }
6051
+ // Default to LoginDialog for other interaction types
6052
+ return _$1(LoginDialog, Object.assign({}, userInteraction));
5503
6053
  }
5504
6054
  }
5505
6055
  function setupDefaultGUI(db) {
@@ -5507,13 +6057,13 @@ function setupDefaultGUI(db) {
5507
6057
  const el = document.createElement('div');
5508
6058
  if (document.body) {
5509
6059
  document.body.appendChild(el);
5510
- P(h(LoginGui, { db: db.vip }), el);
6060
+ G(_$1(LoginGui, { db: db.vip }), el);
5511
6061
  }
5512
6062
  else {
5513
6063
  addEventListener('DOMContentLoaded', () => {
5514
6064
  if (!closed) {
5515
6065
  document.body.appendChild(el);
5516
- P(h(LoginGui, { db: db.vip }), el);
6066
+ G(_$1(LoginGui, { db: db.vip }), el);
5517
6067
  }
5518
6068
  });
5519
6069
  }
@@ -6097,7 +6647,7 @@ function dexieCloud(dexie) {
6097
6647
  const syncComplete = new Subject();
6098
6648
  dexie.cloud = {
6099
6649
  // @ts-ignore
6100
- version: "4.2.4",
6650
+ version: "4.3.0",
6101
6651
  options: Object.assign({}, DEFAULT_OPTIONS),
6102
6652
  schema: null,
6103
6653
  get currentUserId() {
@@ -6414,7 +6964,7 @@ function dexieCloud(dexie) {
6414
6964
  }
6415
6965
  }
6416
6966
  // @ts-ignore
6417
- dexieCloud.version = "4.2.4";
6967
+ dexieCloud.version = "4.3.0";
6418
6968
  Dexie.Cloud = dexieCloud;
6419
6969
 
6420
6970
  // In case the SW lives for a while, let it reuse already opened connections: