// app.jsx — composes everything
const { useState, useEffect } = React;
const PALETTES = {
skyideaDefault: { name: 'Sky / 提案準拠', sky: '#87CEEB', deep: '#4A9BC4', mid: '#5B7FE0', sec: '#1F4E96', bcp: '#5DADE2', night: '#191970' },
cooler: { name: 'Cool Navy', sky: '#A8DADC', deep: '#457B9D', mid: '#5B7FE0', sec: '#1D3557', bcp: '#6FB1FC', night: '#0F1B3D' },
monoNavy: { name: 'Mono Navy', sky: '#B8C5DB', deep: '#3D5A8A', mid: '#4F6FA8', sec: '#1E2F5A', bcp: '#7B96C2', night: '#0E1849' }
};
function App() {
const [modalOpen, setModalOpen] = useState(false);
const [initialTheme, setInitialTheme] = useState('');
const openModal = (theme) => {
setInitialTheme(typeof theme === 'string' ? theme : '');
setModalOpen(true);
};
// Tweaks
const tweakDefaults = /*EDITMODE-BEGIN*/{
"palette": "skyideaDefault",
"showPhilosophy": true
}/*EDITMODE-END*/;
const [t, setTweak] = window.useTweaks(tweakDefaults);
// Apply palette
useEffect(() => {
const p = PALETTES[t.palette] || PALETTES.skyideaDefault;
const root = document.documentElement;
root.style.setProperty('--sky-blue', p.sky);
root.style.setProperty('--sky-deep', p.deep);
root.style.setProperty('--mid-blue', p.mid);
root.style.setProperty('--deep-blue', p.sec);
root.style.setProperty('--light-sky', p.bcp);
root.style.setProperty('--midnight', p.night);
}, [t.palette]);
// Reveal on scroll
useEffect(() => {
const els = document.querySelectorAll('.reveal');
const io = new IntersectionObserver((entries) => {
entries.forEach(e => {
if (e.isIntersecting) {
e.target.classList.add('is-shown');
io.unobserve(e.target);
}
});
}, { threshold: 0.08 });
els.forEach(el => io.observe(el));
return () => io.disconnect();
}, []);
// Palette options for TweakColor — array of palette arrays
const paletteOptions = Object.values(PALETTES).map(p => [p.sky, p.deep, p.night]);
const paletteKeys = Object.keys(PALETTES);
const currentPaletteArr = (() => {
const p = PALETTES[t.palette] || PALETTES.skyideaDefault;
return [p.sky, p.deep, p.night];
})();
return (
openModal()} />
openModal()} />
{t.showPhilosophy && (
)}
{window.CONTACT_ENABLED && (
openModal()} />
)}
{window.CONTACT_ENABLED && (
setModalOpen(false)}
initialTheme={initialTheme}
/>
)}
{
const idx = paletteOptions.findIndex(p => JSON.stringify(p) === JSON.stringify(arr));
if (idx >= 0) setTweak('palette', paletteKeys[idx]);
}}
/>
setTweak('showPhilosophy', v)}
/>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render();