uai-direct 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/index.html ADDED
@@ -0,0 +1,26 @@
1
+ <!doctype html>
2
+ <html lang="en" style="margin: 0; padding: 0; width: 100%; height: 100%; overflow: hidden; background-color: #ffffff;">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/png" href="/assets/logo.png" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
7
+ <meta name="theme-color" content="#ffffff" />
8
+ <title>SAMPARK - Single Administrative Management Portal for Access, Resources and Knowledge</title>
9
+ <style>
10
+ * { box-sizing: border-box; }
11
+ html, body, #root {
12
+ width: 100%;
13
+ height: 100%;
14
+ margin: 0;
15
+ padding: 0;
16
+ overflow: hidden;
17
+ background-color: #ffffff;
18
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
19
+ }
20
+ </style>
21
+ </head>
22
+ <body style="margin: 0; padding: 0; width: 100%; height: 100%; overflow: hidden;">
23
+ <div id="root"></div>
24
+ <script type="module" src="/src/main.tsx"></script>
25
+ </body>
26
+ </html>
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "uai-direct",
3
+ "version": "1.0.0",
4
+ "description": "SAMPARK - Unified Administrative Interface Host Embedding Container",
5
+ "type": "module",
6
+ "bin": {
7
+ "uai-direct": "bin/cli.js"
8
+ },
9
+ "scripts": {
10
+ "dev": "vite",
11
+ "build": "vite build",
12
+ "preview": "vite preview",
13
+ "configure": "node bin/cli.js"
14
+ },
15
+ "files": [
16
+ "bin",
17
+ "dist",
18
+ "src",
19
+ "public",
20
+ "index.html",
21
+ "firebase.json",
22
+ ".firebaserc",
23
+ "vite.config.ts",
24
+ "tsconfig.json"
25
+ ],
26
+ "dependencies": {
27
+ "react": "^19.0.0",
28
+ "react-dom": "^19.0.0"
29
+ },
30
+ "devDependencies": {
31
+ "@types/node": "^24.0.0",
32
+ "@types/react": "^19.0.0",
33
+ "@types/react-dom": "^19.0.0",
34
+ "@vitejs/plugin-react": "^4.3.4",
35
+ "typescript": "^5.7.0",
36
+ "vite": "^6.0.0"
37
+ }
38
+ }
Binary file
Binary file
@@ -0,0 +1,24 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg">
2
+ <symbol id="bluesky-icon" viewBox="0 0 16 17">
3
+ <g clip-path="url(#bluesky-clip)"><path fill="#08060d" d="M7.75 7.735c-.693-1.348-2.58-3.86-4.334-5.097-1.68-1.187-2.32-.981-2.74-.79C.188 2.065.1 2.812.1 3.251s.241 3.602.398 4.13c.52 1.744 2.367 2.333 4.07 2.145-2.495.37-4.71 1.278-1.805 4.512 3.196 3.309 4.38-.71 4.987-2.746.608 2.036 1.307 5.91 4.93 2.746 2.72-2.746.747-4.143-1.747-4.512 1.702.189 3.55-.4 4.07-2.145.156-.528.397-3.691.397-4.13s-.088-1.186-.575-1.406c-.42-.19-1.06-.395-2.741.79-1.755 1.24-3.64 3.752-4.334 5.099"/></g>
4
+ <defs><clipPath id="bluesky-clip"><path fill="#fff" d="M.1.85h15.3v15.3H.1z"/></clipPath></defs>
5
+ </symbol>
6
+ <symbol id="discord-icon" viewBox="0 0 20 19">
7
+ <path fill="#08060d" d="M16.224 3.768a14.5 14.5 0 0 0-3.67-1.153c-.158.286-.343.67-.47.976a13.5 13.5 0 0 0-4.067 0c-.128-.306-.317-.69-.476-.976A14.4 14.4 0 0 0 3.868 3.77C1.546 7.28.916 10.703 1.231 14.077a14.7 14.7 0 0 0 4.5 2.306q.545-.748.965-1.587a9.5 9.5 0 0 1-1.518-.74q.191-.14.372-.293c2.927 1.369 6.107 1.369 8.999 0q.183.152.372.294-.723.437-1.52.74.418.838.963 1.588a14.6 14.6 0 0 0 4.504-2.308c.37-3.911-.63-7.302-2.644-10.309m-9.13 8.234c-.878 0-1.599-.82-1.599-1.82 0-.998.705-1.82 1.6-1.82.894 0 1.614.82 1.599 1.82.001 1-.705 1.82-1.6 1.82m5.91 0c-.878 0-1.599-.82-1.599-1.82 0-.998.705-1.82 1.6-1.82.893 0 1.614.82 1.599 1.82 0 1-.706 1.82-1.6 1.82"/>
8
+ </symbol>
9
+ <symbol id="documentation-icon" viewBox="0 0 21 20">
10
+ <path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="m15.5 13.333 1.533 1.322c.645.555.967.833.967 1.178s-.322.623-.967 1.179L15.5 18.333m-3.333-5-1.534 1.322c-.644.555-.966.833-.966 1.178s.322.623.966 1.179l1.534 1.321"/>
11
+ <path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M17.167 10.836v-4.32c0-1.41 0-2.117-.224-2.68-.359-.906-1.118-1.621-2.08-1.96-.599-.21-1.349-.21-2.848-.21-2.623 0-3.935 0-4.983.369-1.684.591-3.013 1.842-3.641 3.428C3 6.449 3 7.684 3 10.154v2.122c0 2.558 0 3.838.706 4.726q.306.383.713.671c.76.536 1.79.64 3.581.66"/>
12
+ <path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M3 10a2.78 2.78 0 0 1 2.778-2.778c.555 0 1.209.097 1.748-.047.48-.129.854-.503.982-.982.145-.54.048-1.194.048-1.749a2.78 2.78 0 0 1 2.777-2.777"/>
13
+ </symbol>
14
+ <symbol id="github-icon" viewBox="0 0 19 19">
15
+ <path fill="#08060d" fill-rule="evenodd" d="M9.356 1.85C5.05 1.85 1.57 5.356 1.57 9.694a7.84 7.84 0 0 0 5.324 7.44c.387.079.528-.168.528-.376 0-.182-.013-.805-.013-1.454-2.165.467-2.616-.935-2.616-.935-.349-.91-.864-1.143-.864-1.143-.71-.48.051-.48.051-.48.787.051 1.2.805 1.2.805.695 1.194 1.817.857 2.268.649.064-.507.27-.857.49-1.052-1.728-.182-3.545-.857-3.545-3.87 0-.857.31-1.558.8-2.104-.078-.195-.349-1 .077-2.078 0 0 .657-.208 2.14.805a7.5 7.5 0 0 1 1.946-.26c.657 0 1.328.092 1.946.26 1.483-1.013 2.14-.805 2.14-.805.426 1.078.155 1.883.078 2.078.502.546.799 1.247.799 2.104 0 3.013-1.818 3.675-3.558 3.87.284.247.528.714.528 1.454 0 1.052-.012 1.896-.012 2.156 0 .208.142.455.528.377a7.84 7.84 0 0 0 5.324-7.441c.013-4.338-3.48-7.844-7.773-7.844" clip-rule="evenodd"/>
16
+ </symbol>
17
+ <symbol id="social-icon" viewBox="0 0 20 20">
18
+ <path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M12.5 6.667a4.167 4.167 0 1 0-8.334 0 4.167 4.167 0 0 0 8.334 0"/>
19
+ <path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M2.5 16.667a5.833 5.833 0 0 1 8.75-5.053m3.837.474.513 1.035c.07.144.257.282.414.309l.93.155c.596.1.736.536.307.965l-.723.73a.64.64 0 0 0-.152.531l.207.903c.164.715-.213.991-.84.618l-.872-.52a.63.63 0 0 0-.577 0l-.872.52c-.624.373-1.003.094-.84-.618l.207-.903a.64.64 0 0 0-.152-.532l-.723-.729c-.426-.43-.289-.864.306-.964l.93-.156a.64.64 0 0 0 .412-.31l.513-1.034c.28-.562.735-.562 1.012 0"/>
20
+ </symbol>
21
+ <symbol id="x-icon" viewBox="0 0 19 19">
22
+ <path fill="#08060d" fill-rule="evenodd" d="M1.893 1.98c.052.072 1.245 1.769 2.653 3.77l2.892 4.114c.183.261.333.48.333.486s-.068.089-.152.183l-.522.593-.765.867-3.597 4.087c-.375.426-.734.834-.798.905a1 1 0 0 0-.118.148c0 .01.236.017.664.017h.663l.729-.83c.4-.457.796-.906.879-.999a692 692 0 0 0 1.794-2.038c.034-.037.301-.34.594-.675l.551-.624.345-.392a7 7 0 0 1 .34-.374c.006 0 .93 1.306 2.052 2.903l2.084 2.965.045.063h2.275c1.87 0 2.273-.003 2.266-.021-.008-.02-1.098-1.572-3.894-5.547-2.013-2.862-2.28-3.246-2.273-3.266.008-.019.282-.332 2.085-2.38l2-2.274 1.567-1.782c.022-.028-.016-.03-.65-.03h-.674l-.3.342a871 871 0 0 1-1.782 2.025c-.067.075-.405.458-.75.852a100 100 0 0 1-.803.91c-.148.172-.299.344-.99 1.127-.304.343-.32.358-.345.327-.015-.019-.904-1.282-1.976-2.808L6.365 1.85H1.8zm1.782.91 8.078 11.294c.772 1.08 1.413 1.973 1.425 1.984.016.017.241.02 1.05.017l1.03-.004-2.694-3.766L7.796 5.75 5.722 2.852l-1.039-.004-1.039-.004z" clip-rule="evenodd"/>
23
+ </symbol>
24
+ </svg>
Binary file
Binary file
Binary file
package/src/App.tsx ADDED
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { UAIContainer } from './components/UAIContainer';
3
+
4
+ function App() {
5
+ return <UAIContainer />;
6
+ }
7
+
8
+ export default App;
Binary file
Binary file
@@ -0,0 +1,370 @@
1
+ import React, { useState, useEffect, useRef } from 'react';
2
+ import uaiConfig from '../uai.config.json';
3
+
4
+ // Target URL is strictly fixed to https://unifiedadministrativeinterface.web.app
5
+ const UAI_TARGET_BASE = 'https://unifiedadministrativeinterface.web.app';
6
+
7
+ interface AcronymStep {
8
+ highlightIndex: number | null;
9
+ word: string;
10
+ }
11
+
12
+ export const UAIContainer: React.FC = () => {
13
+ const [activeStepIndex, setActiveStepIndex] = useState<number>(0);
14
+ const [isCompleted, setIsCompleted] = useState<boolean>(false);
15
+ const [showSplash, setShowSplash] = useState(true);
16
+ const [splashFading, setSplashFading] = useState(false);
17
+ const [iframeSrc, setIframeSrc] = useState(UAI_TARGET_BASE);
18
+ const [isHostBarVisible, setIsHostBarVisible] = useState(false);
19
+ const iframeRef = useRef<HTMLIFrameElement>(null);
20
+
21
+ // Dynamic configuration loaded from uai.config.json
22
+ const platformName = uaiConfig.platformName || 'SAMPARK';
23
+ const themeColor = uaiConfig.themeColor || '#ea580c';
24
+ const themeSecondary = uaiConfig.themeSecondary || '#f97316';
25
+ const fullForm = uaiConfig.fullForm || '';
26
+ const sequenceSteps: AcronymStep[] = uaiConfig.sequenceSteps || [];
27
+
28
+ const platformLetters = platformName.split('');
29
+
30
+ // Helper function to build fresh URL ensuring most recent deployed build is loaded
31
+ const buildFreshTargetUrl = () => {
32
+ const currentSearch = window.location.search;
33
+ const currentHash = window.location.hash;
34
+ const currentPath = window.location.pathname !== '/' ? window.location.pathname : '';
35
+
36
+ // Add cache buster parameter to bypass stale browser iframe cache & fetch latest deployment
37
+ const cacheBuster = `_uai_t=${Date.now()}`;
38
+ const separator = currentSearch ? '&' : '?';
39
+ const freshSearch = `${currentSearch}${separator}${cacheBuster}`;
40
+
41
+ return `${UAI_TARGET_BASE}${currentPath}${freshSearch}${currentHash}`;
42
+ };
43
+
44
+ // Preserve current query parameters and hash fragment with cache buster on mount
45
+ useEffect(() => {
46
+ setIframeSrc(buildFreshTargetUrl());
47
+ }, []);
48
+
49
+ // Sequential animation timer (~290ms per step)
50
+ useEffect(() => {
51
+ if (!sequenceSteps || sequenceSteps.length === 0) {
52
+ setIsCompleted(true);
53
+ setShowSplash(false);
54
+ return;
55
+ }
56
+
57
+ const stepDuration = 290;
58
+ const timer = setInterval(() => {
59
+ setActiveStepIndex((prev) => {
60
+ if (prev < sequenceSteps.length - 1) {
61
+ return prev + 1;
62
+ } else {
63
+ clearInterval(timer);
64
+ setIsCompleted(true);
65
+
66
+ // Hold briefly at end, then fade out splash screen
67
+ setTimeout(() => {
68
+ setSplashFading(true);
69
+ setTimeout(() => {
70
+ setShowSplash(false);
71
+ }, 500);
72
+ }, 700);
73
+ return prev;
74
+ }
75
+ });
76
+ }, stepDuration);
77
+
78
+ return () => clearInterval(timer);
79
+ }, [sequenceSteps.length]);
80
+
81
+ const reloadIframe = () => {
82
+ const freshUrl = buildFreshTargetUrl();
83
+ setIframeSrc(freshUrl);
84
+ if (iframeRef.current) {
85
+ iframeRef.current.src = freshUrl;
86
+ }
87
+ };
88
+
89
+ const currentStep = sequenceSteps[activeStepIndex] || sequenceSteps[0] || { highlightIndex: null, word: '' };
90
+
91
+ return (
92
+ <div style={{
93
+ position: 'fixed',
94
+ top: 0,
95
+ left: 0,
96
+ width: '100vw',
97
+ height: '100dvh',
98
+ margin: 0,
99
+ padding: 0,
100
+ overflow: 'hidden',
101
+ backgroundColor: '#ffffff',
102
+ zIndex: 999999
103
+ }}>
104
+ {/* Typography Splash Screen */}
105
+ {showSplash && (
106
+ <div style={{
107
+ position: 'absolute',
108
+ top: 0,
109
+ left: 0,
110
+ width: '100%',
111
+ height: '100%',
112
+ backgroundColor: '#ffffff',
113
+ display: 'flex',
114
+ flexDirection: 'column',
115
+ alignItems: 'center',
116
+ justifyContent: 'center',
117
+ zIndex: 99,
118
+ color: '#0f172a',
119
+ fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
120
+ opacity: splashFading ? 0 : 1,
121
+ transition: 'opacity 0.5s cubic-bezier(0.4, 0, 0.2, 1)',
122
+ pointerEvents: splashFading ? 'none' : 'auto',
123
+ padding: '24px',
124
+ boxSizing: 'border-box'
125
+ }}>
126
+ {/* Subtle Ambient Background Glow */}
127
+ <div style={{
128
+ position: 'absolute',
129
+ width: '600px',
130
+ height: '600px',
131
+ borderRadius: '50%',
132
+ background: `radial-gradient(circle, ${themeSecondary}18 0%, ${themeColor}05 50%, transparent 70%)`,
133
+ filter: 'blur(70px)',
134
+ pointerEvents: 'none'
135
+ }} />
136
+
137
+ {/* PURE TYPOGRAPHY LOGO HEADER */}
138
+ <h1 style={{
139
+ display: 'flex',
140
+ alignItems: 'center',
141
+ justifyContent: 'center',
142
+ gap: '10px',
143
+ margin: '0 0 32px 0',
144
+ userSelect: 'none',
145
+ letterSpacing: '0.12em'
146
+ }}>
147
+ {platformLetters.map((letter, index) => {
148
+ const isActive = !isCompleted && currentStep.highlightIndex === index;
149
+
150
+ return (
151
+ <span
152
+ key={index}
153
+ style={{
154
+ fontSize: isActive ? '4.2rem' : '3.4rem',
155
+ fontWeight: isActive || isCompleted ? 900 : 700,
156
+ color: isActive
157
+ ? themeColor
158
+ : isCompleted
159
+ ? themeSecondary
160
+ : '#1e293b',
161
+ transition: 'all 0.22s cubic-bezier(0.34, 1.56, 0.64, 1)',
162
+ display: 'inline-block',
163
+ transform: isActive ? 'translateY(-5px) scale(1.15)' : 'translateY(0) scale(1)',
164
+ textShadow: isActive
165
+ ? `0 10px 25px ${themeColor}60`
166
+ : isCompleted
167
+ ? `0 4px 12px ${themeSecondary}33`
168
+ : 'none'
169
+ }}
170
+ >
171
+ {letter}
172
+ </span>
173
+ );
174
+ })}
175
+ </h1>
176
+
177
+ {/* DYNAMIC WORD DISPLAY BELOW LOGO HEADER */}
178
+ <div style={{
179
+ minHeight: '70px',
180
+ display: 'flex',
181
+ alignItems: 'center',
182
+ justifyContent: 'center',
183
+ textAlign: 'center'
184
+ }}>
185
+ {!isCompleted ? (
186
+ <span
187
+ key={activeStepIndex}
188
+ style={{
189
+ fontSize: currentStep.highlightIndex !== null ? '2.1rem' : '1.75rem',
190
+ fontWeight: currentStep.highlightIndex !== null ? 700 : 500,
191
+ color: currentStep.highlightIndex !== null ? themeColor : '#475569',
192
+ letterSpacing: '0.02em',
193
+ fontStyle: currentStep.highlightIndex === null ? 'italic' : 'normal',
194
+ animation: 'popInText 0.25s cubic-bezier(0.16, 1, 0.3, 1) forwards'
195
+ }}
196
+ >
197
+ {currentStep.word}
198
+ </span>
199
+ ) : fullForm ? (
200
+ <p style={{
201
+ fontSize: '1.2rem',
202
+ fontWeight: 600,
203
+ color: themeColor,
204
+ maxWidth: '680px',
205
+ lineHeight: 1.5,
206
+ margin: 0,
207
+ letterSpacing: '0.01em',
208
+ animation: 'fadeInText 0.4s ease-out forwards'
209
+ }}>
210
+ ({fullForm})
211
+ </p>
212
+ ) : null}
213
+ </div>
214
+
215
+ {/* MINIMAL PROGRESS TRACK */}
216
+ {sequenceSteps.length > 0 && (
217
+ <div style={{
218
+ width: '240px',
219
+ height: '4px',
220
+ backgroundColor: `${themeSecondary}20`,
221
+ borderRadius: '2px',
222
+ overflow: 'hidden',
223
+ position: 'relative',
224
+ marginTop: '48px'
225
+ }}>
226
+ <div style={{
227
+ position: 'absolute',
228
+ height: '100%',
229
+ width: `${((activeStepIndex + 1) / sequenceSteps.length) * 100}%`,
230
+ backgroundColor: themeColor,
231
+ borderRadius: '2px',
232
+ transition: 'width 0.25s cubic-bezier(0.4, 0, 0.2, 1)'
233
+ }} />
234
+ </div>
235
+ )}
236
+ </div>
237
+ )}
238
+
239
+ {/* Embedded UAI Host Frame */}
240
+ <iframe
241
+ ref={iframeRef}
242
+ src={iframeSrc}
243
+ title={`${platformName} - Unified Administrative Interface`}
244
+ style={{
245
+ width: '100%',
246
+ height: '100%',
247
+ border: 'none',
248
+ outline: 'none',
249
+ margin: 0,
250
+ padding: 0,
251
+ display: 'block',
252
+ backgroundColor: '#ffffff'
253
+ }}
254
+ allow="camera; microphone; geolocation; payment; clipboard-read; clipboard-write; display-capture; autoplay; encrypted-media; fullscreen"
255
+ sandbox="allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts allow-top-navigation allow-downloads"
256
+ />
257
+
258
+ {/* Integration Host Badge */}
259
+ <div style={{
260
+ position: 'fixed',
261
+ bottom: '16px',
262
+ right: '16px',
263
+ zIndex: 1000000,
264
+ display: 'flex',
265
+ alignItems: 'center',
266
+ gap: '8px'
267
+ }}>
268
+ {isHostBarVisible && (
269
+ <div style={{
270
+ display: 'flex',
271
+ alignItems: 'center',
272
+ gap: '8px',
273
+ padding: '8px 14px',
274
+ borderRadius: '24px',
275
+ backgroundColor: 'rgba(255, 255, 255, 0.95)',
276
+ backdropFilter: 'blur(12px)',
277
+ border: `1px solid ${themeColor}33`,
278
+ boxShadow: `0 8px 24px ${themeColor}26`,
279
+ color: '#1e293b',
280
+ fontSize: '12px',
281
+ fontWeight: 500
282
+ }}>
283
+ <span style={{
284
+ width: '8px',
285
+ height: '8px',
286
+ borderRadius: '50%',
287
+ backgroundColor: themeColor,
288
+ boxShadow: `0 0 8px ${themeColor}`
289
+ }} />
290
+ <span>{platformName} • UAI Embedded</span>
291
+ <button
292
+ onClick={reloadIframe}
293
+ title="Fetch Latest Deployed Version"
294
+ style={{
295
+ background: 'none',
296
+ border: 'none',
297
+ color: themeColor,
298
+ cursor: 'pointer',
299
+ padding: '2px 4px',
300
+ fontSize: '14px',
301
+ lineHeight: 1
302
+ }}
303
+ >
304
+ 🔄
305
+ </button>
306
+ <a
307
+ href={iframeSrc}
308
+ target="_blank"
309
+ rel="noopener noreferrer"
310
+ title="Open standalone"
311
+ style={{
312
+ color: themeColor,
313
+ textDecoration: 'none',
314
+ padding: '2px 4px',
315
+ fontSize: '14px',
316
+ lineHeight: 1
317
+ }}
318
+ >
319
+
320
+ </a>
321
+ </div>
322
+ )}
323
+ <button
324
+ onClick={() => setIsHostBarVisible(!isHostBarVisible)}
325
+ title="Toggle Host Info"
326
+ style={{
327
+ width: '32px',
328
+ height: '32px',
329
+ borderRadius: '50%',
330
+ backgroundColor: 'rgba(255, 255, 255, 0.95)',
331
+ border: `1px solid ${themeColor}40`,
332
+ color: themeColor,
333
+ display: 'flex',
334
+ alignItems: 'center',
335
+ justifyContent: 'center',
336
+ cursor: 'pointer',
337
+ fontSize: '14px',
338
+ backdropFilter: 'blur(8px)',
339
+ boxShadow: `0 4px 12px ${themeColor}20`
340
+ }}
341
+ >
342
+ {isHostBarVisible ? '✕' : 'ℹ'}
343
+ </button>
344
+ </div>
345
+
346
+ <style>{`
347
+ @keyframes popInText {
348
+ 0% {
349
+ opacity: 0;
350
+ transform: translateY(8px) scale(0.96);
351
+ }
352
+ 100% {
353
+ opacity: 1;
354
+ transform: translateY(0) scale(1);
355
+ }
356
+ }
357
+ @keyframes fadeInText {
358
+ 0% {
359
+ opacity: 0;
360
+ transform: translateY(6px);
361
+ }
362
+ 100% {
363
+ opacity: 1;
364
+ transform: translateY(0);
365
+ }
366
+ }
367
+ `}</style>
368
+ </div>
369
+ );
370
+ };
package/src/index.css ADDED
@@ -0,0 +1,19 @@
1
+ /* SAMPARK UAI Host Container Global Resets */
2
+ *, *::before, *::after {
3
+ box-sizing: border-box;
4
+ margin: 0;
5
+ padding: 0;
6
+ }
7
+
8
+ html, body, #root {
9
+ width: 100%;
10
+ height: 100%;
11
+ height: 100dvh;
12
+ margin: 0;
13
+ padding: 0;
14
+ overflow: hidden;
15
+ background-color: #ffffff;
16
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
17
+ -webkit-font-smoothing: antialiased;
18
+ -moz-osx-font-smoothing: grayscale;
19
+ }
package/src/main.tsx ADDED
@@ -0,0 +1,10 @@
1
+ import React from 'react'
2
+ import ReactDOM from 'react-dom/client'
3
+ import App from './App.tsx'
4
+ import './index.css'
5
+
6
+ ReactDOM.createRoot(document.getElementById('root')!).render(
7
+ <React.StrictMode>
8
+ <App />
9
+ </React.StrictMode>,
10
+ )
@@ -0,0 +1,17 @@
1
+ {
2
+ "platformName": "SAMPARK",
3
+ "themeColor": "#ea580c",
4
+ "themeSecondary": "#f97316",
5
+ "fullForm": "Single Administrative Management Portal for Access, Resources and Knowledge",
6
+ "sequenceSteps": [
7
+ { "highlightIndex": 0, "word": "Single" },
8
+ { "highlightIndex": 1, "word": "Administrative" },
9
+ { "highlightIndex": 2, "word": "Management" },
10
+ { "highlightIndex": 3, "word": "Portal" },
11
+ { "highlightIndex": null, "word": "for" },
12
+ { "highlightIndex": 4, "word": "Access" },
13
+ { "highlightIndex": 5, "word": "Resources" },
14
+ { "highlightIndex": null, "word": "and" },
15
+ { "highlightIndex": 6, "word": "Knowledge" }
16
+ ]
17
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "files": [],
3
+ "references": [
4
+ { "path": "./tsconfig.app.json" },
5
+ { "path": "./tsconfig.node.json" }
6
+ ]
7
+ }
package/vite.config.ts ADDED
@@ -0,0 +1,6 @@
1
+ import { defineConfig } from 'vite'
2
+ import react from '@vitejs/plugin-react'
3
+
4
+ export default defineConfig({
5
+ plugins: [react()],
6
+ })