@spektre/veil 0.1.6 → 0.1.7
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.
- package/dist/SecurityGate.d.ts +5 -0
- package/dist/devUI.d.ts +7 -0
- package/dist/index.esm.js +407 -0
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +407 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/SecurityGate.d.ts
CHANGED
package/dist/devUI.d.ts
ADDED
package/dist/index.esm.js
CHANGED
|
@@ -1,5 +1,397 @@
|
|
|
1
1
|
import React, { createContext, useState, useEffect, useContext } from 'react';
|
|
2
2
|
|
|
3
|
+
const DEV_UI_STORAGE_KEY = 'spektre_dev_enabled';
|
|
4
|
+
// Inject styles directly into the document
|
|
5
|
+
function injectDevUIStyles() {
|
|
6
|
+
if (document.getElementById('spektre-dev-ui-styles')) {
|
|
7
|
+
return; // Already injected
|
|
8
|
+
}
|
|
9
|
+
const styleSheet = document.createElement('style');
|
|
10
|
+
styleSheet.id = 'spektre-dev-ui-styles';
|
|
11
|
+
styleSheet.textContent = `
|
|
12
|
+
/* Spektre Dev UI Dot */
|
|
13
|
+
.spektre-dev-dot {
|
|
14
|
+
position: fixed;
|
|
15
|
+
bottom: 24px;
|
|
16
|
+
right: 24px;
|
|
17
|
+
width: 16px;
|
|
18
|
+
height: 16px;
|
|
19
|
+
background-color: #f97316;
|
|
20
|
+
border-radius: 50%;
|
|
21
|
+
cursor: pointer;
|
|
22
|
+
z-index: 9998;
|
|
23
|
+
box-shadow: 0 4px 12px rgba(249, 115, 22, 0.4);
|
|
24
|
+
transition: all 0.2s ease;
|
|
25
|
+
outline: none;
|
|
26
|
+
border: none;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.spektre-dev-dot:hover {
|
|
30
|
+
width: 20px;
|
|
31
|
+
height: 20px;
|
|
32
|
+
bottom: 22px;
|
|
33
|
+
right: 22px;
|
|
34
|
+
box-shadow: 0 6px 16px rgba(249, 115, 22, 0.6);
|
|
35
|
+
transform: scale(1.1);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.spektre-dev-dot.disabled {
|
|
39
|
+
background-color: #64748b;
|
|
40
|
+
box-shadow: 0 4px 12px rgba(100, 116, 139, 0.4);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.spektre-dev-dot.disabled:hover {
|
|
44
|
+
box-shadow: 0 6px 16px rgba(100, 116, 139, 0.6);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* Modal Overlay */
|
|
48
|
+
.spektre-dev-modal-overlay {
|
|
49
|
+
position: fixed;
|
|
50
|
+
top: 0;
|
|
51
|
+
left: 0;
|
|
52
|
+
right: 0;
|
|
53
|
+
bottom: 0;
|
|
54
|
+
background-color: rgba(0, 0, 0, 0.7);
|
|
55
|
+
display: flex;
|
|
56
|
+
align-items: center;
|
|
57
|
+
justify-content: center;
|
|
58
|
+
z-index: 9999;
|
|
59
|
+
animation: spektre-fade-in 0.2s ease;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@keyframes spektre-fade-in {
|
|
63
|
+
from {
|
|
64
|
+
opacity: 0;
|
|
65
|
+
}
|
|
66
|
+
to {
|
|
67
|
+
opacity: 1;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* Modal Container */
|
|
72
|
+
.spektre-dev-modal {
|
|
73
|
+
background-color: #000000;
|
|
74
|
+
border: 1px solid #1e293b;
|
|
75
|
+
border-radius: 12px;
|
|
76
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.8);
|
|
77
|
+
width: 90%;
|
|
78
|
+
max-width: 400px;
|
|
79
|
+
overflow: hidden;
|
|
80
|
+
animation: spektre-slide-up 0.3s ease;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@keyframes spektre-slide-up {
|
|
84
|
+
from {
|
|
85
|
+
transform: translateY(20px);
|
|
86
|
+
opacity: 0;
|
|
87
|
+
}
|
|
88
|
+
to {
|
|
89
|
+
transform: translateY(0);
|
|
90
|
+
opacity: 1;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* Modal Header */
|
|
95
|
+
.spektre-dev-modal-header {
|
|
96
|
+
display: flex;
|
|
97
|
+
justify-content: space-between;
|
|
98
|
+
align-items: center;
|
|
99
|
+
padding: 20px;
|
|
100
|
+
border-bottom: 1px solid #1e293b;
|
|
101
|
+
background: linear-gradient(135deg, rgba(249, 115, 22, 0.1) 0%, rgba(0, 0, 0, 0.5) 100%);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.spektre-dev-modal-header h2 {
|
|
105
|
+
margin: 0;
|
|
106
|
+
font-size: 18px;
|
|
107
|
+
font-weight: 600;
|
|
108
|
+
color: #ffffff;
|
|
109
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.spektre-dev-modal-close {
|
|
113
|
+
background: none;
|
|
114
|
+
border: none;
|
|
115
|
+
color: #94a3b8;
|
|
116
|
+
font-size: 24px;
|
|
117
|
+
cursor: pointer;
|
|
118
|
+
padding: 0;
|
|
119
|
+
width: 28px;
|
|
120
|
+
height: 28px;
|
|
121
|
+
display: flex;
|
|
122
|
+
align-items: center;
|
|
123
|
+
justify-content: center;
|
|
124
|
+
transition: color 0.2s ease;
|
|
125
|
+
border-radius: 4px;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.spektre-dev-modal-close:hover {
|
|
129
|
+
color: #f97316;
|
|
130
|
+
background-color: rgba(249, 115, 22, 0.1);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/* Modal Body */
|
|
134
|
+
.spektre-dev-modal-body {
|
|
135
|
+
padding: 24px;
|
|
136
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.spektre-dev-modal-info {
|
|
140
|
+
margin: 0 0 16px 0;
|
|
141
|
+
font-size: 14px;
|
|
142
|
+
color: #cbd5e1;
|
|
143
|
+
line-height: 1.5;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/* Status Badge */
|
|
147
|
+
.spektre-dev-modal-status {
|
|
148
|
+
display: inline-block;
|
|
149
|
+
padding: 8px 12px;
|
|
150
|
+
border-radius: 6px;
|
|
151
|
+
font-size: 14px;
|
|
152
|
+
font-weight: 500;
|
|
153
|
+
margin-bottom: 20px;
|
|
154
|
+
font-family: monospace;
|
|
155
|
+
transition: all 0.2s ease;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.spektre-dev-modal-status.enabled {
|
|
159
|
+
background-color: rgba(34, 197, 94, 0.15);
|
|
160
|
+
color: #86efac;
|
|
161
|
+
border: 1px solid rgba(34, 197, 94, 0.3);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.spektre-dev-modal-status.disabled {
|
|
165
|
+
background-color: rgba(100, 116, 139, 0.15);
|
|
166
|
+
color: #cbd5e1;
|
|
167
|
+
border: 1px solid rgba(100, 116, 139, 0.3);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/* Toggle Container */
|
|
171
|
+
.spektre-dev-modal-toggle-container {
|
|
172
|
+
display: flex;
|
|
173
|
+
align-items: center;
|
|
174
|
+
margin-bottom: 16px;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.spektre-dev-toggle-label {
|
|
178
|
+
display: flex;
|
|
179
|
+
align-items: center;
|
|
180
|
+
gap: 12px;
|
|
181
|
+
cursor: pointer;
|
|
182
|
+
font-size: 14px;
|
|
183
|
+
color: #e2e8f0;
|
|
184
|
+
user-select: none;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/* Toggle Switch */
|
|
188
|
+
.spektre-dev-toggle {
|
|
189
|
+
appearance: none;
|
|
190
|
+
-webkit-appearance: none;
|
|
191
|
+
width: 44px;
|
|
192
|
+
height: 24px;
|
|
193
|
+
background-color: #1e293b;
|
|
194
|
+
border: 1px solid #334155;
|
|
195
|
+
border-radius: 12px;
|
|
196
|
+
cursor: pointer;
|
|
197
|
+
position: relative;
|
|
198
|
+
transition: all 0.3s ease;
|
|
199
|
+
padding: 2px;
|
|
200
|
+
flex-shrink: 0;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.spektre-dev-toggle:checked {
|
|
204
|
+
background-color: #f97316;
|
|
205
|
+
border-color: #f97316;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.spektre-dev-toggle::before {
|
|
209
|
+
content: '';
|
|
210
|
+
position: absolute;
|
|
211
|
+
width: 18px;
|
|
212
|
+
height: 18px;
|
|
213
|
+
background-color: white;
|
|
214
|
+
border-radius: 10px;
|
|
215
|
+
top: 3px;
|
|
216
|
+
left: 3px;
|
|
217
|
+
transition: left 0.3s ease;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.spektre-dev-toggle:checked::before {
|
|
221
|
+
left: 23px;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.spektre-dev-toggle:focus {
|
|
225
|
+
outline: none;
|
|
226
|
+
box-shadow: 0 0 0 3px rgba(249, 115, 22, 0.2);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/* Reload Message */
|
|
230
|
+
.spektre-dev-modal-reload-msg {
|
|
231
|
+
margin: 0;
|
|
232
|
+
padding: 12px;
|
|
233
|
+
background-color: rgba(249, 115, 22, 0.15);
|
|
234
|
+
border: 1px solid rgba(249, 115, 22, 0.3);
|
|
235
|
+
border-radius: 6px;
|
|
236
|
+
font-size: 13px;
|
|
237
|
+
color: #fed7aa;
|
|
238
|
+
text-align: center;
|
|
239
|
+
transition: opacity 0.2s ease;
|
|
240
|
+
font-weight: 500;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/* Accessibility */
|
|
244
|
+
@media (prefers-reduced-motion: reduce) {
|
|
245
|
+
.spektre-dev-dot,
|
|
246
|
+
.spektre-dev-modal-overlay,
|
|
247
|
+
.spektre-dev-modal,
|
|
248
|
+
.spektre-dev-toggle,
|
|
249
|
+
.spektre-dev-toggle::before {
|
|
250
|
+
animation: none;
|
|
251
|
+
transition: none;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/* Mobile responsiveness */
|
|
256
|
+
@media (max-width: 480px) {
|
|
257
|
+
.spektre-dev-dot {
|
|
258
|
+
bottom: 16px;
|
|
259
|
+
right: 16px;
|
|
260
|
+
width: 14px;
|
|
261
|
+
height: 14px;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.spektre-dev-dot:hover {
|
|
265
|
+
width: 18px;
|
|
266
|
+
height: 18px;
|
|
267
|
+
bottom: 14px;
|
|
268
|
+
right: 14px;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.spektre-dev-modal {
|
|
272
|
+
width: 85%;
|
|
273
|
+
max-width: 320px;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.spektre-dev-modal-header h2 {
|
|
277
|
+
font-size: 16px;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.spektre-dev-modal-body {
|
|
281
|
+
padding: 16px;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
`;
|
|
285
|
+
document.head.appendChild(styleSheet);
|
|
286
|
+
}
|
|
287
|
+
function initializeDevUI() {
|
|
288
|
+
// Inject styles first
|
|
289
|
+
injectDevUIStyles();
|
|
290
|
+
// Check if Spektre is enabled in localStorage (default to true)
|
|
291
|
+
const isEnabled = localStorage.getItem(DEV_UI_STORAGE_KEY);
|
|
292
|
+
const spektreEnabled = isEnabled === null ? true : isEnabled === 'true';
|
|
293
|
+
// If disabled, prevent core Spektre from initializing
|
|
294
|
+
if (!spektreEnabled) {
|
|
295
|
+
window.__spektreDevDisabled = true;
|
|
296
|
+
}
|
|
297
|
+
// Create and inject the orange dot
|
|
298
|
+
createDevDot();
|
|
299
|
+
}
|
|
300
|
+
function createDevDot() {
|
|
301
|
+
const dot = document.createElement('div');
|
|
302
|
+
dot.id = 'spektre-dev-dot';
|
|
303
|
+
dot.className = 'spektre-dev-dot';
|
|
304
|
+
dot.setAttribute('aria-label', 'Spektre development environment controls');
|
|
305
|
+
dot.addEventListener('click', () => {
|
|
306
|
+
openDevModal();
|
|
307
|
+
});
|
|
308
|
+
document.body.appendChild(dot);
|
|
309
|
+
}
|
|
310
|
+
function openDevModal() {
|
|
311
|
+
// Check if modal already exists
|
|
312
|
+
if (document.getElementById('spektre-dev-modal')) {
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
const isEnabled = localStorage.getItem(DEV_UI_STORAGE_KEY) !== 'false';
|
|
316
|
+
const modal = document.createElement('div');
|
|
317
|
+
modal.id = 'spektre-dev-modal';
|
|
318
|
+
modal.className = 'spektre-dev-modal-overlay';
|
|
319
|
+
const modalContent = document.createElement('div');
|
|
320
|
+
modalContent.className = 'spektre-dev-modal';
|
|
321
|
+
const header = document.createElement('div');
|
|
322
|
+
header.className = 'spektre-dev-modal-header';
|
|
323
|
+
header.innerHTML = '<h2>Spektre Development Mode</h2>';
|
|
324
|
+
const closeButton = document.createElement('button');
|
|
325
|
+
closeButton.className = 'spektre-dev-modal-close';
|
|
326
|
+
closeButton.innerHTML = '✕';
|
|
327
|
+
closeButton.setAttribute('aria-label', 'Close modal');
|
|
328
|
+
closeButton.addEventListener('click', () => {
|
|
329
|
+
modal.remove();
|
|
330
|
+
});
|
|
331
|
+
header.appendChild(closeButton);
|
|
332
|
+
const body = document.createElement('div');
|
|
333
|
+
body.className = 'spektre-dev-modal-body';
|
|
334
|
+
const infoText = document.createElement('p');
|
|
335
|
+
infoText.className = 'spektre-dev-modal-info';
|
|
336
|
+
infoText.textContent = 'You are in a development environment. Spektre is currently:';
|
|
337
|
+
const statusBadge = document.createElement('div');
|
|
338
|
+
statusBadge.className = `spektre-dev-modal-status ${isEnabled ? 'enabled' : 'disabled'}`;
|
|
339
|
+
statusBadge.textContent = isEnabled ? '● Enabled' : '● Disabled';
|
|
340
|
+
const toggleContainer = document.createElement('div');
|
|
341
|
+
toggleContainer.className = 'spektre-dev-modal-toggle-container';
|
|
342
|
+
const toggleLabel = document.createElement('label');
|
|
343
|
+
toggleLabel.className = 'spektre-dev-toggle-label';
|
|
344
|
+
const toggleSwitch = document.createElement('input');
|
|
345
|
+
toggleSwitch.type = 'checkbox';
|
|
346
|
+
toggleSwitch.className = 'spektre-dev-toggle';
|
|
347
|
+
toggleSwitch.checked = isEnabled;
|
|
348
|
+
toggleSwitch.setAttribute('aria-label', 'Toggle Spektre');
|
|
349
|
+
toggleSwitch.addEventListener('change', (e) => {
|
|
350
|
+
const enabled = e.target.checked;
|
|
351
|
+
localStorage.setItem(DEV_UI_STORAGE_KEY, String(enabled));
|
|
352
|
+
// Update status badge
|
|
353
|
+
statusBadge.className = `spektre-dev-modal-status ${enabled ? 'enabled' : 'disabled'}`;
|
|
354
|
+
statusBadge.textContent = enabled ? '● Enabled' : '● Disabled';
|
|
355
|
+
// Update dot visual
|
|
356
|
+
const dot = document.getElementById('spektre-dev-dot');
|
|
357
|
+
if (dot) {
|
|
358
|
+
dot.classList.toggle('disabled', !enabled);
|
|
359
|
+
}
|
|
360
|
+
// Show reload message
|
|
361
|
+
const reloadMsg = document.querySelector('.spektre-dev-modal-reload-msg');
|
|
362
|
+
if (reloadMsg) {
|
|
363
|
+
reloadMsg.textContent = 'Reload the page for changes to take effect';
|
|
364
|
+
reloadMsg.style.opacity = '1';
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
toggleLabel.appendChild(toggleSwitch);
|
|
368
|
+
toggleLabel.appendChild(document.createTextNode('Enable Spektre'));
|
|
369
|
+
toggleContainer.appendChild(toggleLabel);
|
|
370
|
+
const reloadMessage = document.createElement('p');
|
|
371
|
+
reloadMessage.className = 'spektre-dev-modal-reload-msg';
|
|
372
|
+
reloadMessage.style.opacity = '0';
|
|
373
|
+
body.appendChild(infoText);
|
|
374
|
+
body.appendChild(statusBadge);
|
|
375
|
+
body.appendChild(toggleContainer);
|
|
376
|
+
body.appendChild(reloadMessage);
|
|
377
|
+
modalContent.appendChild(header);
|
|
378
|
+
modalContent.appendChild(body);
|
|
379
|
+
modal.appendChild(modalContent);
|
|
380
|
+
// Close on overlay click
|
|
381
|
+
modal.addEventListener('click', (e) => {
|
|
382
|
+
if (e.target === modal) {
|
|
383
|
+
modal.remove();
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
// Close on escape key
|
|
387
|
+
document.addEventListener('keydown', (e) => {
|
|
388
|
+
if (e.key === 'Escape' && document.getElementById('spektre-dev-modal')) {
|
|
389
|
+
modal.remove();
|
|
390
|
+
}
|
|
391
|
+
}, { once: true });
|
|
392
|
+
document.body.appendChild(modal);
|
|
393
|
+
}
|
|
394
|
+
|
|
3
395
|
const SpektreContext = createContext(null);
|
|
4
396
|
SpektreContext.displayName = 'SpektreContext';
|
|
5
397
|
|
|
@@ -16,6 +408,16 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
|
|
|
16
408
|
sessionId: null,
|
|
17
409
|
});
|
|
18
410
|
useEffect(() => {
|
|
411
|
+
// Check if Spektre is disabled in dev mode
|
|
412
|
+
if (window.__spektreDevDisabled) {
|
|
413
|
+
setState({
|
|
414
|
+
isVerified: true,
|
|
415
|
+
isLoading: false,
|
|
416
|
+
error: null,
|
|
417
|
+
sessionId: 'dev-disabled',
|
|
418
|
+
});
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
19
421
|
// Set tampering detection marker
|
|
20
422
|
sessionStorage.setItem('spektre_js_enabled', 'true');
|
|
21
423
|
sessionStorage.setItem('spektre_init_time', Date.now().toString());
|
|
@@ -430,5 +832,10 @@ const useProtectedFetch = () => {
|
|
|
430
832
|
return protectedFetch;
|
|
431
833
|
};
|
|
432
834
|
|
|
835
|
+
// Check if we're in an iframe (development environment) and initialize dev UI
|
|
836
|
+
if (typeof window !== 'undefined' && window.self !== window.top) {
|
|
837
|
+
initializeDevUI();
|
|
838
|
+
}
|
|
839
|
+
|
|
433
840
|
export { SecurityGate, SpektreContext, SpektreProvider, useProtectedFetch, useSpektre };
|
|
434
841
|
//# sourceMappingURL=index.esm.js.map
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,398 @@
|
|
|
2
2
|
|
|
3
3
|
var React = require('react');
|
|
4
4
|
|
|
5
|
+
const DEV_UI_STORAGE_KEY = 'spektre_dev_enabled';
|
|
6
|
+
// Inject styles directly into the document
|
|
7
|
+
function injectDevUIStyles() {
|
|
8
|
+
if (document.getElementById('spektre-dev-ui-styles')) {
|
|
9
|
+
return; // Already injected
|
|
10
|
+
}
|
|
11
|
+
const styleSheet = document.createElement('style');
|
|
12
|
+
styleSheet.id = 'spektre-dev-ui-styles';
|
|
13
|
+
styleSheet.textContent = `
|
|
14
|
+
/* Spektre Dev UI Dot */
|
|
15
|
+
.spektre-dev-dot {
|
|
16
|
+
position: fixed;
|
|
17
|
+
bottom: 24px;
|
|
18
|
+
right: 24px;
|
|
19
|
+
width: 16px;
|
|
20
|
+
height: 16px;
|
|
21
|
+
background-color: #f97316;
|
|
22
|
+
border-radius: 50%;
|
|
23
|
+
cursor: pointer;
|
|
24
|
+
z-index: 9998;
|
|
25
|
+
box-shadow: 0 4px 12px rgba(249, 115, 22, 0.4);
|
|
26
|
+
transition: all 0.2s ease;
|
|
27
|
+
outline: none;
|
|
28
|
+
border: none;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.spektre-dev-dot:hover {
|
|
32
|
+
width: 20px;
|
|
33
|
+
height: 20px;
|
|
34
|
+
bottom: 22px;
|
|
35
|
+
right: 22px;
|
|
36
|
+
box-shadow: 0 6px 16px rgba(249, 115, 22, 0.6);
|
|
37
|
+
transform: scale(1.1);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.spektre-dev-dot.disabled {
|
|
41
|
+
background-color: #64748b;
|
|
42
|
+
box-shadow: 0 4px 12px rgba(100, 116, 139, 0.4);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.spektre-dev-dot.disabled:hover {
|
|
46
|
+
box-shadow: 0 6px 16px rgba(100, 116, 139, 0.6);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* Modal Overlay */
|
|
50
|
+
.spektre-dev-modal-overlay {
|
|
51
|
+
position: fixed;
|
|
52
|
+
top: 0;
|
|
53
|
+
left: 0;
|
|
54
|
+
right: 0;
|
|
55
|
+
bottom: 0;
|
|
56
|
+
background-color: rgba(0, 0, 0, 0.7);
|
|
57
|
+
display: flex;
|
|
58
|
+
align-items: center;
|
|
59
|
+
justify-content: center;
|
|
60
|
+
z-index: 9999;
|
|
61
|
+
animation: spektre-fade-in 0.2s ease;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@keyframes spektre-fade-in {
|
|
65
|
+
from {
|
|
66
|
+
opacity: 0;
|
|
67
|
+
}
|
|
68
|
+
to {
|
|
69
|
+
opacity: 1;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* Modal Container */
|
|
74
|
+
.spektre-dev-modal {
|
|
75
|
+
background-color: #000000;
|
|
76
|
+
border: 1px solid #1e293b;
|
|
77
|
+
border-radius: 12px;
|
|
78
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.8);
|
|
79
|
+
width: 90%;
|
|
80
|
+
max-width: 400px;
|
|
81
|
+
overflow: hidden;
|
|
82
|
+
animation: spektre-slide-up 0.3s ease;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@keyframes spektre-slide-up {
|
|
86
|
+
from {
|
|
87
|
+
transform: translateY(20px);
|
|
88
|
+
opacity: 0;
|
|
89
|
+
}
|
|
90
|
+
to {
|
|
91
|
+
transform: translateY(0);
|
|
92
|
+
opacity: 1;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* Modal Header */
|
|
97
|
+
.spektre-dev-modal-header {
|
|
98
|
+
display: flex;
|
|
99
|
+
justify-content: space-between;
|
|
100
|
+
align-items: center;
|
|
101
|
+
padding: 20px;
|
|
102
|
+
border-bottom: 1px solid #1e293b;
|
|
103
|
+
background: linear-gradient(135deg, rgba(249, 115, 22, 0.1) 0%, rgba(0, 0, 0, 0.5) 100%);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.spektre-dev-modal-header h2 {
|
|
107
|
+
margin: 0;
|
|
108
|
+
font-size: 18px;
|
|
109
|
+
font-weight: 600;
|
|
110
|
+
color: #ffffff;
|
|
111
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.spektre-dev-modal-close {
|
|
115
|
+
background: none;
|
|
116
|
+
border: none;
|
|
117
|
+
color: #94a3b8;
|
|
118
|
+
font-size: 24px;
|
|
119
|
+
cursor: pointer;
|
|
120
|
+
padding: 0;
|
|
121
|
+
width: 28px;
|
|
122
|
+
height: 28px;
|
|
123
|
+
display: flex;
|
|
124
|
+
align-items: center;
|
|
125
|
+
justify-content: center;
|
|
126
|
+
transition: color 0.2s ease;
|
|
127
|
+
border-radius: 4px;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.spektre-dev-modal-close:hover {
|
|
131
|
+
color: #f97316;
|
|
132
|
+
background-color: rgba(249, 115, 22, 0.1);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* Modal Body */
|
|
136
|
+
.spektre-dev-modal-body {
|
|
137
|
+
padding: 24px;
|
|
138
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.spektre-dev-modal-info {
|
|
142
|
+
margin: 0 0 16px 0;
|
|
143
|
+
font-size: 14px;
|
|
144
|
+
color: #cbd5e1;
|
|
145
|
+
line-height: 1.5;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/* Status Badge */
|
|
149
|
+
.spektre-dev-modal-status {
|
|
150
|
+
display: inline-block;
|
|
151
|
+
padding: 8px 12px;
|
|
152
|
+
border-radius: 6px;
|
|
153
|
+
font-size: 14px;
|
|
154
|
+
font-weight: 500;
|
|
155
|
+
margin-bottom: 20px;
|
|
156
|
+
font-family: monospace;
|
|
157
|
+
transition: all 0.2s ease;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.spektre-dev-modal-status.enabled {
|
|
161
|
+
background-color: rgba(34, 197, 94, 0.15);
|
|
162
|
+
color: #86efac;
|
|
163
|
+
border: 1px solid rgba(34, 197, 94, 0.3);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.spektre-dev-modal-status.disabled {
|
|
167
|
+
background-color: rgba(100, 116, 139, 0.15);
|
|
168
|
+
color: #cbd5e1;
|
|
169
|
+
border: 1px solid rgba(100, 116, 139, 0.3);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/* Toggle Container */
|
|
173
|
+
.spektre-dev-modal-toggle-container {
|
|
174
|
+
display: flex;
|
|
175
|
+
align-items: center;
|
|
176
|
+
margin-bottom: 16px;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.spektre-dev-toggle-label {
|
|
180
|
+
display: flex;
|
|
181
|
+
align-items: center;
|
|
182
|
+
gap: 12px;
|
|
183
|
+
cursor: pointer;
|
|
184
|
+
font-size: 14px;
|
|
185
|
+
color: #e2e8f0;
|
|
186
|
+
user-select: none;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/* Toggle Switch */
|
|
190
|
+
.spektre-dev-toggle {
|
|
191
|
+
appearance: none;
|
|
192
|
+
-webkit-appearance: none;
|
|
193
|
+
width: 44px;
|
|
194
|
+
height: 24px;
|
|
195
|
+
background-color: #1e293b;
|
|
196
|
+
border: 1px solid #334155;
|
|
197
|
+
border-radius: 12px;
|
|
198
|
+
cursor: pointer;
|
|
199
|
+
position: relative;
|
|
200
|
+
transition: all 0.3s ease;
|
|
201
|
+
padding: 2px;
|
|
202
|
+
flex-shrink: 0;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.spektre-dev-toggle:checked {
|
|
206
|
+
background-color: #f97316;
|
|
207
|
+
border-color: #f97316;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.spektre-dev-toggle::before {
|
|
211
|
+
content: '';
|
|
212
|
+
position: absolute;
|
|
213
|
+
width: 18px;
|
|
214
|
+
height: 18px;
|
|
215
|
+
background-color: white;
|
|
216
|
+
border-radius: 10px;
|
|
217
|
+
top: 3px;
|
|
218
|
+
left: 3px;
|
|
219
|
+
transition: left 0.3s ease;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.spektre-dev-toggle:checked::before {
|
|
223
|
+
left: 23px;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.spektre-dev-toggle:focus {
|
|
227
|
+
outline: none;
|
|
228
|
+
box-shadow: 0 0 0 3px rgba(249, 115, 22, 0.2);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/* Reload Message */
|
|
232
|
+
.spektre-dev-modal-reload-msg {
|
|
233
|
+
margin: 0;
|
|
234
|
+
padding: 12px;
|
|
235
|
+
background-color: rgba(249, 115, 22, 0.15);
|
|
236
|
+
border: 1px solid rgba(249, 115, 22, 0.3);
|
|
237
|
+
border-radius: 6px;
|
|
238
|
+
font-size: 13px;
|
|
239
|
+
color: #fed7aa;
|
|
240
|
+
text-align: center;
|
|
241
|
+
transition: opacity 0.2s ease;
|
|
242
|
+
font-weight: 500;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/* Accessibility */
|
|
246
|
+
@media (prefers-reduced-motion: reduce) {
|
|
247
|
+
.spektre-dev-dot,
|
|
248
|
+
.spektre-dev-modal-overlay,
|
|
249
|
+
.spektre-dev-modal,
|
|
250
|
+
.spektre-dev-toggle,
|
|
251
|
+
.spektre-dev-toggle::before {
|
|
252
|
+
animation: none;
|
|
253
|
+
transition: none;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/* Mobile responsiveness */
|
|
258
|
+
@media (max-width: 480px) {
|
|
259
|
+
.spektre-dev-dot {
|
|
260
|
+
bottom: 16px;
|
|
261
|
+
right: 16px;
|
|
262
|
+
width: 14px;
|
|
263
|
+
height: 14px;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.spektre-dev-dot:hover {
|
|
267
|
+
width: 18px;
|
|
268
|
+
height: 18px;
|
|
269
|
+
bottom: 14px;
|
|
270
|
+
right: 14px;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.spektre-dev-modal {
|
|
274
|
+
width: 85%;
|
|
275
|
+
max-width: 320px;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
.spektre-dev-modal-header h2 {
|
|
279
|
+
font-size: 16px;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.spektre-dev-modal-body {
|
|
283
|
+
padding: 16px;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
`;
|
|
287
|
+
document.head.appendChild(styleSheet);
|
|
288
|
+
}
|
|
289
|
+
function initializeDevUI() {
|
|
290
|
+
// Inject styles first
|
|
291
|
+
injectDevUIStyles();
|
|
292
|
+
// Check if Spektre is enabled in localStorage (default to true)
|
|
293
|
+
const isEnabled = localStorage.getItem(DEV_UI_STORAGE_KEY);
|
|
294
|
+
const spektreEnabled = isEnabled === null ? true : isEnabled === 'true';
|
|
295
|
+
// If disabled, prevent core Spektre from initializing
|
|
296
|
+
if (!spektreEnabled) {
|
|
297
|
+
window.__spektreDevDisabled = true;
|
|
298
|
+
}
|
|
299
|
+
// Create and inject the orange dot
|
|
300
|
+
createDevDot();
|
|
301
|
+
}
|
|
302
|
+
function createDevDot() {
|
|
303
|
+
const dot = document.createElement('div');
|
|
304
|
+
dot.id = 'spektre-dev-dot';
|
|
305
|
+
dot.className = 'spektre-dev-dot';
|
|
306
|
+
dot.setAttribute('aria-label', 'Spektre development environment controls');
|
|
307
|
+
dot.addEventListener('click', () => {
|
|
308
|
+
openDevModal();
|
|
309
|
+
});
|
|
310
|
+
document.body.appendChild(dot);
|
|
311
|
+
}
|
|
312
|
+
function openDevModal() {
|
|
313
|
+
// Check if modal already exists
|
|
314
|
+
if (document.getElementById('spektre-dev-modal')) {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
const isEnabled = localStorage.getItem(DEV_UI_STORAGE_KEY) !== 'false';
|
|
318
|
+
const modal = document.createElement('div');
|
|
319
|
+
modal.id = 'spektre-dev-modal';
|
|
320
|
+
modal.className = 'spektre-dev-modal-overlay';
|
|
321
|
+
const modalContent = document.createElement('div');
|
|
322
|
+
modalContent.className = 'spektre-dev-modal';
|
|
323
|
+
const header = document.createElement('div');
|
|
324
|
+
header.className = 'spektre-dev-modal-header';
|
|
325
|
+
header.innerHTML = '<h2>Spektre Development Mode</h2>';
|
|
326
|
+
const closeButton = document.createElement('button');
|
|
327
|
+
closeButton.className = 'spektre-dev-modal-close';
|
|
328
|
+
closeButton.innerHTML = '✕';
|
|
329
|
+
closeButton.setAttribute('aria-label', 'Close modal');
|
|
330
|
+
closeButton.addEventListener('click', () => {
|
|
331
|
+
modal.remove();
|
|
332
|
+
});
|
|
333
|
+
header.appendChild(closeButton);
|
|
334
|
+
const body = document.createElement('div');
|
|
335
|
+
body.className = 'spektre-dev-modal-body';
|
|
336
|
+
const infoText = document.createElement('p');
|
|
337
|
+
infoText.className = 'spektre-dev-modal-info';
|
|
338
|
+
infoText.textContent = 'You are in a development environment. Spektre is currently:';
|
|
339
|
+
const statusBadge = document.createElement('div');
|
|
340
|
+
statusBadge.className = `spektre-dev-modal-status ${isEnabled ? 'enabled' : 'disabled'}`;
|
|
341
|
+
statusBadge.textContent = isEnabled ? '● Enabled' : '● Disabled';
|
|
342
|
+
const toggleContainer = document.createElement('div');
|
|
343
|
+
toggleContainer.className = 'spektre-dev-modal-toggle-container';
|
|
344
|
+
const toggleLabel = document.createElement('label');
|
|
345
|
+
toggleLabel.className = 'spektre-dev-toggle-label';
|
|
346
|
+
const toggleSwitch = document.createElement('input');
|
|
347
|
+
toggleSwitch.type = 'checkbox';
|
|
348
|
+
toggleSwitch.className = 'spektre-dev-toggle';
|
|
349
|
+
toggleSwitch.checked = isEnabled;
|
|
350
|
+
toggleSwitch.setAttribute('aria-label', 'Toggle Spektre');
|
|
351
|
+
toggleSwitch.addEventListener('change', (e) => {
|
|
352
|
+
const enabled = e.target.checked;
|
|
353
|
+
localStorage.setItem(DEV_UI_STORAGE_KEY, String(enabled));
|
|
354
|
+
// Update status badge
|
|
355
|
+
statusBadge.className = `spektre-dev-modal-status ${enabled ? 'enabled' : 'disabled'}`;
|
|
356
|
+
statusBadge.textContent = enabled ? '● Enabled' : '● Disabled';
|
|
357
|
+
// Update dot visual
|
|
358
|
+
const dot = document.getElementById('spektre-dev-dot');
|
|
359
|
+
if (dot) {
|
|
360
|
+
dot.classList.toggle('disabled', !enabled);
|
|
361
|
+
}
|
|
362
|
+
// Show reload message
|
|
363
|
+
const reloadMsg = document.querySelector('.spektre-dev-modal-reload-msg');
|
|
364
|
+
if (reloadMsg) {
|
|
365
|
+
reloadMsg.textContent = 'Reload the page for changes to take effect';
|
|
366
|
+
reloadMsg.style.opacity = '1';
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
toggleLabel.appendChild(toggleSwitch);
|
|
370
|
+
toggleLabel.appendChild(document.createTextNode('Enable Spektre'));
|
|
371
|
+
toggleContainer.appendChild(toggleLabel);
|
|
372
|
+
const reloadMessage = document.createElement('p');
|
|
373
|
+
reloadMessage.className = 'spektre-dev-modal-reload-msg';
|
|
374
|
+
reloadMessage.style.opacity = '0';
|
|
375
|
+
body.appendChild(infoText);
|
|
376
|
+
body.appendChild(statusBadge);
|
|
377
|
+
body.appendChild(toggleContainer);
|
|
378
|
+
body.appendChild(reloadMessage);
|
|
379
|
+
modalContent.appendChild(header);
|
|
380
|
+
modalContent.appendChild(body);
|
|
381
|
+
modal.appendChild(modalContent);
|
|
382
|
+
// Close on overlay click
|
|
383
|
+
modal.addEventListener('click', (e) => {
|
|
384
|
+
if (e.target === modal) {
|
|
385
|
+
modal.remove();
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
// Close on escape key
|
|
389
|
+
document.addEventListener('keydown', (e) => {
|
|
390
|
+
if (e.key === 'Escape' && document.getElementById('spektre-dev-modal')) {
|
|
391
|
+
modal.remove();
|
|
392
|
+
}
|
|
393
|
+
}, { once: true });
|
|
394
|
+
document.body.appendChild(modal);
|
|
395
|
+
}
|
|
396
|
+
|
|
5
397
|
const SpektreContext = React.createContext(null);
|
|
6
398
|
SpektreContext.displayName = 'SpektreContext';
|
|
7
399
|
|
|
@@ -18,6 +410,16 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
|
|
|
18
410
|
sessionId: null,
|
|
19
411
|
});
|
|
20
412
|
React.useEffect(() => {
|
|
413
|
+
// Check if Spektre is disabled in dev mode
|
|
414
|
+
if (window.__spektreDevDisabled) {
|
|
415
|
+
setState({
|
|
416
|
+
isVerified: true,
|
|
417
|
+
isLoading: false,
|
|
418
|
+
error: null,
|
|
419
|
+
sessionId: 'dev-disabled',
|
|
420
|
+
});
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
21
423
|
// Set tampering detection marker
|
|
22
424
|
sessionStorage.setItem('spektre_js_enabled', 'true');
|
|
23
425
|
sessionStorage.setItem('spektre_init_time', Date.now().toString());
|
|
@@ -432,6 +834,11 @@ const useProtectedFetch = () => {
|
|
|
432
834
|
return protectedFetch;
|
|
433
835
|
};
|
|
434
836
|
|
|
837
|
+
// Check if we're in an iframe (development environment) and initialize dev UI
|
|
838
|
+
if (typeof window !== 'undefined' && window.self !== window.top) {
|
|
839
|
+
initializeDevUI();
|
|
840
|
+
}
|
|
841
|
+
|
|
435
842
|
exports.SecurityGate = SecurityGate;
|
|
436
843
|
exports.SpektreContext = SpektreContext;
|
|
437
844
|
exports.SpektreProvider = SpektreProvider;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|