Feat v0.6.10 viewport foundation (#45)
All checks were successful
All checks were successful
Co-authored-by: Jeffrey Smith <jasafpro@gmail.com> Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
This commit was merged in pull request #45.
This commit is contained in:
@@ -16,21 +16,14 @@ export function Menu({ items = [], anchor, open, direction = 'down-right', onSel
|
||||
|
||||
const selectableItems = items.filter(i => !i.divider && !i.disabled);
|
||||
|
||||
// Position relative to anchor
|
||||
// When the surface uses CSS transform: scale(), getBoundingClientRect()
|
||||
// returns scaled coordinates but position:fixed uses viewport coordinates.
|
||||
// Dividing by the scale factor converts back to true viewport pixels.
|
||||
// Position relative to anchor (CSS zoom reflows layout correctly)
|
||||
useEffect(() => {
|
||||
if (!open || !anchor) return;
|
||||
const scale = window.sw?.shell?.getScale?.() || 1;
|
||||
const raw = typeof anchor.getBoundingClientRect === 'function'
|
||||
const rect = typeof anchor.getBoundingClientRect === 'function'
|
||||
? anchor.getBoundingClientRect()
|
||||
: anchor;
|
||||
const rect = scale !== 1
|
||||
? { top: raw.top / scale, bottom: raw.bottom / scale, left: raw.left / scale, right: raw.right / scale }
|
||||
: raw;
|
||||
const vw = window.innerWidth / scale;
|
||||
const vh = window.innerHeight / scale;
|
||||
const vw = window.innerWidth;
|
||||
const vh = window.innerHeight;
|
||||
|
||||
let top, left;
|
||||
const [vDir, hDir] = direction.split('-');
|
||||
|
||||
@@ -123,15 +123,8 @@ export async function boot() {
|
||||
|
||||
// Shell — layout utilities (decouples surface code from shell DOM)
|
||||
const _shell = {
|
||||
/** CSS transform scale on #surfaceInner (appearance zoom). */
|
||||
getScale() {
|
||||
const el = document.getElementById('surfaceInner');
|
||||
if (!el) return 1;
|
||||
const t = getComputedStyle(el).transform;
|
||||
if (!t || t === 'none') return 1;
|
||||
const m = t.match(/matrix\(([^,]+)/);
|
||||
return m ? parseFloat(m[1]) || 1 : 1;
|
||||
},
|
||||
/** @deprecated v0.6.10 — CSS zoom handles reflow; no scale correction needed. */
|
||||
getScale() { return 1; },
|
||||
/** Topbar — set after dynamic import below */
|
||||
Topbar: null,
|
||||
};
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
/**
|
||||
/** @deprecated v0.6.10 — No surface imports AppShell. Layout root is <body> in base.html.
|
||||
* Kept for reference; will be removed in a future version.
|
||||
*
|
||||
* AppShell — Layer 1 layout scaffold
|
||||
*
|
||||
* ┌─────────────────────────────────┐ ← fixed banner (top, optional)
|
||||
@@ -22,20 +24,10 @@
|
||||
const { html } = window;
|
||||
const { useState, useEffect, useRef, useReducer } = hooks;
|
||||
|
||||
/** @deprecated v0.6.10 — Banner height is measured by template scripts in base.html. */
|
||||
function ShellBanner({ position, text, variant = 'info' }) {
|
||||
const ref = useRef(null);
|
||||
const prop = position === 'top' ? '--banner-top-height' : '--banner-bottom-height';
|
||||
|
||||
useEffect(() => {
|
||||
if (ref.current) {
|
||||
const h = ref.current.offsetHeight + 'px';
|
||||
document.documentElement.style.setProperty(prop, h);
|
||||
}
|
||||
return () => document.documentElement.style.setProperty(prop, '0px');
|
||||
}, [text, prop]);
|
||||
|
||||
return html`
|
||||
<div class="sw-shell__banner sw-shell__banner--${position} sw-shell__banner--${variant}" ref=${ref}>
|
||||
<div class="sw-shell__banner sw-shell__banner--${position} sw-shell__banner--${variant}">
|
||||
<span class="sw-shell__banner-text">${text}</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
/**
|
||||
/** @deprecated v0.6.10 — No surface imports App. Layout root is <body> in base.html.
|
||||
* Kept for reference; will be removed in a future version.
|
||||
*
|
||||
* App — root component composing the full shell tree
|
||||
*
|
||||
* ┌───────────────────────────────┐
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/**
|
||||
/** @deprecated v0.6.10 — No surface imports SurfaceViewport. Layout root is <body> in base.html.
|
||||
*
|
||||
* SurfaceViewport — container where the active surface renders
|
||||
*
|
||||
* Deliberately thin. Error boundaries and
|
||||
|
||||
@@ -37,20 +37,11 @@ export function AppearanceSection() {
|
||||
p.scale = scale;
|
||||
localStorage.setItem('sb-appearance', JSON.stringify(p));
|
||||
|
||||
// Apply scale to content area only (not shell/nav)
|
||||
// Apply scale to content area only (not shell/nav).
|
||||
// CSS zoom reflows layout correctly — no getBoundingClientRect hacks needed.
|
||||
const inner = document.getElementById('surfaceInner');
|
||||
if (inner) {
|
||||
if (scale !== 100) {
|
||||
const s = scale / 100;
|
||||
inner.style.transform = `scale(${s})`;
|
||||
inner.style.transformOrigin = 'top left';
|
||||
inner.style.width = (100 / s) + '%';
|
||||
inner.style.height = (100 / s) + '%';
|
||||
} else {
|
||||
inner.style.transform = '';
|
||||
inner.style.width = '';
|
||||
inner.style.height = '';
|
||||
}
|
||||
inner.style.zoom = scale !== 100 ? (scale / 100) : '';
|
||||
}
|
||||
|
||||
sw.emit('toast', { message: 'Appearance saved', variant: 'success' });
|
||||
|
||||
Reference in New Issue
Block a user