@oasisomniverse/js 1.0.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.
- package/package.json +36 -0
- package/src/add-data.js +54 -0
- package/src/avatar-connect.js +126 -0
- package/src/avatar-wallet.js +60 -0
- package/src/coming-soon.js +35 -0
- package/src/confirmation.js +53 -0
- package/src/contact.js +84 -0
- package/src/cross-chain-management.js +36 -0
- package/src/edit-avatar.js +79 -0
- package/src/eggs.js +88 -0
- package/src/forgot-password.js +73 -0
- package/src/index.esm.js +15 -0
- package/src/index.js +15 -0
- package/src/karma-toast.js +50 -0
- package/src/load-data.js +56 -0
- package/src/login.js +154 -0
- package/src/manage-data.js +42 -0
- package/src/manage-eggs.js +41 -0
- package/src/manage-mission.js +42 -0
- package/src/manage-oasis-nft.js +41 -0
- package/src/message.js +57 -0
- package/src/navbar.js +80 -0
- package/src/oasis-modal.js +79 -0
- package/src/off-chain-management.js +36 -0
- package/src/provider-dropdown.js +87 -0
- package/src/purchase-oasis-nft.js +54 -0
- package/src/purchase-oasis-virtual-land-nft.js +54 -0
- package/src/reset-password.js +75 -0
- package/src/search-avatar.js +78 -0
- package/src/search-data.js +59 -0
- package/src/search-eggs.js +49 -0
- package/src/search-karma.js +48 -0
- package/src/search-mission.js +50 -0
- package/src/search-oasis-nft.js +49 -0
- package/src/search-profiles.js +50 -0
- package/src/seeds.js +83 -0
- package/src/signup.js +154 -0
- package/src/star-field.js +68 -0
- package/src/verify-email.js +77 -0
- package/src/view-achievements.js +42 -0
- package/src/view-avatar-karma.js +50 -0
- package/src/view-avatar.js +69 -0
- package/src/view-eggs.js +44 -0
- package/src/view-karma.js +41 -0
- package/src/view-leagues.js +41 -0
- package/src/view-mission.js +44 -0
- package/src/view-oasis-nft.js +46 -0
- package/src/view-tournaments.js +41 -0
- package/src/vote-karma.js +61 -0
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@oasisomniverse/js",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "OASIS Omniverse vanilla JS web component widgets",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"oasis",
|
|
7
|
+
"omniverse",
|
|
8
|
+
"web-components",
|
|
9
|
+
"javascript",
|
|
10
|
+
"widgets"
|
|
11
|
+
],
|
|
12
|
+
"author": "NextGenSoftware",
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "https://github.com/NextGenSoftwareUK/OASIS-JS-UI-Component-Library.git"
|
|
17
|
+
},
|
|
18
|
+
"main": "src/index.js",
|
|
19
|
+
"module": "src/index.esm.js",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"import": "./src/index.esm.js",
|
|
23
|
+
"require": "./src/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./widgets/*": "./src/widgets/*.js"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"src"
|
|
29
|
+
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "node scripts/build.js"
|
|
32
|
+
},
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
}
|
|
36
|
+
}
|
package/src/add-data.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OasisAddData — add off-chain or on-chain data entry popup widget
|
|
3
|
+
* Usage: const w = new OasisAddData({ onSave: (data) => {} }); w.open();
|
|
4
|
+
*/
|
|
5
|
+
class OasisAddData {
|
|
6
|
+
constructor({ container, apiUrl = 'https://api.web4.oasisomniverse.one', onSave = null, onClose = null } = {}) {
|
|
7
|
+
this._apiUrl = apiUrl; this._onSave = onSave; this._onClose = onClose; this._overlay = null;
|
|
8
|
+
this._injectStyles(); if (container) this._render(container);
|
|
9
|
+
}
|
|
10
|
+
_injectStyles() {
|
|
11
|
+
if (document.getElementById('oasis-popup-styles')) return;
|
|
12
|
+
const s = document.createElement('style'); s.id = 'oasis-popup-styles';
|
|
13
|
+
s.textContent = `.oasis-popup-overlay{position:fixed;inset:0;z-index:9000;background:rgba(0,0,0,.65);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .25s}.oasis-popup-overlay.is-open{opacity:1}.oasis-popup-modal{background:#0a1628;border:1px solid rgba(0,200,255,.2);border-radius:16px;box-shadow:0 24px 64px rgba(0,0,0,.6);width:90%;max-width:560px;max-height:90vh;overflow-y:auto;transform:translateY(16px);transition:transform .25s}.oasis-popup-overlay.is-open .oasis-popup-modal{transform:none}.oasis-popup-modal.lg{max-width:900px}.oasis-popup-header{display:flex;align-items:center;justify-content:space-between;padding:20px 24px;border-bottom:1px solid rgba(0,200,255,.1)}.oasis-popup-title{font-family:'Orbitron',sans-serif;font-size:14px;font-weight:700;color:#00c8ff;letter-spacing:.08em}.oasis-popup-close{background:none;border:none;color:#7a9bbf;font-size:22px;cursor:pointer;padding:0;line-height:1}.oasis-popup-close:hover{color:#fff}.oasis-popup-body{padding:24px}.oasis-field{display:flex;flex-direction:column;gap:6px;margin-bottom:16px}.oasis-label{font-size:11px;font-weight:600;letter-spacing:.06em;color:#7a9bbf;text-transform:uppercase}.oasis-input,.oasis-select,.oasis-textarea{background:rgba(255,255,255,.05);border:1px solid rgba(0,200,255,.2);border-radius:8px;padding:10px 14px;color:#fff;font-size:14px;outline:none;transition:border-color .2s;width:100%;box-sizing:border-box}.oasis-input:focus,.oasis-select:focus,.oasis-textarea:focus{border-color:rgba(0,200,255,.5)}.oasis-textarea{resize:vertical;min-height:80px}.oasis-select option{background:#0a1628}.oasis-btn{background:linear-gradient(135deg,#00c8ff,#0080ff);border:none;border-radius:8px;color:#fff;font-family:'Orbitron',sans-serif;font-size:12px;font-weight:700;letter-spacing:.08em;padding:11px 20px;cursor:pointer;transition:opacity .2s}.oasis-btn:hover{opacity:.85}.oasis-btn:disabled{opacity:.5;cursor:not-allowed}.oasis-btn-ghost{background:rgba(0,200,255,.1);border:1px solid rgba(0,200,255,.3);color:#00c8ff;border-radius:8px;font-size:12px;font-weight:600;padding:9px 16px;cursor:pointer}.oasis-btn-row{display:flex;gap:10px;justify-content:flex-end;margin-top:20px}.oasis-msg{border-radius:8px;padding:10px 14px;font-size:13px;margin-bottom:16px}.oasis-msg-error{background:rgba(255,80,80,.12);border:1px solid rgba(255,80,80,.3);color:#ff6b6b}.oasis-msg-success{background:rgba(0,200,100,.12);border:1px solid rgba(0,200,100,.3);color:#00c864}.oasis-grid-2{display:grid;grid-template-columns:1fr 1fr;gap:16px}.oasis-info-block{background:rgba(0,200,255,.05);border:1px solid rgba(0,200,255,.1);border-radius:10px;padding:16px;margin-bottom:12px}.oasis-info-label{font-size:10px;font-weight:600;letter-spacing:.06em;color:#7a9bbf;text-transform:uppercase;margin-bottom:4px}.oasis-info-value{color:#fff;font-size:14px;font-weight:500}.oasis-cs{text-align:center;padding:32px 16px}.oasis-cs-icon{font-size:48px;margin-bottom:12px}.oasis-cs h3{font-family:'Orbitron',sans-serif;font-size:15px;color:#00c8ff;margin:0 0 8px}.oasis-cs p{color:#7a9bbf;font-size:13px;margin:0}.oasis-table{width:100%;border-collapse:collapse;font-size:13px}.oasis-table th{text-align:left;padding:10px 12px;font-size:10px;font-weight:700;letter-spacing:.06em;color:#7a9bbf;text-transform:uppercase;border-bottom:1px solid rgba(0,200,255,.1)}.oasis-table td{padding:10px 12px;color:#fff;border-bottom:1px solid rgba(255,255,255,.05)}.oasis-table tr:hover td{background:rgba(0,200,255,.04)}.oasis-badge{display:inline-block;padding:3px 8px;border-radius:999px;font-size:10px;font-weight:700}.oasis-badge-blue{background:rgba(0,200,255,.15);color:#00c8ff}.oasis-badge-green{background:rgba(0,200,100,.15);color:#00c864}.oasis-badge-red{background:rgba(255,80,80,.15);color:#ff6b6b}.oasis-badge-yellow{background:rgba(255,200,0,.15);color:#ffc800}.oasis-search-row{display:flex;gap:10px;margin-bottom:16px}.oasis-search-row .oasis-input{flex:1}.oasis-stat-row{display:flex;gap:12px;margin-bottom:20px}.oasis-stat{flex:1;background:rgba(0,200,255,.05);border:1px solid rgba(0,200,255,.1);border-radius:10px;padding:14px;text-align:center}.oasis-stat-val{font-family:'Orbitron',sans-serif;font-size:20px;font-weight:700;color:#00c8ff}.oasis-stat-lbl{font-size:10px;color:#7a9bbf;margin-top:4px}.oasis-divider{border:none;border-top:1px solid rgba(0,200,255,.1);margin:16px 0}.oasis-section-title{font-size:11px;font-weight:700;color:#7a9bbf;letter-spacing:.08em;text-transform:uppercase;margin:0 0 12px}.oasis-radio-group{display:flex;gap:16px;margin-bottom:16px}.oasis-radio-label{display:flex;align-items:center;gap:8px;font-size:13px;color:#fff;cursor:pointer}.oasis-radio-label input[type=radio]{accent-color:#00c8ff}.oasis-link{background:none;border:none;color:#00c8ff;font-size:13px;cursor:pointer;padding:0;text-decoration:underline}.oasis-chat-area{background:rgba(0,0,0,.2);border:1px solid rgba(0,200,255,.1);border-radius:10px;height:220px;overflow-y:auto;padding:12px;margin-bottom:12px;display:flex;flex-direction:column;gap:8px}.oasis-chat-bubble{background:rgba(0,200,255,.1);border-radius:10px;padding:8px 12px;font-size:13px;color:#fff;max-width:75%}.oasis-chat-bubble.mine{background:rgba(0,128,255,.2);align-self:flex-end}.oasis-chat-input-row{display:flex;gap:8px}.oasis-chat-input-row .oasis-input{flex:1}`;
|
|
14
|
+
document.head.appendChild(s);
|
|
15
|
+
}
|
|
16
|
+
open() {
|
|
17
|
+
if (this._overlay) return;
|
|
18
|
+
this._overlay = document.createElement('div');
|
|
19
|
+
this._overlay.className = 'oasis-popup-overlay';
|
|
20
|
+
this._overlay.innerHTML = `<div class="oasis-popup-modal"><div class="oasis-popup-header"><span class="oasis-popup-title">Add Data</span><button class="oasis-popup-close">×</button></div><div class="oasis-popup-body">${this._buildBody()}</div></div>`;
|
|
21
|
+
this._overlay.querySelector('.oasis-popup-close').addEventListener('click', () => this.close());
|
|
22
|
+
this._overlay.addEventListener('click', e => { if (e.target === this._overlay) this.close(); });
|
|
23
|
+
document.body.appendChild(this._overlay);
|
|
24
|
+
requestAnimationFrame(() => this._overlay.classList.add('is-open'));
|
|
25
|
+
this._overlay.querySelector('#oasis-ad-save').addEventListener('click', () => this._doSave());
|
|
26
|
+
}
|
|
27
|
+
_buildBody() {
|
|
28
|
+
return `<div id="oasis-ad-msg"></div>
|
|
29
|
+
<div class="oasis-field"><label class="oasis-label">Key</label><input class="oasis-input" id="oasis-ad-key" type="text" placeholder="my.data.key" /></div>
|
|
30
|
+
<div class="oasis-field"><label class="oasis-label">Value</label><textarea class="oasis-textarea" id="oasis-ad-val" placeholder="Enter value (JSON, text, or any data)"></textarea></div>
|
|
31
|
+
<div class="oasis-field"><label class="oasis-label">Provider</label><select class="oasis-select" id="oasis-ad-prov"><option value="holochain">Holochain</option><option value="ethereum">Ethereum</option><option value="ipfs">IPFS</option><option value="mongodb">MongoDB</option><option value="neo4j">Neo4j</option></select></div>
|
|
32
|
+
<div class="oasis-field"><label class="oasis-label">Encrypt</label><select class="oasis-select" id="oasis-ad-enc"><option value="false">No</option><option value="true">Yes (AES-256)</option></select></div>
|
|
33
|
+
<div class="oasis-btn-row"><button class="oasis-btn-ghost" onclick="this.closest('.oasis-popup-overlay')?.remove()">Cancel</button><button class="oasis-btn" id="oasis-ad-save">Save Data</button></div>`;
|
|
34
|
+
}
|
|
35
|
+
async _doSave() {
|
|
36
|
+
const key = this._overlay.querySelector('#oasis-ad-key').value.trim();
|
|
37
|
+
const val = this._overlay.querySelector('#oasis-ad-val').value;
|
|
38
|
+
const msgEl = this._overlay.querySelector('#oasis-ad-msg');
|
|
39
|
+
const btn = this._overlay.querySelector('#oasis-ad-save');
|
|
40
|
+
if (!key) { msgEl.innerHTML = '<div class="oasis-msg oasis-msg-error">Key is required.</div>'; return; }
|
|
41
|
+
btn.textContent = 'Saving…'; btn.disabled = true;
|
|
42
|
+
try {
|
|
43
|
+
const res = await fetch(`${this._apiUrl}/api/data`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ key, value: val, providerType: this._overlay.querySelector('#oasis-ad-prov').value, encrypt: this._overlay.querySelector('#oasis-ad-enc').value === 'true' }) });
|
|
44
|
+
const data = await res.json();
|
|
45
|
+
if (!res.ok || data.isError) throw new Error(data.message || 'Save failed');
|
|
46
|
+
msgEl.innerHTML = '<div class="oasis-msg oasis-msg-success">Data saved successfully!</div>';
|
|
47
|
+
if (this._onSave) this._onSave(data);
|
|
48
|
+
} catch (e) { msgEl.innerHTML = `<div class="oasis-msg oasis-msg-error">${e.message}</div>`; btn.textContent = 'Save Data'; btn.disabled = false; }
|
|
49
|
+
}
|
|
50
|
+
close() { if (!this._overlay) return; const el = this._overlay; this._overlay = null; el.classList.remove('is-open'); el.addEventListener('transitionend', () => el.remove(), { once: true }); if (this._onClose) this._onClose(); }
|
|
51
|
+
_render(c) { c.innerHTML = `<div class="oasis-popup-body">${this._buildBody()}</div>`; }
|
|
52
|
+
destroy() { this.close(); }
|
|
53
|
+
}
|
|
54
|
+
window.OasisAddData = OasisAddData;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OasisAvatarConnect — login/logout toggle widget
|
|
3
|
+
* Renders a button that shows login state and opens an OasisModal with the login form.
|
|
4
|
+
* Usage:
|
|
5
|
+
* const ac = new OasisAvatarConnect({ container: document.querySelector('#nav-auth') })
|
|
6
|
+
* ac.destroy()
|
|
7
|
+
*/
|
|
8
|
+
class OasisAvatarConnect {
|
|
9
|
+
constructor({ container, apiUrl = 'https://api.web4.oasisomniverse.one', sessionKey = 'oasis_session', onLogin = null, onLogout = null } = {}) {
|
|
10
|
+
this._container = container;
|
|
11
|
+
this._apiUrl = apiUrl;
|
|
12
|
+
this._sessionKey = sessionKey;
|
|
13
|
+
this._onLogin = onLogin;
|
|
14
|
+
this._onLogout = onLogout;
|
|
15
|
+
this._modal = null;
|
|
16
|
+
this._session = this._loadSession();
|
|
17
|
+
this._render();
|
|
18
|
+
this._injectStyles();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
_loadSession() {
|
|
22
|
+
try { return JSON.parse(sessionStorage.getItem(this._sessionKey)); } catch { return null; }
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
_saveSession(sess) {
|
|
26
|
+
sessionStorage.setItem(this._sessionKey, JSON.stringify(sess));
|
|
27
|
+
this._session = sess;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
_clearSession() {
|
|
31
|
+
sessionStorage.removeItem(this._sessionKey);
|
|
32
|
+
this._session = null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
_render() {
|
|
36
|
+
this._container.innerHTML = '';
|
|
37
|
+
if (this._session) {
|
|
38
|
+
const btn = document.createElement('div');
|
|
39
|
+
btn.className = 'oac-avatar-chip';
|
|
40
|
+
btn.innerHTML = `<span class="oac-avatar-icon">👤</span><span class="oac-username">${this._session.username}</span><span class="oac-karma">⚡ ${this._session.karma ?? 0}</span><button class="oac-logout-btn">Logout</button>`;
|
|
41
|
+
btn.querySelector('.oac-logout-btn').addEventListener('click', () => this._logout());
|
|
42
|
+
this._container.appendChild(btn);
|
|
43
|
+
} else {
|
|
44
|
+
const btn = document.createElement('button');
|
|
45
|
+
btn.className = 'oac-login-btn';
|
|
46
|
+
btn.textContent = 'Beam In';
|
|
47
|
+
btn.addEventListener('click', () => this._openLogin());
|
|
48
|
+
this._container.appendChild(btn);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
_openLogin() {
|
|
53
|
+
const formHtml = `
|
|
54
|
+
<div class="oac-form" id="oac-login-form">
|
|
55
|
+
<div id="oac-error" class="oac-error" style="display:none"></div>
|
|
56
|
+
<div class="oac-field"><label class="oac-label">Username</label><input class="oac-input" id="oac-username" type="text" placeholder="yourusername" autocomplete="username" /></div>
|
|
57
|
+
<div class="oac-field"><label class="oac-label">Password</label><input class="oac-input" id="oac-password" type="password" placeholder="••••••••" autocomplete="current-password" /></div>
|
|
58
|
+
<button class="oac-submit-btn" id="oac-submit">Beam In</button>
|
|
59
|
+
</div>
|
|
60
|
+
`;
|
|
61
|
+
this._modal = new OasisModal({ title: 'Beam In', content: formHtml, accentColor: '#00c8ff' });
|
|
62
|
+
this._modal.open();
|
|
63
|
+
document.getElementById('oac-submit').addEventListener('click', () => this._doLogin());
|
|
64
|
+
document.getElementById('oac-password').addEventListener('keydown', e => { if (e.key === 'Enter') this._doLogin(); });
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async _doLogin() {
|
|
68
|
+
const username = document.getElementById('oac-username').value.trim();
|
|
69
|
+
const password = document.getElementById('oac-password').value;
|
|
70
|
+
const errEl = document.getElementById('oac-error');
|
|
71
|
+
const btn = document.getElementById('oac-submit');
|
|
72
|
+
if (!username || !password) { errEl.textContent = 'Please fill in all fields.'; errEl.style.display = 'block'; return; }
|
|
73
|
+
btn.textContent = 'Connecting…'; btn.disabled = true; errEl.style.display = 'none';
|
|
74
|
+
try {
|
|
75
|
+
const { OASISClient } = await import('https://esm.sh/@oasisomniverse/web4-api@2.0.2');
|
|
76
|
+
const oasis = new OASISClient({ baseUrl: this._apiUrl });
|
|
77
|
+
const result = await oasis.auth.login({ username, password });
|
|
78
|
+
const karma = await oasis.karma.getKarmaForAvatar({ avatarId: result.avatarId });
|
|
79
|
+
this._saveSession({ avatarId: result.avatarId, username, karma: karma.total ?? 0 });
|
|
80
|
+
this._modal.close();
|
|
81
|
+
this._render();
|
|
82
|
+
if (this._onLogin) this._onLogin(this._session);
|
|
83
|
+
} catch (e) {
|
|
84
|
+
errEl.textContent = e?.message ?? 'Login failed. Please check your credentials.';
|
|
85
|
+
errEl.style.display = 'block';
|
|
86
|
+
btn.textContent = 'Beam In'; btn.disabled = false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
_logout() {
|
|
91
|
+
this._clearSession();
|
|
92
|
+
this._render();
|
|
93
|
+
if (this._onLogout) this._onLogout();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
_injectStyles() {
|
|
97
|
+
if (document.getElementById('oac-styles')) return;
|
|
98
|
+
const s = document.createElement('style');
|
|
99
|
+
s.id = 'oac-styles';
|
|
100
|
+
s.textContent = `
|
|
101
|
+
.oac-login-btn{background:linear-gradient(135deg,#00c8ff,#0080ff);border:none;border-radius:8px;color:#fff;font-family:'Orbitron',sans-serif;font-size:12px;font-weight:700;letter-spacing:.08em;padding:9px 18px;cursor:pointer;transition:opacity .2s}
|
|
102
|
+
.oac-login-btn:hover{opacity:.85}
|
|
103
|
+
.oac-avatar-chip{display:flex;align-items:center;gap:10px;background:rgba(0,200,255,.08);border:1px solid rgba(0,200,255,.2);border-radius:999px;padding:6px 14px 6px 10px;font-size:13px}
|
|
104
|
+
.oac-avatar-icon{font-size:18px}
|
|
105
|
+
.oac-username{color:#fff;font-weight:600}
|
|
106
|
+
.oac-karma{color:#00c8ff;font-family:'Orbitron',sans-serif;font-size:11px}
|
|
107
|
+
.oac-logout-btn{background:none;border:1px solid rgba(255,100,100,.3);color:#ff8080;border-radius:6px;font-size:11px;padding:3px 8px;cursor:pointer;margin-left:4px}
|
|
108
|
+
.oac-form{display:flex;flex-direction:column;gap:16px}
|
|
109
|
+
.oac-error{background:rgba(255,80,80,.12);border:1px solid rgba(255,80,80,.3);color:#ff6b6b;border-radius:8px;padding:10px 14px;font-size:13px}
|
|
110
|
+
.oac-field{display:flex;flex-direction:column;gap:6px}
|
|
111
|
+
.oac-label{font-size:11px;font-weight:600;letter-spacing:.06em;color:#7a9bbf;text-transform:uppercase}
|
|
112
|
+
.oac-input{background:rgba(255,255,255,.05);border:1px solid rgba(0,200,255,.2);border-radius:8px;padding:10px 14px;color:#fff;font-size:14px;outline:none;transition:border-color .2s}
|
|
113
|
+
.oac-input:focus{border-color:rgba(0,200,255,.5)}
|
|
114
|
+
.oac-submit-btn{background:linear-gradient(135deg,#00c8ff,#0080ff);border:none;border-radius:8px;color:#fff;font-family:'Orbitron',sans-serif;font-size:13px;font-weight:700;letter-spacing:.08em;padding:12px;cursor:pointer}
|
|
115
|
+
.oac-submit-btn:disabled{opacity:.5;cursor:not-allowed}
|
|
116
|
+
`;
|
|
117
|
+
document.head.appendChild(s);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
destroy() {
|
|
121
|
+
this._modal?.destroy();
|
|
122
|
+
this._container.innerHTML = '';
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
window.OasisAvatarConnect = OasisAvatarConnect;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OasisAvatarWallet — view avatar's linked wallets popup widget
|
|
3
|
+
* Usage: const w = new OasisAvatarWallet({ avatarId: '...' }); w.open();
|
|
4
|
+
*/
|
|
5
|
+
class OasisAvatarWallet {
|
|
6
|
+
constructor({ container, avatarId = '', apiUrl = 'https://api.web4.oasisomniverse.one', onClose = null } = {}) {
|
|
7
|
+
this._avatarId = avatarId; this._apiUrl = apiUrl; this._onClose = onClose; this._overlay = null;
|
|
8
|
+
this._injectStyles();
|
|
9
|
+
if (container) this._render(container);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
_injectStyles() {
|
|
13
|
+
if (document.getElementById('oasis-popup-styles')) return;
|
|
14
|
+
const s = document.createElement('style'); s.id = 'oasis-popup-styles';
|
|
15
|
+
s.textContent = `.oasis-popup-overlay{position:fixed;inset:0;z-index:9000;background:rgba(0,0,0,.65);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .25s}.oasis-popup-overlay.is-open{opacity:1}.oasis-popup-modal{background:#0a1628;border:1px solid rgba(0,200,255,.2);border-radius:16px;box-shadow:0 24px 64px rgba(0,0,0,.6);width:90%;max-width:560px;max-height:90vh;overflow-y:auto;transform:translateY(16px);transition:transform .25s}.oasis-popup-overlay.is-open .oasis-popup-modal{transform:none}.oasis-popup-modal.lg{max-width:900px}.oasis-popup-header{display:flex;align-items:center;justify-content:space-between;padding:20px 24px;border-bottom:1px solid rgba(0,200,255,.1)}.oasis-popup-title{font-family:'Orbitron',sans-serif;font-size:14px;font-weight:700;color:#00c8ff;letter-spacing:.08em}.oasis-popup-close{background:none;border:none;color:#7a9bbf;font-size:22px;cursor:pointer;padding:0;line-height:1}.oasis-popup-close:hover{color:#fff}.oasis-popup-body{padding:24px}.oasis-field{display:flex;flex-direction:column;gap:6px;margin-bottom:16px}.oasis-label{font-size:11px;font-weight:600;letter-spacing:.06em;color:#7a9bbf;text-transform:uppercase}.oasis-input,.oasis-select,.oasis-textarea{background:rgba(255,255,255,.05);border:1px solid rgba(0,200,255,.2);border-radius:8px;padding:10px 14px;color:#fff;font-size:14px;outline:none;transition:border-color .2s;width:100%;box-sizing:border-box}.oasis-input:focus,.oasis-select:focus,.oasis-textarea:focus{border-color:rgba(0,200,255,.5)}.oasis-textarea{resize:vertical;min-height:80px}.oasis-select option{background:#0a1628}.oasis-btn{background:linear-gradient(135deg,#00c8ff,#0080ff);border:none;border-radius:8px;color:#fff;font-family:'Orbitron',sans-serif;font-size:12px;font-weight:700;letter-spacing:.08em;padding:11px 20px;cursor:pointer;transition:opacity .2s}.oasis-btn:hover{opacity:.85}.oasis-btn:disabled{opacity:.5;cursor:not-allowed}.oasis-btn-ghost{background:rgba(0,200,255,.1);border:1px solid rgba(0,200,255,.3);color:#00c8ff;border-radius:8px;font-size:12px;font-weight:600;padding:9px 16px;cursor:pointer}.oasis-btn-row{display:flex;gap:10px;justify-content:flex-end;margin-top:20px}.oasis-msg{border-radius:8px;padding:10px 14px;font-size:13px;margin-bottom:16px}.oasis-msg-error{background:rgba(255,80,80,.12);border:1px solid rgba(255,80,80,.3);color:#ff6b6b}.oasis-msg-success{background:rgba(0,200,100,.12);border:1px solid rgba(0,200,100,.3);color:#00c864}.oasis-grid-2{display:grid;grid-template-columns:1fr 1fr;gap:16px}.oasis-info-block{background:rgba(0,200,255,.05);border:1px solid rgba(0,200,255,.1);border-radius:10px;padding:16px;margin-bottom:12px}.oasis-info-label{font-size:10px;font-weight:600;letter-spacing:.06em;color:#7a9bbf;text-transform:uppercase;margin-bottom:4px}.oasis-info-value{color:#fff;font-size:14px;font-weight:500;word-break:break-all}.oasis-cs{text-align:center;padding:32px 16px}.oasis-cs-icon{font-size:48px;margin-bottom:12px}.oasis-cs h3{font-family:'Orbitron',sans-serif;font-size:15px;color:#00c8ff;margin:0 0 8px}.oasis-cs p{color:#7a9bbf;font-size:13px;margin:0}.oasis-table{width:100%;border-collapse:collapse;font-size:13px}.oasis-table th{text-align:left;padding:10px 12px;font-size:10px;font-weight:700;letter-spacing:.06em;color:#7a9bbf;text-transform:uppercase;border-bottom:1px solid rgba(0,200,255,.1)}.oasis-table td{padding:10px 12px;color:#fff;border-bottom:1px solid rgba(255,255,255,.05)}.oasis-table tr:hover td{background:rgba(0,200,255,.04)}.oasis-badge{display:inline-block;padding:3px 8px;border-radius:999px;font-size:10px;font-weight:700}.oasis-badge-blue{background:rgba(0,200,255,.15);color:#00c8ff}.oasis-badge-green{background:rgba(0,200,100,.15);color:#00c864}.oasis-badge-red{background:rgba(255,80,80,.15);color:#ff6b6b}.oasis-badge-yellow{background:rgba(255,200,0,.15);color:#ffc800}.oasis-search-row{display:flex;gap:10px;margin-bottom:16px}.oasis-search-row .oasis-input{flex:1}.oasis-stat-row{display:flex;gap:12px;margin-bottom:20px}.oasis-stat{flex:1;background:rgba(0,200,255,.05);border:1px solid rgba(0,200,255,.1);border-radius:10px;padding:14px;text-align:center}.oasis-stat-val{font-family:'Orbitron',sans-serif;font-size:20px;font-weight:700;color:#00c8ff}.oasis-stat-lbl{font-size:10px;color:#7a9bbf;margin-top:4px}.oasis-divider{border:none;border-top:1px solid rgba(0,200,255,.1);margin:16px 0}.oasis-section-title{font-size:11px;font-weight:700;color:#7a9bbf;letter-spacing:.08em;text-transform:uppercase;margin:0 0 12px}.oasis-radio-group{display:flex;gap:16px;margin-bottom:16px}.oasis-radio-label{display:flex;align-items:center;gap:8px;font-size:13px;color:#fff;cursor:pointer}.oasis-radio-label input[type=radio]{accent-color:#00c8ff}.oasis-link{background:none;border:none;color:#00c8ff;font-size:13px;cursor:pointer;padding:0;text-decoration:underline}.oasis-chat-area{background:rgba(0,0,0,.2);border:1px solid rgba(0,200,255,.1);border-radius:10px;height:220px;overflow-y:auto;padding:12px;margin-bottom:12px;display:flex;flex-direction:column;gap:8px}.oasis-chat-bubble{background:rgba(0,200,255,.1);border-radius:10px;padding:8px 12px;font-size:13px;color:#fff;max-width:75%}.oasis-chat-bubble.mine{background:rgba(0,128,255,.2);align-self:flex-end}.oasis-chat-input-row{display:flex;gap:8px}.oasis-chat-input-row .oasis-input{flex:1}`;
|
|
16
|
+
document.head.appendChild(s);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
open() {
|
|
20
|
+
if (this._overlay) return;
|
|
21
|
+
this._overlay = document.createElement('div');
|
|
22
|
+
this._overlay.className = 'oasis-popup-overlay';
|
|
23
|
+
this._overlay.innerHTML = `<div class="oasis-popup-modal">
|
|
24
|
+
<div class="oasis-popup-header"><span class="oasis-popup-title">Avatar Wallet</span><button class="oasis-popup-close">×</button></div>
|
|
25
|
+
<div class="oasis-popup-body">${this._buildBody()}</div>
|
|
26
|
+
</div>`;
|
|
27
|
+
this._overlay.querySelector('.oasis-popup-close').addEventListener('click', () => this.close());
|
|
28
|
+
this._overlay.addEventListener('click', e => { if (e.target === this._overlay) this.close(); });
|
|
29
|
+
document.body.appendChild(this._overlay);
|
|
30
|
+
requestAnimationFrame(() => this._overlay.classList.add('is-open'));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
_buildBody() {
|
|
34
|
+
return `
|
|
35
|
+
<div class="oasis-stat-row">
|
|
36
|
+
<div class="oasis-stat"><div class="oasis-stat-val">0.00</div><div class="oasis-stat-lbl">ETH Balance</div></div>
|
|
37
|
+
<div class="oasis-stat"><div class="oasis-stat-val">0</div><div class="oasis-stat-lbl">NFTs Held</div></div>
|
|
38
|
+
<div class="oasis-stat"><div class="oasis-stat-val">0</div><div class="oasis-stat-lbl">Seeds</div></div>
|
|
39
|
+
</div>
|
|
40
|
+
<p class="oasis-section-title">Linked Wallets</p>
|
|
41
|
+
<div class="oasis-info-block"><div class="oasis-info-label">Ethereum</div><div class="oasis-info-value">Not linked</div></div>
|
|
42
|
+
<div class="oasis-info-block"><div class="oasis-info-label">Solana</div><div class="oasis-info-value">Not linked</div></div>
|
|
43
|
+
<div class="oasis-info-block"><div class="oasis-info-label">Holochain</div><div class="oasis-info-value">Not linked</div></div>
|
|
44
|
+
<div class="oasis-btn-row"><button class="oasis-btn" style="width:auto" onclick="this.textContent='Coming Soon…'">Link Wallet</button></div>
|
|
45
|
+
`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
close() {
|
|
49
|
+
if (!this._overlay) return;
|
|
50
|
+
const el = this._overlay; this._overlay = null;
|
|
51
|
+
el.classList.remove('is-open');
|
|
52
|
+
el.addEventListener('transitionend', () => el.remove(), { once: true });
|
|
53
|
+
if (this._onClose) this._onClose();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
_render(container) { container.innerHTML = `<div class="oasis-popup-body">${this._buildBody()}</div>`; }
|
|
57
|
+
destroy() { this.close(); }
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
window.OasisAvatarWallet = OasisAvatarWallet;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OasisComingSoon — standalone Coming Soon widget
|
|
3
|
+
* Usage: new OasisComingSoon({ container, title, message })
|
|
4
|
+
*/
|
|
5
|
+
(function () {
|
|
6
|
+
const CSS = `
|
|
7
|
+
.oasis-cs-shell{font-family:'Rajdhani',sans-serif;display:flex;flex-direction:column;align-items:center;gap:16px;padding:40px 20px;text-align:center}
|
|
8
|
+
.oasis-cs-icon{font-size:48px}
|
|
9
|
+
.oasis-cs-title{font-family:'Orbitron',sans-serif;font-size:20px;color:#fff;margin:0}
|
|
10
|
+
.oasis-cs-body{font-size:14px;color:#7a9bbf;line-height:1.6;margin:0;max-width:360px}
|
|
11
|
+
.oasis-cs-badge{background:rgba(255,180,60,.12);border:1px solid rgba(255,180,60,.28);color:#ffb43c;border-radius:999px;font-size:11px;font-weight:700;letter-spacing:.1em;padding:5px 14px;text-transform:uppercase}
|
|
12
|
+
`;
|
|
13
|
+
|
|
14
|
+
class OasisComingSoon {
|
|
15
|
+
constructor({ container, title = 'Feature Coming Soon', message = 'This feature is currently under development and will be available soon.' } = {}) {
|
|
16
|
+
this._container = typeof container === 'string' ? document.querySelector(container) : container;
|
|
17
|
+
if (!this._container) throw new Error('OasisComingSoon: container not found');
|
|
18
|
+
if (!document.getElementById('oasis-cs-styles')) {
|
|
19
|
+
const s = document.createElement('style'); s.id = 'oasis-cs-styles'; s.textContent = CSS;
|
|
20
|
+
document.head.appendChild(s);
|
|
21
|
+
}
|
|
22
|
+
this._container.innerHTML = `
|
|
23
|
+
<div class="oasis-cs-shell">
|
|
24
|
+
<div class="oasis-cs-icon">🚀</div>
|
|
25
|
+
<h2 class="oasis-cs-title">${title}</h2>
|
|
26
|
+
<p class="oasis-cs-body">${message}</p>
|
|
27
|
+
<div class="oasis-cs-badge">Coming Soon</div>
|
|
28
|
+
</div>`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
destroy() { this._container.innerHTML = ''; }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
window.OasisComingSoon = OasisComingSoon;
|
|
35
|
+
})();
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OasisConfirmation — standalone Confirmation dialog widget
|
|
3
|
+
* Usage: new OasisConfirmation({ container, title, message, onConfirm, onCancel })
|
|
4
|
+
*/
|
|
5
|
+
(function () {
|
|
6
|
+
const CSS = `
|
|
7
|
+
.oasis-conf-shell{font-family:'Rajdhani',sans-serif;display:flex;flex-direction:column;align-items:center;gap:18px;padding:20px;text-align:center}
|
|
8
|
+
.oasis-conf-icon{font-size:44px}
|
|
9
|
+
.oasis-conf-title{font-family:'Orbitron',sans-serif;font-size:18px;color:#fff;margin:0}
|
|
10
|
+
.oasis-conf-body{font-size:14px;color:#a8bfd8;line-height:1.6;margin:0;max-width:360px}
|
|
11
|
+
.oasis-conf-actions{display:flex;gap:12px;margin-top:4px}
|
|
12
|
+
.oasis-conf-btn{border:none;border-radius:8px;font-family:'Orbitron',sans-serif;font-size:12px;font-weight:700;letter-spacing:.08em;padding:11px 24px;cursor:pointer;transition:opacity .2s}
|
|
13
|
+
.oasis-conf-btn:hover{opacity:.85}
|
|
14
|
+
.oasis-conf-btn--confirm{background:linear-gradient(135deg,#ff4444,#cc0000);color:#fff}
|
|
15
|
+
.oasis-conf-btn--cancel{background:transparent;border:1px solid rgba(0,200,255,.3);color:#00c8ff}
|
|
16
|
+
`;
|
|
17
|
+
|
|
18
|
+
class OasisConfirmation {
|
|
19
|
+
constructor({
|
|
20
|
+
container,
|
|
21
|
+
title = 'Are you sure?',
|
|
22
|
+
message = 'This action cannot be undone.',
|
|
23
|
+
icon = '⚠️',
|
|
24
|
+
confirmLabel = 'Confirm',
|
|
25
|
+
cancelLabel = 'Cancel',
|
|
26
|
+
onConfirm = () => {},
|
|
27
|
+
onCancel = () => {},
|
|
28
|
+
} = {}) {
|
|
29
|
+
this._container = typeof container === 'string' ? document.querySelector(container) : container;
|
|
30
|
+
if (!this._container) throw new Error('OasisConfirmation: container not found');
|
|
31
|
+
if (!document.getElementById('oasis-conf-styles')) {
|
|
32
|
+
const s = document.createElement('style'); s.id = 'oasis-conf-styles'; s.textContent = CSS;
|
|
33
|
+
document.head.appendChild(s);
|
|
34
|
+
}
|
|
35
|
+
this._container.innerHTML = `
|
|
36
|
+
<div class="oasis-conf-shell">
|
|
37
|
+
<div class="oasis-conf-icon">${icon}</div>
|
|
38
|
+
<h2 class="oasis-conf-title">${title}</h2>
|
|
39
|
+
<p class="oasis-conf-body">${message}</p>
|
|
40
|
+
<div class="oasis-conf-actions">
|
|
41
|
+
<button class="oasis-conf-btn oasis-conf-btn--confirm" id="oasis-conf-confirm">${confirmLabel}</button>
|
|
42
|
+
<button class="oasis-conf-btn oasis-conf-btn--cancel" id="oasis-conf-cancel">${cancelLabel}</button>
|
|
43
|
+
</div>
|
|
44
|
+
</div>`;
|
|
45
|
+
document.getElementById('oasis-conf-confirm')?.addEventListener('click', onConfirm);
|
|
46
|
+
document.getElementById('oasis-conf-cancel')?.addEventListener('click', onCancel);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
destroy() { this._container.innerHTML = ''; }
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
window.OasisConfirmation = OasisConfirmation;
|
|
53
|
+
})();
|
package/src/contact.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OasisContact — standalone Contact form widget
|
|
3
|
+
* Usage: new OasisContact({ container: document.getElementById('contact') })
|
|
4
|
+
*/
|
|
5
|
+
(function () {
|
|
6
|
+
const CSS = `
|
|
7
|
+
.oasis-contact-shell{font-family:'Rajdhani',sans-serif;display:flex;flex-direction:column;gap:18px}
|
|
8
|
+
.oasis-contact-header{text-align:center}
|
|
9
|
+
.oasis-contact-title{font-family:'Orbitron',sans-serif;font-size:20px;color:#fff;margin:0 0 6px}
|
|
10
|
+
.oasis-contact-sub{font-size:13px;color:#7a9bbf;margin:0}
|
|
11
|
+
.oasis-contact-grid2{display:grid;grid-template-columns:1fr 1fr;gap:14px}
|
|
12
|
+
.oasis-contact-field{display:flex;flex-direction:column;gap:6px}
|
|
13
|
+
.oasis-contact-label{font-size:12px;font-weight:600;letter-spacing:.06em;color:#7a9bbf;text-transform:uppercase}
|
|
14
|
+
.oasis-contact-input,.oasis-contact-textarea{width:100%;background:rgba(255,255,255,.05);border:1px solid rgba(0,200,255,.2);border-radius:8px;padding:10px 14px;color:#fff;font-size:14px;outline:none;box-sizing:border-box;font-family:inherit;transition:border-color .2s}
|
|
15
|
+
.oasis-contact-input:focus,.oasis-contact-textarea:focus{border-color:rgba(0,200,255,.5)}
|
|
16
|
+
.oasis-contact-textarea{resize:vertical;min-height:100px}
|
|
17
|
+
.oasis-contact-btn{background:linear-gradient(135deg,#00c8ff,#0080ff);border:none;border-radius:8px;color:#fff;font-family:'Orbitron',sans-serif;font-size:13px;font-weight:700;letter-spacing:.08em;padding:12px;cursor:pointer;transition:opacity .2s;width:100%}
|
|
18
|
+
.oasis-contact-btn:disabled{opacity:.5;cursor:not-allowed}
|
|
19
|
+
.oasis-contact-success{background:rgba(72,220,130,.12);border:1px solid rgba(72,220,130,.3);color:#48dc82;border-radius:8px;padding:10px 14px;font-size:13px}
|
|
20
|
+
.oasis-contact-error{background:rgba(255,80,80,.12);border:1px solid rgba(255,80,80,.3);color:#ff6b6b;border-radius:8px;padding:10px 14px;font-size:13px}
|
|
21
|
+
`;
|
|
22
|
+
|
|
23
|
+
class OasisContact {
|
|
24
|
+
constructor({ container } = {}) {
|
|
25
|
+
this._container = typeof container === 'string' ? document.querySelector(container) : container;
|
|
26
|
+
if (!this._container) throw new Error('OasisContact: container not found');
|
|
27
|
+
if (!document.getElementById('oasis-contact-styles')) {
|
|
28
|
+
const s = document.createElement('style'); s.id = 'oasis-contact-styles'; s.textContent = CSS;
|
|
29
|
+
document.head.appendChild(s);
|
|
30
|
+
}
|
|
31
|
+
this._fields = { firstName: '', lastName: '', email: '', subject: '', message: '' };
|
|
32
|
+
this._loading = false;
|
|
33
|
+
this._sent = false;
|
|
34
|
+
this._error = '';
|
|
35
|
+
this._render();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
_render() {
|
|
39
|
+
if (this._sent) {
|
|
40
|
+
this._container.innerHTML = `<div class="oasis-contact-shell"><div class="oasis-contact-header"><h2 class="oasis-contact-title">Contact Us</h2></div><div class="oasis-contact-success">✅ Message sent! We'll be in touch soon.</div></div>`;
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const f = this._fields;
|
|
44
|
+
this._container.innerHTML = `
|
|
45
|
+
<div class="oasis-contact-shell">
|
|
46
|
+
<div class="oasis-contact-header">
|
|
47
|
+
<h2 class="oasis-contact-title">✉️ Contact Us</h2>
|
|
48
|
+
<p class="oasis-contact-sub">Get in touch with the OASIS team.</p>
|
|
49
|
+
</div>
|
|
50
|
+
${this._error ? `<div class="oasis-contact-error">${this._error}</div>` : ''}
|
|
51
|
+
<div class="oasis-contact-grid2">
|
|
52
|
+
<div class="oasis-contact-field"><label class="oasis-contact-label">First Name</label><input class="oasis-contact-input" data-field="firstName" value="${f.firstName}" placeholder="John" /></div>
|
|
53
|
+
<div class="oasis-contact-field"><label class="oasis-contact-label">Last Name</label><input class="oasis-contact-input" data-field="lastName" value="${f.lastName}" placeholder="Doe" /></div>
|
|
54
|
+
</div>
|
|
55
|
+
<div class="oasis-contact-field"><label class="oasis-contact-label">Email</label><input class="oasis-contact-input" type="email" data-field="email" value="${f.email}" placeholder="name@example.com" /></div>
|
|
56
|
+
<div class="oasis-contact-field"><label class="oasis-contact-label">Subject</label><input class="oasis-contact-input" data-field="subject" value="${f.subject}" placeholder="How can we help?" /></div>
|
|
57
|
+
<div class="oasis-contact-field"><label class="oasis-contact-label">Message</label><textarea class="oasis-contact-textarea" data-field="message" placeholder="Your message…">${f.message}</textarea></div>
|
|
58
|
+
<button class="oasis-contact-btn" id="oasis-contact-submit" ${this._loading ? 'disabled' : ''}>${this._loading ? 'Sending…' : 'Send Message'}</button>
|
|
59
|
+
</div>`;
|
|
60
|
+
this._container.querySelectorAll('[data-field]').forEach(el => {
|
|
61
|
+
el.addEventListener('input', () => { this._fields[el.dataset.field] = el.value; });
|
|
62
|
+
});
|
|
63
|
+
document.getElementById('oasis-contact-submit')?.addEventListener('click', () => this._submit());
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async _submit() {
|
|
67
|
+
if (!this._fields.email || !this._fields.message) { this._error = 'Please fill in your email and message.'; this._render(); return; }
|
|
68
|
+
this._loading = true; this._error = ''; this._render();
|
|
69
|
+
try {
|
|
70
|
+
await fetch('https://formsubmit.co/ajax/davidellams@hotmail.com', {
|
|
71
|
+
method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
|
72
|
+
body: JSON.stringify(this._fields),
|
|
73
|
+
});
|
|
74
|
+
this._sent = true;
|
|
75
|
+
} catch (e) { this._error = e?.message || 'Send failed. Please try again.'; }
|
|
76
|
+
this._loading = false;
|
|
77
|
+
this._render();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
destroy() { this._container.innerHTML = ''; }
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
window.OasisContact = OasisContact;
|
|
84
|
+
})();
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OasisCrossChainManagement — manage cross-chain data replication popup widget
|
|
3
|
+
* Usage: const w = new OasisCrossChainManagement({}); w.open();
|
|
4
|
+
*/
|
|
5
|
+
class OasisCrossChainManagement {
|
|
6
|
+
constructor({ container, onClose = null } = {}) {
|
|
7
|
+
this._onClose = onClose; this._overlay = null;
|
|
8
|
+
this._injectStyles(); if (container) this._render(container);
|
|
9
|
+
}
|
|
10
|
+
_injectStyles() {
|
|
11
|
+
if (document.getElementById('oasis-popup-styles')) return;
|
|
12
|
+
const s = document.createElement('style'); s.id = 'oasis-popup-styles';
|
|
13
|
+
s.textContent = `.oasis-popup-overlay{position:fixed;inset:0;z-index:9000;background:rgba(0,0,0,.65);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .25s}.oasis-popup-overlay.is-open{opacity:1}.oasis-popup-modal{background:#0a1628;border:1px solid rgba(0,200,255,.2);border-radius:16px;box-shadow:0 24px 64px rgba(0,0,0,.6);width:90%;max-width:680px;max-height:90vh;overflow-y:auto;transform:translateY(16px);transition:transform .25s}.oasis-popup-overlay.is-open .oasis-popup-modal{transform:none}.oasis-popup-header{display:flex;align-items:center;justify-content:space-between;padding:20px 24px;border-bottom:1px solid rgba(0,200,255,.1)}.oasis-popup-title{font-family:'Orbitron',sans-serif;font-size:14px;font-weight:700;color:#00c8ff;letter-spacing:.08em}.oasis-popup-close{background:none;border:none;color:#7a9bbf;font-size:22px;cursor:pointer;padding:0;line-height:1}.oasis-popup-close:hover{color:#fff}.oasis-popup-body{padding:24px}.oasis-info-block{background:rgba(0,200,255,.05);border:1px solid rgba(0,200,255,.1);border-radius:10px;padding:16px;margin-bottom:12px}.oasis-info-label{font-size:10px;font-weight:600;letter-spacing:.06em;color:#7a9bbf;text-transform:uppercase;margin-bottom:4px}.oasis-info-value{color:#fff;font-size:14px;font-weight:500}.oasis-badge{display:inline-block;padding:3px 8px;border-radius:999px;font-size:10px;font-weight:700}.oasis-badge-blue{background:rgba(0,200,255,.15);color:#00c8ff}.oasis-badge-green{background:rgba(0,200,100,.15);color:#00c864}.oasis-badge-red{background:rgba(255,80,80,.15);color:#ff6b6b}.oasis-btn{background:linear-gradient(135deg,#00c8ff,#0080ff);border:none;border-radius:8px;color:#fff;font-family:'Orbitron',sans-serif;font-size:12px;font-weight:700;letter-spacing:.08em;padding:11px 20px;cursor:pointer;transition:opacity .2s}.oasis-btn:hover{opacity:.85}.oasis-section-title{font-size:11px;font-weight:700;color:#7a9bbf;letter-spacing:.08em;text-transform:uppercase;margin:0 0 12px}.oasis-cs{text-align:center;padding:32px 16px}.oasis-cs-icon{font-size:48px;margin-bottom:12px}.oasis-cs h3{font-family:'Orbitron',sans-serif;font-size:15px;color:#00c8ff;margin:0 0 8px}.oasis-cs p{color:#7a9bbf;font-size:13px;margin:0}`;
|
|
14
|
+
document.head.appendChild(s);
|
|
15
|
+
}
|
|
16
|
+
open() {
|
|
17
|
+
if (this._overlay) return;
|
|
18
|
+
this._overlay = document.createElement('div');
|
|
19
|
+
this._overlay.className = 'oasis-popup-overlay';
|
|
20
|
+
this._overlay.innerHTML = `<div class="oasis-popup-modal"><div class="oasis-popup-header"><span class="oasis-popup-title">Cross-Chain Management</span><button class="oasis-popup-close">×</button></div><div class="oasis-popup-body">${this._buildBody()}</div></div>`;
|
|
21
|
+
this._overlay.querySelector('.oasis-popup-close').addEventListener('click', () => this.close());
|
|
22
|
+
this._overlay.addEventListener('click', e => { if (e.target === this._overlay) this.close(); });
|
|
23
|
+
document.body.appendChild(this._overlay);
|
|
24
|
+
requestAnimationFrame(() => this._overlay.classList.add('is-open'));
|
|
25
|
+
}
|
|
26
|
+
_buildBody() {
|
|
27
|
+
const chains = [{ name: 'Ethereum', status: 'active' }, { name: 'Holochain', status: 'active' }, { name: 'IPFS', status: 'inactive' }, { name: 'Solana', status: 'inactive' }, { name: 'ThreeFold', status: 'inactive' }];
|
|
28
|
+
return `<p class="oasis-section-title">Chain Sync Status</p>
|
|
29
|
+
${chains.map(c => `<div class="oasis-info-block" style="display:flex;align-items:center;justify-content:space-between"><div><div class="oasis-info-label">${c.name}</div><div class="oasis-info-value">Data replication ${c.status === 'active' ? 'enabled' : 'disabled'}</div></div><span class="oasis-badge ${c.status === 'active' ? 'oasis-badge-green' : 'oasis-badge-red'}">${c.status}</span></div>`).join('')}
|
|
30
|
+
<div style="text-align:right;margin-top:16px"><button class="oasis-btn" onclick="this.textContent='Syncing…';setTimeout(()=>this.textContent='Sync All',1500)">Sync All Chains</button></div>`;
|
|
31
|
+
}
|
|
32
|
+
close() { if (!this._overlay) return; const el = this._overlay; this._overlay = null; el.classList.remove('is-open'); el.addEventListener('transitionend', () => el.remove(), { once: true }); if (this._onClose) this._onClose(); }
|
|
33
|
+
_render(c) { c.innerHTML = `<div class="oasis-popup-body">${this._buildBody()}</div>`; }
|
|
34
|
+
destroy() { this.close(); }
|
|
35
|
+
}
|
|
36
|
+
window.OasisCrossChainManagement = OasisCrossChainManagement;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OasisEditAvatar — edit avatar profile popup widget
|
|
3
|
+
* Usage: const w = new OasisEditAvatar({ avatarId: '...', onSave: (data) => {} }); w.open();
|
|
4
|
+
*/
|
|
5
|
+
class OasisEditAvatar {
|
|
6
|
+
constructor({ container, avatarId = '', apiUrl = 'https://api.web4.oasisomniverse.one', onSave = null, onClose = null } = {}) {
|
|
7
|
+
this._avatarId = avatarId; this._apiUrl = apiUrl; this._onSave = onSave; this._onClose = onClose; this._overlay = null;
|
|
8
|
+
this._injectStyles();
|
|
9
|
+
if (container) this._render(container);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
_injectStyles() {
|
|
13
|
+
if (document.getElementById('oasis-popup-styles')) return;
|
|
14
|
+
const s = document.createElement('style'); s.id = 'oasis-popup-styles';
|
|
15
|
+
s.textContent = `.oasis-popup-overlay{position:fixed;inset:0;z-index:9000;background:rgba(0,0,0,.65);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .25s}.oasis-popup-overlay.is-open{opacity:1}.oasis-popup-modal{background:#0a1628;border:1px solid rgba(0,200,255,.2);border-radius:16px;box-shadow:0 24px 64px rgba(0,0,0,.6);width:90%;max-width:560px;max-height:90vh;overflow-y:auto;transform:translateY(16px);transition:transform .25s}.oasis-popup-overlay.is-open .oasis-popup-modal{transform:none}.oasis-popup-modal.lg{max-width:900px}.oasis-popup-header{display:flex;align-items:center;justify-content:space-between;padding:20px 24px;border-bottom:1px solid rgba(0,200,255,.1)}.oasis-popup-title{font-family:'Orbitron',sans-serif;font-size:14px;font-weight:700;color:#00c8ff;letter-spacing:.08em}.oasis-popup-close{background:none;border:none;color:#7a9bbf;font-size:22px;cursor:pointer;padding:0;line-height:1}.oasis-popup-close:hover{color:#fff}.oasis-popup-body{padding:24px}.oasis-field{display:flex;flex-direction:column;gap:6px;margin-bottom:16px}.oasis-label{font-size:11px;font-weight:600;letter-spacing:.06em;color:#7a9bbf;text-transform:uppercase}.oasis-input,.oasis-select,.oasis-textarea{background:rgba(255,255,255,.05);border:1px solid rgba(0,200,255,.2);border-radius:8px;padding:10px 14px;color:#fff;font-size:14px;outline:none;transition:border-color .2s;width:100%;box-sizing:border-box}.oasis-input:focus,.oasis-select:focus,.oasis-textarea:focus{border-color:rgba(0,200,255,.5)}.oasis-textarea{resize:vertical;min-height:80px}.oasis-select option{background:#0a1628}.oasis-btn{background:linear-gradient(135deg,#00c8ff,#0080ff);border:none;border-radius:8px;color:#fff;font-family:'Orbitron',sans-serif;font-size:12px;font-weight:700;letter-spacing:.08em;padding:11px 20px;cursor:pointer;transition:opacity .2s}.oasis-btn:hover{opacity:.85}.oasis-btn:disabled{opacity:.5;cursor:not-allowed}.oasis-btn-ghost{background:rgba(0,200,255,.1);border:1px solid rgba(0,200,255,.3);color:#00c8ff;border-radius:8px;font-size:12px;font-weight:600;padding:9px 16px;cursor:pointer}.oasis-btn-row{display:flex;gap:10px;justify-content:flex-end;margin-top:20px}.oasis-msg{border-radius:8px;padding:10px 14px;font-size:13px;margin-bottom:16px}.oasis-msg-error{background:rgba(255,80,80,.12);border:1px solid rgba(255,80,80,.3);color:#ff6b6b}.oasis-msg-success{background:rgba(0,200,100,.12);border:1px solid rgba(0,200,100,.3);color:#00c864}.oasis-grid-2{display:grid;grid-template-columns:1fr 1fr;gap:16px}.oasis-info-block{background:rgba(0,200,255,.05);border:1px solid rgba(0,200,255,.1);border-radius:10px;padding:16px;margin-bottom:12px}.oasis-info-label{font-size:10px;font-weight:600;letter-spacing:.06em;color:#7a9bbf;text-transform:uppercase;margin-bottom:4px}.oasis-info-value{color:#fff;font-size:14px;font-weight:500}.oasis-cs{text-align:center;padding:32px 16px}.oasis-cs-icon{font-size:48px;margin-bottom:12px}.oasis-cs h3{font-family:'Orbitron',sans-serif;font-size:15px;color:#00c8ff;margin:0 0 8px}.oasis-cs p{color:#7a9bbf;font-size:13px;margin:0}.oasis-table{width:100%;border-collapse:collapse;font-size:13px}.oasis-table th{text-align:left;padding:10px 12px;font-size:10px;font-weight:700;letter-spacing:.06em;color:#7a9bbf;text-transform:uppercase;border-bottom:1px solid rgba(0,200,255,.1)}.oasis-table td{padding:10px 12px;color:#fff;border-bottom:1px solid rgba(255,255,255,.05)}.oasis-badge{display:inline-block;padding:3px 8px;border-radius:999px;font-size:10px;font-weight:700}.oasis-badge-blue{background:rgba(0,200,255,.15);color:#00c8ff}.oasis-badge-green{background:rgba(0,200,100,.15);color:#00c864}.oasis-badge-red{background:rgba(255,80,80,.15);color:#ff6b6b}.oasis-search-row{display:flex;gap:10px;margin-bottom:16px}.oasis-search-row .oasis-input{flex:1}.oasis-stat-row{display:flex;gap:12px;margin-bottom:20px}.oasis-stat{flex:1;background:rgba(0,200,255,.05);border:1px solid rgba(0,200,255,.1);border-radius:10px;padding:14px;text-align:center}.oasis-stat-val{font-family:'Orbitron',sans-serif;font-size:20px;font-weight:700;color:#00c8ff}.oasis-stat-lbl{font-size:10px;color:#7a9bbf;margin-top:4px}.oasis-divider{border:none;border-top:1px solid rgba(0,200,255,.1);margin:16px 0}.oasis-section-title{font-size:11px;font-weight:700;color:#7a9bbf;letter-spacing:.08em;text-transform:uppercase;margin:0 0 12px}.oasis-radio-group{display:flex;gap:16px;margin-bottom:16px}.oasis-radio-label{display:flex;align-items:center;gap:8px;font-size:13px;color:#fff;cursor:pointer}.oasis-radio-label input[type=radio]{accent-color:#00c8ff}.oasis-link{background:none;border:none;color:#00c8ff;font-size:13px;cursor:pointer;padding:0;text-decoration:underline}.oasis-chat-area{background:rgba(0,0,0,.2);border:1px solid rgba(0,200,255,.1);border-radius:10px;height:220px;overflow-y:auto;padding:12px;margin-bottom:12px;display:flex;flex-direction:column;gap:8px}.oasis-chat-bubble{background:rgba(0,200,255,.1);border-radius:10px;padding:8px 12px;font-size:13px;color:#fff;max-width:75%}.oasis-chat-bubble.mine{background:rgba(0,128,255,.2);align-self:flex-end}.oasis-chat-input-row{display:flex;gap:8px}.oasis-chat-input-row .oasis-input{flex:1}`;
|
|
16
|
+
document.head.appendChild(s);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
open() {
|
|
20
|
+
if (this._overlay) return;
|
|
21
|
+
this._overlay = document.createElement('div');
|
|
22
|
+
this._overlay.className = 'oasis-popup-overlay';
|
|
23
|
+
this._overlay.innerHTML = `<div class="oasis-popup-modal">
|
|
24
|
+
<div class="oasis-popup-header"><span class="oasis-popup-title">Edit Avatar</span><button class="oasis-popup-close">×</button></div>
|
|
25
|
+
<div class="oasis-popup-body">${this._buildBody()}</div>
|
|
26
|
+
</div>`;
|
|
27
|
+
this._overlay.querySelector('.oasis-popup-close').addEventListener('click', () => this.close());
|
|
28
|
+
this._overlay.addEventListener('click', e => { if (e.target === this._overlay) this.close(); });
|
|
29
|
+
document.body.appendChild(this._overlay);
|
|
30
|
+
requestAnimationFrame(() => this._overlay.classList.add('is-open'));
|
|
31
|
+
this._overlay.querySelector('#oasis-ea-save').addEventListener('click', () => this._doSave());
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
_buildBody() {
|
|
35
|
+
return `
|
|
36
|
+
<div id="oasis-ea-msg"></div>
|
|
37
|
+
<div class="oasis-grid-2">
|
|
38
|
+
<div class="oasis-field"><label class="oasis-label">First Name</label><input class="oasis-input" id="oasis-ea-first" type="text" placeholder="First" /></div>
|
|
39
|
+
<div class="oasis-field"><label class="oasis-label">Last Name</label><input class="oasis-input" id="oasis-ea-last" type="text" placeholder="Last" /></div>
|
|
40
|
+
</div>
|
|
41
|
+
<div class="oasis-field"><label class="oasis-label">Username</label><input class="oasis-input" id="oasis-ea-user" type="text" placeholder="username" /></div>
|
|
42
|
+
<div class="oasis-field"><label class="oasis-label">Email</label><input class="oasis-input" id="oasis-ea-email" type="email" placeholder="you@example.com" /></div>
|
|
43
|
+
<div class="oasis-field"><label class="oasis-label">Bio</label><textarea class="oasis-textarea" id="oasis-ea-bio" placeholder="Tell the world about yourself…"></textarea></div>
|
|
44
|
+
<div class="oasis-field"><label class="oasis-label">Avatar Image URL</label><input class="oasis-input" id="oasis-ea-img" type="url" placeholder="https://…" /></div>
|
|
45
|
+
<div class="oasis-btn-row"><button class="oasis-btn-ghost" onclick="this.closest('.oasis-popup-overlay')?.remove()">Cancel</button><button class="oasis-btn" id="oasis-ea-save">Save Changes</button></div>
|
|
46
|
+
`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async _doSave() {
|
|
50
|
+
const f = (id) => this._overlay.querySelector(id)?.value.trim();
|
|
51
|
+
const msgEl = this._overlay.querySelector('#oasis-ea-msg');
|
|
52
|
+
const btn = this._overlay.querySelector('#oasis-ea-save');
|
|
53
|
+
btn.textContent = 'Saving…'; btn.disabled = true;
|
|
54
|
+
try {
|
|
55
|
+
const res = await fetch(`${this._apiUrl}/api/avatar/${this._avatarId}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ firstName: f('#oasis-ea-first'), lastName: f('#oasis-ea-last'), username: f('#oasis-ea-user'), email: f('#oasis-ea-email'), description: f('#oasis-ea-bio'), avatarImageUrl: f('#oasis-ea-img') }) });
|
|
56
|
+
const data = await res.json();
|
|
57
|
+
if (!res.ok || data.isError) throw new Error(data.message || 'Save failed');
|
|
58
|
+
msgEl.innerHTML = '<div class="oasis-msg oasis-msg-success">Avatar updated successfully!</div>';
|
|
59
|
+
if (this._onSave) this._onSave(data);
|
|
60
|
+
btn.textContent = 'Saved';
|
|
61
|
+
} catch (e) {
|
|
62
|
+
msgEl.innerHTML = `<div class="oasis-msg oasis-msg-error">${e.message}</div>`;
|
|
63
|
+
btn.textContent = 'Save Changes'; btn.disabled = false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
close() {
|
|
68
|
+
if (!this._overlay) return;
|
|
69
|
+
const el = this._overlay; this._overlay = null;
|
|
70
|
+
el.classList.remove('is-open');
|
|
71
|
+
el.addEventListener('transitionend', () => el.remove(), { once: true });
|
|
72
|
+
if (this._onClose) this._onClose();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
_render(container) { container.innerHTML = `<div class="oasis-popup-body">${this._buildBody()}</div>`; }
|
|
76
|
+
destroy() { this.close(); }
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
window.OasisEditAvatar = OasisEditAvatar;
|