@glideidentity/web-client-sdk 5.1.3 → 6.0.0-beta.2

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 (203) hide show
  1. package/README.md +337 -526
  2. package/dist/browser/web-client-sdk.min.js +1 -1
  3. package/dist/cjs/adapters/index.js +15 -0
  4. package/dist/cjs/adapters/react.js +192 -0
  5. package/dist/cjs/adapters/vanilla.js +38 -0
  6. package/dist/cjs/adapters/vue.js +187 -0
  7. package/dist/cjs/browser.js +58 -0
  8. package/dist/cjs/client/http.js +159 -0
  9. package/dist/cjs/client/index.js +19 -0
  10. package/dist/cjs/client/logger.js +135 -0
  11. package/dist/cjs/client/phone-auth-client.js +428 -0
  12. package/dist/cjs/client/strategies/polling.js +177 -0
  13. package/dist/cjs/core/errors.js +204 -0
  14. package/dist/cjs/core/index.js +83 -0
  15. package/dist/cjs/core/type-guards.js +196 -0
  16. package/dist/cjs/core/types.js +25 -0
  17. package/dist/{core/phone-auth/validation-utils.js → cjs/core/validators.js} +70 -23
  18. package/dist/cjs/index.js +81 -0
  19. package/dist/cjs/ui/index.js +11 -0
  20. package/dist/{core/phone-auth → cjs}/ui/mobile-debug-console.js +149 -78
  21. package/dist/cjs/ui/modal.js +1122 -0
  22. package/dist/esm/adapters/index.js +11 -0
  23. package/dist/esm/adapters/react.js +182 -0
  24. package/dist/esm/adapters/vanilla.js +29 -0
  25. package/dist/esm/adapters/vue.js +177 -0
  26. package/dist/esm/browser.js +30 -11
  27. package/dist/esm/client/http.js +156 -0
  28. package/dist/esm/client/index.js +11 -0
  29. package/dist/esm/client/logger.js +131 -0
  30. package/dist/esm/client/phone-auth-client.js +424 -0
  31. package/dist/esm/client/strategies/polling.js +174 -0
  32. package/dist/esm/core/errors.js +193 -0
  33. package/dist/esm/core/index.js +60 -0
  34. package/dist/esm/core/type-guards.js +181 -0
  35. package/dist/esm/core/types.js +22 -1
  36. package/dist/esm/core/{phone-auth/validation-utils.js → validators.js} +66 -21
  37. package/dist/esm/index.js +45 -17
  38. package/dist/esm/ui/index.js +5 -0
  39. package/dist/esm/{core/phone-auth/ui → ui}/mobile-debug-console.js +149 -78
  40. package/dist/esm/ui/modal.js +1117 -0
  41. package/dist/types/adapters/index.d.ts +10 -0
  42. package/dist/types/adapters/index.d.ts.map +1 -0
  43. package/dist/types/adapters/react.d.ts +70 -0
  44. package/dist/types/adapters/react.d.ts.map +1 -0
  45. package/dist/types/adapters/vanilla.d.ts +29 -0
  46. package/dist/types/adapters/vanilla.d.ts.map +1 -0
  47. package/dist/types/adapters/vue.d.ts +71 -0
  48. package/dist/types/adapters/vue.d.ts.map +1 -0
  49. package/dist/types/browser.d.ts +27 -0
  50. package/dist/types/browser.d.ts.map +1 -0
  51. package/dist/types/client/http.d.ts +41 -0
  52. package/dist/types/client/http.d.ts.map +1 -0
  53. package/dist/types/client/index.d.ts +10 -0
  54. package/dist/types/client/index.d.ts.map +1 -0
  55. package/dist/types/client/logger.d.ts +36 -0
  56. package/dist/types/client/logger.d.ts.map +1 -0
  57. package/dist/types/client/phone-auth-client.d.ts +91 -0
  58. package/dist/types/client/phone-auth-client.d.ts.map +1 -0
  59. package/dist/types/client/strategies/polling.d.ts +36 -0
  60. package/dist/types/client/strategies/polling.d.ts.map +1 -0
  61. package/dist/types/core/errors.d.ts +71 -0
  62. package/dist/types/core/errors.d.ts.map +1 -0
  63. package/dist/types/core/index.d.ts +38 -0
  64. package/dist/types/core/index.d.ts.map +1 -0
  65. package/dist/types/core/type-guards.d.ts +118 -0
  66. package/dist/types/core/type-guards.d.ts.map +1 -0
  67. package/dist/types/core/types.d.ts +535 -0
  68. package/dist/types/core/types.d.ts.map +1 -0
  69. package/dist/types/core/validators.d.ts +63 -0
  70. package/dist/types/core/validators.d.ts.map +1 -0
  71. package/dist/types/index.d.ts +40 -0
  72. package/dist/types/index.d.ts.map +1 -0
  73. package/dist/types/ui/index.d.ts +6 -0
  74. package/dist/types/ui/index.d.ts.map +1 -0
  75. package/dist/{esm/core/phone-auth → types}/ui/mobile-debug-console.d.ts +1 -0
  76. package/dist/types/ui/mobile-debug-console.d.ts.map +1 -0
  77. package/dist/types/ui/modal.d.ts +87 -0
  78. package/dist/types/ui/modal.d.ts.map +1 -0
  79. package/package.json +48 -34
  80. package/dist/adapters/angular/client.service.d.ts +0 -7
  81. package/dist/adapters/angular/client.service.js +0 -30
  82. package/dist/adapters/angular/index.d.ts +0 -3
  83. package/dist/adapters/angular/index.js +0 -18
  84. package/dist/adapters/angular/phone-auth.service.d.ts +0 -38
  85. package/dist/adapters/angular/phone-auth.service.js +0 -130
  86. package/dist/adapters/react/index.d.ts +0 -9
  87. package/dist/adapters/react/index.js +0 -28
  88. package/dist/adapters/react/useClient.d.ts +0 -26
  89. package/dist/adapters/react/useClient.js +0 -121
  90. package/dist/adapters/react/usePhoneAuth.d.ts +0 -23
  91. package/dist/adapters/react/usePhoneAuth.js +0 -95
  92. package/dist/adapters/vanilla/client.d.ts +0 -8
  93. package/dist/adapters/vanilla/client.js +0 -33
  94. package/dist/adapters/vanilla/index.d.ts +0 -3
  95. package/dist/adapters/vanilla/index.js +0 -18
  96. package/dist/adapters/vanilla/phone-auth.d.ts +0 -46
  97. package/dist/adapters/vanilla/phone-auth.js +0 -138
  98. package/dist/adapters/vue/index.d.ts +0 -10
  99. package/dist/adapters/vue/index.js +0 -36
  100. package/dist/adapters/vue/useClient.d.ts +0 -115
  101. package/dist/adapters/vue/useClient.js +0 -131
  102. package/dist/adapters/vue/usePhoneAuth.d.ts +0 -94
  103. package/dist/adapters/vue/usePhoneAuth.js +0 -103
  104. package/dist/browser.d.ts +0 -7
  105. package/dist/browser.js +0 -31
  106. package/dist/core/client.d.ts +0 -22
  107. package/dist/core/client.js +0 -77
  108. package/dist/core/logger.d.ts +0 -130
  109. package/dist/core/logger.js +0 -370
  110. package/dist/core/phone-auth/api-types.d.ts +0 -593
  111. package/dist/core/phone-auth/api-types.js +0 -215
  112. package/dist/core/phone-auth/client.d.ts +0 -189
  113. package/dist/core/phone-auth/client.js +0 -1441
  114. package/dist/core/phone-auth/error-utils.d.ts +0 -110
  115. package/dist/core/phone-auth/error-utils.js +0 -350
  116. package/dist/core/phone-auth/index.d.ts +0 -7
  117. package/dist/core/phone-auth/index.js +0 -50
  118. package/dist/core/phone-auth/status-types.d.ts +0 -107
  119. package/dist/core/phone-auth/status-types.js +0 -31
  120. package/dist/core/phone-auth/strategies/desktop.d.ts +0 -122
  121. package/dist/core/phone-auth/strategies/desktop.js +0 -596
  122. package/dist/core/phone-auth/strategies/index.d.ts +0 -11
  123. package/dist/core/phone-auth/strategies/index.js +0 -15
  124. package/dist/core/phone-auth/strategies/link.d.ts +0 -89
  125. package/dist/core/phone-auth/strategies/link.js +0 -384
  126. package/dist/core/phone-auth/strategies/ts43.d.ts +0 -32
  127. package/dist/core/phone-auth/strategies/ts43.js +0 -161
  128. package/dist/core/phone-auth/strategies/types.d.ts +0 -18
  129. package/dist/core/phone-auth/strategies/types.js +0 -6
  130. package/dist/core/phone-auth/type-guards.d.ts +0 -143
  131. package/dist/core/phone-auth/type-guards.js +0 -198
  132. package/dist/core/phone-auth/types.d.ts +0 -237
  133. package/dist/core/phone-auth/types.js +0 -93
  134. package/dist/core/phone-auth/ui/mobile-debug-console.d.ts +0 -25
  135. package/dist/core/phone-auth/ui/modal.d.ts +0 -88
  136. package/dist/core/phone-auth/ui/modal.js +0 -598
  137. package/dist/core/phone-auth/validation-utils.d.ts +0 -44
  138. package/dist/core/types.d.ts +0 -62
  139. package/dist/core/types.js +0 -2
  140. package/dist/core/version.d.ts +0 -1
  141. package/dist/core/version.js +0 -5
  142. package/dist/esm/adapters/angular/client.service.d.ts +0 -7
  143. package/dist/esm/adapters/angular/client.service.js +0 -27
  144. package/dist/esm/adapters/angular/index.d.ts +0 -3
  145. package/dist/esm/adapters/angular/index.js +0 -4
  146. package/dist/esm/adapters/angular/phone-auth.service.d.ts +0 -38
  147. package/dist/esm/adapters/angular/phone-auth.service.js +0 -127
  148. package/dist/esm/adapters/react/index.d.ts +0 -9
  149. package/dist/esm/adapters/react/index.js +0 -8
  150. package/dist/esm/adapters/react/useClient.d.ts +0 -26
  151. package/dist/esm/adapters/react/useClient.js +0 -116
  152. package/dist/esm/adapters/react/usePhoneAuth.d.ts +0 -23
  153. package/dist/esm/adapters/react/usePhoneAuth.js +0 -92
  154. package/dist/esm/adapters/vanilla/client.d.ts +0 -8
  155. package/dist/esm/adapters/vanilla/client.js +0 -29
  156. package/dist/esm/adapters/vanilla/index.d.ts +0 -3
  157. package/dist/esm/adapters/vanilla/index.js +0 -4
  158. package/dist/esm/adapters/vanilla/phone-auth.d.ts +0 -46
  159. package/dist/esm/adapters/vanilla/phone-auth.js +0 -134
  160. package/dist/esm/adapters/vue/index.d.ts +0 -10
  161. package/dist/esm/adapters/vue/index.js +0 -11
  162. package/dist/esm/adapters/vue/useClient.d.ts +0 -115
  163. package/dist/esm/adapters/vue/useClient.js +0 -127
  164. package/dist/esm/adapters/vue/usePhoneAuth.d.ts +0 -94
  165. package/dist/esm/adapters/vue/usePhoneAuth.js +0 -100
  166. package/dist/esm/browser.d.ts +0 -7
  167. package/dist/esm/core/client.d.ts +0 -22
  168. package/dist/esm/core/client.js +0 -70
  169. package/dist/esm/core/logger.d.ts +0 -130
  170. package/dist/esm/core/logger.js +0 -359
  171. package/dist/esm/core/phone-auth/api-types.d.ts +0 -593
  172. package/dist/esm/core/phone-auth/api-types.js +0 -203
  173. package/dist/esm/core/phone-auth/client.d.ts +0 -189
  174. package/dist/esm/core/phone-auth/client.js +0 -1404
  175. package/dist/esm/core/phone-auth/error-utils.d.ts +0 -110
  176. package/dist/esm/core/phone-auth/error-utils.js +0 -338
  177. package/dist/esm/core/phone-auth/index.d.ts +0 -7
  178. package/dist/esm/core/phone-auth/index.js +0 -8
  179. package/dist/esm/core/phone-auth/status-types.d.ts +0 -107
  180. package/dist/esm/core/phone-auth/status-types.js +0 -26
  181. package/dist/esm/core/phone-auth/strategies/desktop.d.ts +0 -122
  182. package/dist/esm/core/phone-auth/strategies/desktop.js +0 -590
  183. package/dist/esm/core/phone-auth/strategies/index.d.ts +0 -11
  184. package/dist/esm/core/phone-auth/strategies/index.js +0 -7
  185. package/dist/esm/core/phone-auth/strategies/link.d.ts +0 -89
  186. package/dist/esm/core/phone-auth/strategies/link.js +0 -380
  187. package/dist/esm/core/phone-auth/strategies/ts43.d.ts +0 -32
  188. package/dist/esm/core/phone-auth/strategies/ts43.js +0 -157
  189. package/dist/esm/core/phone-auth/strategies/types.d.ts +0 -18
  190. package/dist/esm/core/phone-auth/strategies/types.js +0 -5
  191. package/dist/esm/core/phone-auth/type-guards.d.ts +0 -143
  192. package/dist/esm/core/phone-auth/type-guards.js +0 -185
  193. package/dist/esm/core/phone-auth/types.d.ts +0 -237
  194. package/dist/esm/core/phone-auth/types.js +0 -76
  195. package/dist/esm/core/phone-auth/ui/modal.d.ts +0 -88
  196. package/dist/esm/core/phone-auth/ui/modal.js +0 -594
  197. package/dist/esm/core/phone-auth/validation-utils.d.ts +0 -44
  198. package/dist/esm/core/types.d.ts +0 -62
  199. package/dist/esm/core/version.d.ts +0 -1
  200. package/dist/esm/core/version.js +0 -2
  201. package/dist/esm/index.d.ts +0 -12
  202. package/dist/index.d.ts +0 -12
  203. package/dist/index.js +0 -55
@@ -1,18 +1,30 @@
1
1
  /**
2
- * Validation utilities for phone authentication
2
+ * Validation utilities for phone authentication.
3
+ *
4
+ * Pure functions with no runtime dependencies.
5
+ * All validators return { valid: boolean; error?: string }.
3
6
  */
4
- import { USE_CASE } from './api-types';
7
+ import { USE_CASE } from './types';
8
+ /** E.164 phone number regex */
9
+ export const E164_REGEX = /^\+[1-9]\d{1,14}$/;
5
10
  /**
6
- * Validates E.164 phone number format
11
+ * Validates E.164 phone number format.
12
+ *
7
13
  * @param phoneNumber - Phone number to validate
8
14
  * @returns Validation result with error if invalid
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * const result = validatePhoneNumber('+14155551234');
19
+ * if (!result.valid) {
20
+ * console.error(result.error);
21
+ * }
22
+ * ```
9
23
  */
10
24
  export function validatePhoneNumber(phoneNumber) {
11
25
  if (!phoneNumber) {
12
26
  return { valid: true }; // Phone number is optional for GetPhoneNumber
13
27
  }
14
- // E.164 format validation - strict, no cleaning
15
- const e164Regex = /^\+[1-9]\d{1,14}$/;
16
28
  if (!phoneNumber.startsWith('+')) {
17
29
  return {
18
30
  valid: false,
@@ -31,14 +43,14 @@ export function validatePhoneNumber(phoneNumber) {
31
43
  error: 'Phone number too long for E.164 format (maximum 15 digits after +)'
32
44
  };
33
45
  }
34
- // Check for any invalid characters (spaces, dashes, parentheses, etc.)
46
+ // Check for invalid characters (spaces, dashes, parentheses, etc.)
35
47
  if (!/^\+\d+$/.test(phoneNumber)) {
36
48
  return {
37
49
  valid: false,
38
50
  error: 'Phone number contains invalid characters. E.164 format only allows + followed by digits'
39
51
  };
40
52
  }
41
- if (!e164Regex.test(phoneNumber)) {
53
+ if (!E164_REGEX.test(phoneNumber)) {
42
54
  return {
43
55
  valid: false,
44
56
  error: 'Invalid E.164 phone number format'
@@ -47,7 +59,11 @@ export function validatePhoneNumber(phoneNumber) {
47
59
  return { valid: true };
48
60
  }
49
61
  /**
50
- * Validates PLMN (MCC/MNC) values
62
+ * Validates PLMN (MCC/MNC) values.
63
+ *
64
+ * @deprecated PLMN validation will be removed with PLMN support.
65
+ * TODO: Remove in next major version
66
+ *
51
67
  * @param plmn - PLMN object with MCC and MNC
52
68
  * @returns Validation result
53
69
  */
@@ -70,14 +86,14 @@ export function validatePlmn(plmn) {
70
86
  error: 'MNC must be 2 or 3 digits'
71
87
  };
72
88
  }
73
- // No range validation - allowing unofficial MCCs for telco labs
74
89
  return { valid: true };
75
90
  }
76
91
  /**
77
- * Validates use case and phone number combination
92
+ * Validates use case and required parameters combination.
93
+ *
78
94
  * @param useCase - The use case
79
95
  * @param phoneNumber - The phone number (required for VerifyPhoneNumber)
80
- * @param hasParentSessionId - Whether parent_session_id is provided (allows skipping normal validation)
96
+ * @param hasParentSessionId - Whether parent_session_id is provided
81
97
  * @returns Validation result
82
98
  */
83
99
  export function validateUseCaseRequirements(useCase, phoneNumber, hasParentSessionId) {
@@ -91,16 +107,45 @@ export function validateUseCaseRequirements(useCase, phoneNumber, hasParentSessi
91
107
  return { valid: true };
92
108
  }
93
109
  /**
94
- * Creates a validation error
95
- * @param code - Error code
96
- * @param message - Error message
97
- * @param field - Field that failed validation
110
+ * Validates nonce format.
111
+ *
112
+ * @param nonce - Nonce string to validate
113
+ * @returns Validation result
114
+ */
115
+ export function validateNonce(nonce) {
116
+ const base64urlRegex = /^[A-Za-z0-9_-]+$/;
117
+ if (!nonce || nonce.length === 0) {
118
+ return {
119
+ valid: false,
120
+ error: 'Nonce is required'
121
+ };
122
+ }
123
+ if (!base64urlRegex.test(nonce)) {
124
+ return {
125
+ valid: false,
126
+ error: 'Nonce must be base64url encoded'
127
+ };
128
+ }
129
+ if (nonce.length < 32 || nonce.length > 128) {
130
+ return {
131
+ valid: false,
132
+ error: 'Nonce must be between 32 and 128 characters'
133
+ };
134
+ }
135
+ return { valid: true };
136
+ }
137
+ /**
138
+ * Validates session key format.
139
+ *
140
+ * @param sessionKey - Session key to validate
141
+ * @returns Validation result
98
142
  */
99
- export function createValidationError(code, message, field) {
100
- const error = new Error(message);
101
- error.code = code;
102
- if (field) {
103
- error.field = field;
143
+ export function validateSessionKey(sessionKey) {
144
+ if (!sessionKey || sessionKey.length < 16) {
145
+ return {
146
+ valid: false,
147
+ error: 'Session key is required and must be at least 16 characters'
148
+ };
104
149
  }
105
- return error;
150
+ return { valid: true };
106
151
  }
package/dist/esm/index.js CHANGED
@@ -1,17 +1,45 @@
1
- // Phone Authentication
2
- export { PhoneAuthClient } from './core/phone-auth';
3
- // Phone Auth Error Utilities
4
- export { PhoneAuthErrorCode, isPhoneAuthError, isUserError, getUserMessage, isErrorCode, getRetryDelay, isRetryableError, serializeError, createErrorBreadcrumb } from './core/phone-auth';
5
- // Phone Auth Type Guards and Helpers
6
- export { isExtendedResponse, isCredential, isAuthCredential, isLinkStrategy, isTS43Strategy, isDesktopStrategy, getStrategy, hasPollingControls, hasTrigger,
7
- // Deprecated aliases
8
- isHeadlessResult, requiresPolling, requiresUserAction } from './core/phone-auth';
9
- // Export constants for use case and strategy
10
- export { USE_CASE as UseCase, AUTHENTICATION_STRATEGY as AuthenticationStrategy, BrowserError, BrowserErrorCode, BrowserName } from './core/phone-auth/types';
11
- // Desktop Strategy Exports
12
- export { DesktopHandler } from './core/phone-auth/strategies/desktop';
13
- // Adapters
14
- export { useClient, usePhoneAuth } from './adapters/react';
15
- export { useClient as useVueClient, usePhoneAuth as useVuePhoneAuth } from './adapters/vue';
16
- export { ClientService, PhoneAuthService } from './adapters/angular';
17
- export { ClientManager, PhoneAuthManager } from './adapters/vanilla';
1
+ /**
2
+ * Glide Phone Authentication SDK
3
+ *
4
+ * @example Basic Usage
5
+ * ```typescript
6
+ * import { PhoneAuthClient } from '@glideidentity/web-client-sdk';
7
+ *
8
+ * const client = new PhoneAuthClient({ debug: true });
9
+ * const result = await client.authenticate({
10
+ * use_case: 'VerifyPhoneNumber',
11
+ * phone_number: '+14155551234'
12
+ * });
13
+ * ```
14
+ *
15
+ * @example React
16
+ * ```typescript
17
+ * import { usePhoneAuth } from '@glideidentity/web-client-sdk/react';
18
+ * ```
19
+ *
20
+ * @example Vue
21
+ * ```typescript
22
+ * import { usePhoneAuth } from '@glideidentity/web-client-sdk/vue';
23
+ * ```
24
+ *
25
+ * @example Core Types Only
26
+ * ```typescript
27
+ * import type { PrepareRequest } from '@glideidentity/web-client-sdk/core';
28
+ * ```
29
+ */
30
+ // Main client
31
+ export { PhoneAuthClient } from './client/phone-auth-client';
32
+ // Constants
33
+ export { USE_CASE, AUTHENTICATION_STRATEGY } from './core/types';
34
+ // Error codes and utilities
35
+ export { ERROR_CODES } from './core/errors';
36
+ export { isAuthError, isClientError, isRetryableError, getUserMessage, createAuthError, parseBackendError, } from './core/errors';
37
+ // Type guards
38
+ export { isInvokeResult, isAuthCredential, isTS43Strategy, isLinkStrategy, isDesktopStrategy, isCancellable, isTS43Data, isLinkData, isDesktopData, isGetPhoneNumberResponse, isVerifyPhoneNumberResponse, isErrorResponse, } from './core/type-guards';
39
+ // Validators
40
+ export { validatePhoneNumber, validatePlmn, validateUseCaseRequirements, validateNonce, validateSessionKey, E164_REGEX, } from './core/validators';
41
+ // Client utilities (for advanced use)
42
+ export { createHttpClient } from './client/http';
43
+ export { createLogger, createNoopLogger } from './client/logger';
44
+ // UI components
45
+ export { AuthModal, createQRCodeDataFromDesktop } from './ui/modal';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * UI Components for Phone Authentication SDK
3
+ */
4
+ export { AuthModal, createQRCodeDataFromDesktop } from './modal';
5
+ export { MobileDebugConsole } from './mobile-debug-console';
@@ -50,24 +50,31 @@ export class MobileDebugConsole {
50
50
  try {
51
51
  return JSON.stringify(arg, null, 2);
52
52
  }
53
- catch (_a) {
53
+ catch {
54
54
  return '[Object]';
55
55
  }
56
56
  }
57
57
  return String(arg);
58
58
  }).join(' ');
59
- // Create colored log entry
59
+ // Color scheme for log types
60
60
  const colors = {
61
- log: '#fff',
62
- error: '#ff6b6b',
63
- warn: '#ffd93d',
64
- info: '#6bcf7f',
65
- debug: '#95a5a6'
61
+ log: '#abb2bf', // Light gray
62
+ error: '#e06c75', // Soft red
63
+ warn: '#e5c07b', // Yellow/gold
64
+ info: '#61afef', // Blue
65
+ debug: '#5c6370' // Dim gray
66
+ };
67
+ const badges = {
68
+ log: '#3c3c3c',
69
+ error: 'rgba(224, 108, 117, 0.2)',
70
+ warn: 'rgba(229, 192, 123, 0.2)',
71
+ info: 'rgba(97, 175, 239, 0.2)',
72
+ debug: '#2d2d2d'
66
73
  };
67
74
  const logHtml = `
68
- <div style="margin: 4px 0; font-family: monospace; font-size: 11px; color: ${colors[type] || '#fff'};">
69
- <span style="color: #666;">[${timestamp}]</span>
70
- <span style="color: ${colors[type]}; font-weight: bold; text-transform: uppercase; font-size: 9px;">[${type}]</span>
75
+ <div style="margin: 3px 0; font-family: 'SF Mono', Menlo, Monaco, monospace; font-size: 11px; color: ${colors[type] || '#abb2bf'}; line-height: 1.5;">
76
+ <span style="color: #5c6370; font-size: 10px;">${timestamp}</span>
77
+ <span style="background: ${badges[type]}; color: ${colors[type]}; padding: 1px 5px; border-radius: 3px; font-size: 9px; font-weight: 500; text-transform: uppercase; margin: 0 6px;">${type}</span>
71
78
  <span style="white-space: pre-wrap; word-break: break-all;">${this.escapeHtml(content)}</span>
72
79
  </div>
73
80
  `;
@@ -100,12 +107,14 @@ export class MobileDebugConsole {
100
107
  left: 0;
101
108
  right: 0;
102
109
  height: 45vh;
103
- background: rgba(0, 0, 0, 0.95);
110
+ background: #1e1e1e;
104
111
  z-index: 999999;
105
112
  display: flex;
106
113
  flex-direction: column;
107
- font-family: monospace;
108
- transition: transform 0.3s ease;
114
+ font-family: 'SF Mono', Menlo, Monaco, 'Courier New', monospace;
115
+ transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
116
+ border-top: 1px solid #3c3c3c;
117
+ box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.4);
109
118
  }
110
119
 
111
120
  #mobile-debug-console.hidden {
@@ -116,74 +125,136 @@ export class MobileDebugConsole {
116
125
  display: flex;
117
126
  justify-content: space-between;
118
127
  align-items: center;
119
- padding: 10px;
120
- background: #1a1a1a;
121
- border-top: 2px solid #333;
128
+ padding: 8px 12px;
129
+ background: #2d2d2d;
130
+ border-bottom: 1px solid #3c3c3c;
131
+ min-height: 36px;
122
132
  }
123
133
 
124
134
  #debug-title {
125
- color: #0f0;
135
+ display: flex;
136
+ align-items: center;
137
+ gap: 8px;
138
+ color: #9da5b4;
126
139
  font-size: 12px;
127
- font-weight: bold;
140
+ font-weight: 500;
141
+ letter-spacing: 0.3px;
142
+ }
143
+
144
+ #debug-title svg {
145
+ width: 14px;
146
+ height: 14px;
147
+ opacity: 0.8;
128
148
  }
129
149
 
130
- #debug-buttons {
150
+ /* Traffic light buttons - using ID for specificity */
151
+ #mobile-debug-console .debug-traffic-lights {
131
152
  display: flex;
132
- gap: 10px;
153
+ gap: 8px;
154
+ align-items: center;
133
155
  }
134
156
 
135
- #debug-buttons button {
136
- padding: 5px 10px;
137
- background: #333;
138
- color: #fff;
139
- border: 1px solid #555;
140
- border-radius: 3px;
141
- font-size: 11px;
157
+ #mobile-debug-console button.debug-traffic-btn {
158
+ width: 16px;
159
+ height: 16px;
160
+ min-width: 16px;
161
+ min-height: 16px;
162
+ border-radius: 50%;
163
+ border: none;
142
164
  cursor: pointer;
165
+ display: flex;
166
+ align-items: center;
167
+ justify-content: center;
168
+ padding: 0;
169
+ font-size: 0;
170
+ line-height: 1;
171
+ }
172
+
173
+ #mobile-debug-console .debug-traffic-btn svg {
174
+ width: 8px;
175
+ height: 8px;
176
+ }
177
+
178
+ #mobile-debug-console .debug-traffic-btn.close {
179
+ background: #ff5f57;
180
+ }
181
+
182
+ #mobile-debug-console .debug-traffic-btn.close svg {
183
+ stroke: #820005;
184
+ stroke-width: 2;
185
+ }
186
+
187
+ #mobile-debug-console .debug-traffic-btn.clear {
188
+ background: #febc2e;
143
189
  }
144
190
 
145
- #debug-buttons button:active {
146
- background: #555;
191
+ #mobile-debug-console .debug-traffic-btn.minimize {
192
+ background: #28c840;
193
+ }
194
+
195
+ #mobile-debug-console .debug-traffic-btn.minimize svg {
196
+ stroke: #006500;
197
+ stroke-width: 2;
198
+ }
199
+
200
+ #mobile-debug-console .debug-traffic-btn:active {
201
+ filter: brightness(0.85);
147
202
  }
148
203
 
149
204
  #debug-logs {
150
205
  flex: 1;
151
206
  overflow-y: auto;
152
- padding: 10px;
207
+ padding: 12px;
208
+ background: #1e1e1e;
153
209
  -webkit-overflow-scrolling: touch;
154
210
  }
155
211
 
156
- #debug-floating-toggle {
157
- position: fixed;
158
- bottom: 20px;
159
- right: 20px;
160
- width: 50px;
161
- height: 50px;
162
- border-radius: 50%;
163
- background: rgba(0, 0, 0, 0.8);
164
- border: 2px solid #0f0;
165
- color: #0f0;
166
- cursor: pointer;
167
- z-index: 999998;
212
+ button#debug-floating-toggle {
213
+ position: fixed !important;
214
+ bottom: 20px !important;
215
+ right: 20px !important;
216
+ width: 42px !important;
217
+ height: 42px !important;
218
+ min-width: 42px !important;
219
+ min-height: 42px !important;
220
+ border-radius: 8px !important;
221
+ background: #2d2d2d !important;
222
+ border: 1px solid #3c3c3c !important;
223
+ color: #9da5b4 !important;
224
+ cursor: pointer !important;
225
+ z-index: 999998 !important;
168
226
  display: none;
169
- align-items: center;
170
- justify-content: center;
171
- font-size: 24px;
172
- box-shadow: 0 2px 10px rgba(0, 255, 0, 0.3);
173
- transition: all 0.3s ease;
227
+ align-items: center !important;
228
+ justify-content: center !important;
229
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3) !important;
230
+ transition: all 0.2s ease !important;
231
+ padding: 0 !important;
232
+ margin: 0 !important;
174
233
  }
175
234
 
176
- #debug-floating-toggle:hover {
177
- background: rgba(0, 0, 0, 0.9);
178
- transform: scale(1.1);
179
- box-shadow: 0 4px 15px rgba(0, 255, 0, 0.5);
235
+ button#debug-floating-toggle:hover {
236
+ background: #3c3c3c !important;
237
+ color: #fff !important;
238
+ transform: translateY(-2px) !important;
239
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4) !important;
180
240
  }
181
241
 
182
- #debug-floating-toggle.visible {
183
- display: flex;
242
+ button#debug-floating-toggle:active {
243
+ transform: translateY(0) !important;
244
+ }
245
+
246
+ button#debug-floating-toggle.visible {
247
+ display: flex !important;
248
+ }
249
+
250
+ button#debug-floating-toggle svg {
251
+ width: 20px !important;
252
+ height: 20px !important;
184
253
  }
185
254
  `;
186
255
  document.head.appendChild(style);
256
+ // Terminal icon SVG (>_)
257
+ const terminalIcon = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"></polyline><line x1="12" y1="19" x2="20" y2="19"></line></svg>`;
187
258
  // Create container
188
259
  this.container = document.createElement('div');
189
260
  this.container.id = 'mobile-debug-console';
@@ -195,27 +266,33 @@ export class MobileDebugConsole {
195
266
  header.id = 'debug-header';
196
267
  const title = document.createElement('div');
197
268
  title.id = 'debug-title';
198
- title.textContent = '📱 Mobile Debug Console';
199
- const buttons = document.createElement('div');
200
- buttons.id = 'debug-buttons';
201
- // Clear button
269
+ title.innerHTML = `${terminalIcon}<span>Mobile Console</span>`;
270
+ // Traffic light control buttons
271
+ const trafficLights = document.createElement('div');
272
+ trafficLights.className = 'debug-traffic-lights';
273
+ // Close button (red) - ×
274
+ const closeBtn = document.createElement('button');
275
+ closeBtn.className = 'debug-traffic-btn close';
276
+ closeBtn.title = 'Close';
277
+ closeBtn.innerHTML = `<svg viewBox="0 0 10 10" fill="none"><line x1="2.5" y1="2.5" x2="7.5" y2="7.5" stroke="currentColor"/><line x1="7.5" y1="2.5" x2="2.5" y2="7.5" stroke="currentColor"/></svg>`;
278
+ closeBtn.onclick = () => this.cleanup();
279
+ // Clear button (yellow) - trash icon
202
280
  const clearBtn = document.createElement('button');
203
- clearBtn.textContent = 'Clear';
281
+ clearBtn.className = 'debug-traffic-btn clear';
282
+ clearBtn.title = 'Clear';
283
+ clearBtn.innerHTML = `<svg viewBox="0 0 16 16" fill="currentColor"><path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5m2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5m3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0z"/><path d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4zM2.5 3h11V2h-11z"/></svg>`;
204
284
  clearBtn.onclick = () => this.clear();
205
- // Show/Hide button
285
+ // Minimize button (green) - minimize to floating button
206
286
  const toggleBtn = document.createElement('button');
207
- toggleBtn.textContent = 'Hide';
287
+ toggleBtn.className = 'debug-traffic-btn minimize';
288
+ toggleBtn.title = 'Minimize';
289
+ toggleBtn.innerHTML = `<svg viewBox="0 0 10 10" fill="none"><path d="M2 3L5 6L8 3" stroke="currentColor" fill="none"/></svg>`;
208
290
  toggleBtn.onclick = () => this.toggle();
209
- // Close button
210
- const closeBtn = document.createElement('button');
211
- closeBtn.textContent = '✕';
212
- closeBtn.style.color = '#ff6b6b';
213
- closeBtn.onclick = () => this.cleanup();
214
- buttons.appendChild(clearBtn);
215
- buttons.appendChild(toggleBtn);
216
- buttons.appendChild(closeBtn);
291
+ trafficLights.appendChild(closeBtn);
292
+ trafficLights.appendChild(clearBtn);
293
+ trafficLights.appendChild(toggleBtn);
294
+ header.appendChild(trafficLights);
217
295
  header.appendChild(title);
218
- header.appendChild(buttons);
219
296
  // Create logs container
220
297
  this.logsContainer = document.createElement('div');
221
298
  this.logsContainer.id = 'debug-logs';
@@ -227,15 +304,13 @@ export class MobileDebugConsole {
227
304
  this.container.appendChild(header);
228
305
  this.container.appendChild(this.logsContainer);
229
306
  document.body.appendChild(this.container);
230
- // Create floating toggle button
307
+ // Create floating toggle button with terminal icon
231
308
  this.floatingToggle = document.createElement('button');
232
309
  this.floatingToggle.id = 'debug-floating-toggle';
233
- this.floatingToggle.innerHTML = '🖥️'; // Console icon
234
- this.floatingToggle.title = 'Show Debug Console';
310
+ this.floatingToggle.innerHTML = terminalIcon;
311
+ this.floatingToggle.title = 'Show Console';
235
312
  this.floatingToggle.onclick = () => this.toggle();
236
313
  document.body.appendChild(this.floatingToggle);
237
- // Store reference for toggle button
238
- window.__debugToggleBtn = toggleBtn;
239
314
  }
240
315
  escapeHtml(text) {
241
316
  const div = document.createElement('div');
@@ -248,13 +323,11 @@ export class MobileDebugConsole {
248
323
  if (this.isVisible) {
249
324
  this.container.classList.remove('hidden');
250
325
  this.floatingToggle.classList.remove('visible');
251
- window.__debugToggleBtn.textContent = 'Hide';
252
326
  this.updateDisplay();
253
327
  }
254
328
  else {
255
329
  this.container.classList.add('hidden');
256
330
  this.floatingToggle.classList.add('visible');
257
- window.__debugToggleBtn.textContent = 'Show';
258
331
  }
259
332
  }
260
333
  }
@@ -277,8 +350,6 @@ export class MobileDebugConsole {
277
350
  if (this.floatingToggle) {
278
351
  this.floatingToggle.remove();
279
352
  }
280
- // Clean up references
281
- delete window.__debugToggleBtn;
282
353
  }
283
354
  }
284
355
  MobileDebugConsole.instance = null;