feat: integrate SimpleCADAPI 2.0.2 CAD workflows
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
import * as THREE from 'three';
|
||||
import type { OrbitControls } from 'three/addons/controls/OrbitControls.js';
|
||||
|
||||
type ClickSelectionOptions = {
|
||||
element: HTMLElement;
|
||||
camera: THREE.PerspectiveCamera;
|
||||
controls: OrbitControls;
|
||||
movementThreshold?: number;
|
||||
onPointerStateChange?: (active: boolean) => void;
|
||||
onClick: (event: PointerEvent) => void;
|
||||
};
|
||||
|
||||
export function bindClickSelection(options: ClickSelectionOptions): () => void {
|
||||
const { element, camera, controls, onClick, movementThreshold = 4 } = options;
|
||||
let pointerDown: {
|
||||
x: number;
|
||||
y: number;
|
||||
button: number;
|
||||
position: THREE.Vector3;
|
||||
target: THREE.Vector3;
|
||||
zoom: number;
|
||||
} | null = null;
|
||||
|
||||
const onPointerDown = (event: PointerEvent): void => {
|
||||
pointerDown = {
|
||||
x: event.clientX,
|
||||
y: event.clientY,
|
||||
button: event.button,
|
||||
position: camera.position.clone(),
|
||||
target: controls.target.clone(),
|
||||
zoom: camera.zoom,
|
||||
};
|
||||
options.onPointerStateChange?.(true);
|
||||
};
|
||||
const onPointerUp = (event: PointerEvent): void => {
|
||||
const down = pointerDown;
|
||||
pointerDown = null;
|
||||
options.onPointerStateChange?.(false);
|
||||
if (!down || down.button !== 0 || event.button !== 0) return;
|
||||
if (Math.hypot(event.clientX - down.x, event.clientY - down.y) > movementThreshold) return;
|
||||
|
||||
// OrbitControls treats any pointer movement as rotation. Drain that movement,
|
||||
// then restore the click-time camera before committing selection.
|
||||
const damping = controls.enableDamping;
|
||||
controls.enableDamping = false;
|
||||
controls.update();
|
||||
camera.position.copy(down.position);
|
||||
camera.zoom = down.zoom;
|
||||
camera.updateProjectionMatrix();
|
||||
controls.target.copy(down.target);
|
||||
controls.update();
|
||||
controls.enableDamping = damping;
|
||||
onClick(event);
|
||||
};
|
||||
const onPointerLeave = (): void => {
|
||||
pointerDown = null;
|
||||
options.onPointerStateChange?.(false);
|
||||
};
|
||||
|
||||
element.addEventListener('pointerdown', onPointerDown);
|
||||
element.addEventListener('pointerup', onPointerUp);
|
||||
element.addEventListener('pointerleave', onPointerLeave);
|
||||
return () => {
|
||||
element.removeEventListener('pointerdown', onPointerDown);
|
||||
element.removeEventListener('pointerup', onPointerUp);
|
||||
element.removeEventListener('pointerleave', onPointerLeave);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
type PanelSide = 'navigator' | 'inspector';
|
||||
|
||||
type ResizablePanelsOptions = {
|
||||
workspace: HTMLElement;
|
||||
navigatorPanel: HTMLElement;
|
||||
inspectorPanel: HTMLElement;
|
||||
navigatorResizer: HTMLElement;
|
||||
inspectorResizer: HTMLElement;
|
||||
minNavigatorWidth?: number;
|
||||
maxNavigatorWidth?: number;
|
||||
minInspectorWidth?: number;
|
||||
maxInspectorWidth?: number;
|
||||
minCenterWidth?: number;
|
||||
gutterWidth?: number;
|
||||
desktopMedia?: string;
|
||||
};
|
||||
|
||||
export function bindResizablePanels(options: ResizablePanelsOptions): () => void {
|
||||
const {
|
||||
workspace,
|
||||
navigatorPanel,
|
||||
inspectorPanel,
|
||||
navigatorResizer,
|
||||
inspectorResizer,
|
||||
minNavigatorWidth = 180,
|
||||
maxNavigatorWidth = 520,
|
||||
minInspectorWidth = 230,
|
||||
maxInspectorWidth = 620,
|
||||
minCenterWidth = 320,
|
||||
gutterWidth = 14,
|
||||
desktopMedia = '(min-width: 901px)',
|
||||
} = options;
|
||||
const media = window.matchMedia(desktopMedia);
|
||||
const cleanups: Array<() => void> = [];
|
||||
|
||||
const panelFor = (side: PanelSide): HTMLElement => side === 'navigator' ? navigatorPanel : inspectorPanel;
|
||||
const otherPanelFor = (side: PanelSide): HTMLElement => side === 'navigator' ? inspectorPanel : navigatorPanel;
|
||||
const resizerFor = (side: PanelSide): HTMLElement => side === 'navigator' ? navigatorResizer : inspectorResizer;
|
||||
|
||||
const setWidth = (side: PanelSide, requestedWidth: number): void => {
|
||||
if (!media.matches) return;
|
||||
const minimum = side === 'navigator' ? minNavigatorWidth : minInspectorWidth;
|
||||
const configuredMaximum = side === 'navigator' ? maxNavigatorWidth : maxInspectorWidth;
|
||||
const available = workspace.getBoundingClientRect().width
|
||||
- otherPanelFor(side).getBoundingClientRect().width
|
||||
- minCenterWidth
|
||||
- gutterWidth;
|
||||
const maximum = Math.max(minimum, Math.min(configuredMaximum, available));
|
||||
const width = Math.round(Math.max(minimum, Math.min(maximum, requestedWidth)));
|
||||
workspace.style.setProperty(side === 'navigator' ? '--navigator-width' : '--inspector-width', `${width}px`);
|
||||
const resizer = resizerFor(side);
|
||||
resizer.setAttribute('aria-valuemin', String(minimum));
|
||||
resizer.setAttribute('aria-valuemax', String(maximum));
|
||||
resizer.setAttribute('aria-valuenow', String(width));
|
||||
};
|
||||
|
||||
const bind = (side: PanelSide): void => {
|
||||
const resizer = resizerFor(side);
|
||||
const onPointerDown = (event: PointerEvent): void => {
|
||||
if (event.button !== 0 || !media.matches) return;
|
||||
event.preventDefault();
|
||||
const startX = event.clientX;
|
||||
const startWidth = panelFor(side).getBoundingClientRect().width;
|
||||
resizer.setPointerCapture(event.pointerId);
|
||||
resizer.classList.add('dragging');
|
||||
document.body.classList.add('resizing-panels');
|
||||
|
||||
const onPointerMove = (moveEvent: PointerEvent): void => {
|
||||
const delta = moveEvent.clientX - startX;
|
||||
setWidth(side, startWidth + (side === 'navigator' ? delta : -delta));
|
||||
};
|
||||
const finish = (): void => {
|
||||
resizer.classList.remove('dragging');
|
||||
document.body.classList.remove('resizing-panels');
|
||||
resizer.removeEventListener('pointermove', onPointerMove);
|
||||
resizer.removeEventListener('pointerup', finish);
|
||||
resizer.removeEventListener('pointercancel', finish);
|
||||
};
|
||||
resizer.addEventListener('pointermove', onPointerMove);
|
||||
resizer.addEventListener('pointerup', finish);
|
||||
resizer.addEventListener('pointercancel', finish);
|
||||
};
|
||||
const onKeyDown = (event: KeyboardEvent): void => {
|
||||
if (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight') return;
|
||||
event.preventDefault();
|
||||
const direction = event.key === 'ArrowRight' ? 1 : -1;
|
||||
const currentWidth = panelFor(side).getBoundingClientRect().width;
|
||||
setWidth(side, currentWidth + direction * (side === 'navigator' ? 12 : -12));
|
||||
};
|
||||
resizer.addEventListener('pointerdown', onPointerDown);
|
||||
resizer.addEventListener('keydown', onKeyDown);
|
||||
cleanups.push(() => resizer.removeEventListener('pointerdown', onPointerDown));
|
||||
cleanups.push(() => resizer.removeEventListener('keydown', onKeyDown));
|
||||
};
|
||||
|
||||
bind('navigator');
|
||||
bind('inspector');
|
||||
setWidth('navigator', navigatorPanel.getBoundingClientRect().width);
|
||||
setWidth('inspector', inspectorPanel.getBoundingClientRect().width);
|
||||
|
||||
const resizeObserver = new ResizeObserver(() => {
|
||||
if (!media.matches) return;
|
||||
setWidth('navigator', navigatorPanel.getBoundingClientRect().width);
|
||||
setWidth('inspector', inspectorPanel.getBoundingClientRect().width);
|
||||
});
|
||||
resizeObserver.observe(workspace);
|
||||
cleanups.push(() => resizeObserver.disconnect());
|
||||
|
||||
return () => cleanups.forEach((cleanup) => cleanup());
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,101 @@
|
||||
:root { color: #e7edf5; background: #0b0e12; font-family: 'Space Grotesk', system-ui, sans-serif; font-synthesis: none; }
|
||||
* { box-sizing: border-box; }
|
||||
* { scrollbar-width: none; -ms-overflow-style: none; }
|
||||
*::-webkit-scrollbar { display: none; width: 0; height: 0; }
|
||||
body { margin: 0; min-width: 320px; min-height: 100vh; overflow: hidden; background: #0b0e12; }
|
||||
body.resizing-panels { cursor: col-resize; user-select: none; }
|
||||
body.resizing-dock { cursor: row-resize; user-select: none; }
|
||||
button, select { font: inherit; }
|
||||
.ui-icon, .button-icon { display: block; flex: 0 0 auto; width: 13px; height: 13px; }
|
||||
.shell { display: grid; grid-template-rows: 64px minmax(0, 1fr) 32px; height: 100vh; }
|
||||
.topbar { display: flex; align-items: center; justify-content: space-between; padding: 0 24px; border-bottom: 1px solid #202832; background: #10141a; }
|
||||
.brand, .top-actions, .brand > div { display: flex; align-items: center; }
|
||||
.brand { gap: 10px; letter-spacing: -.02em; }
|
||||
.brand-mark { display: grid; place-items: center; width: 30px; height: 30px; border: 1px solid #b3e36b; color: #b3e36b; font: 500 11px 'DM Mono', monospace; transform: rotate(-7deg); }
|
||||
.brand strong { display: block; font-size: 14px; line-height: 15px; }
|
||||
.brand span:not(.brand-mark) { display: block; color: #758397; font-size: 10px; letter-spacing: .08em; text-transform: uppercase; }
|
||||
.top-actions { gap: 18px; }
|
||||
.case-picker { display: flex; align-items: center; gap: 9px; color: #738093; font: 500 10px 'DM Mono', monospace; }
|
||||
.case-picker select { max-width: 230px; padding: 7px 25px 7px 9px; border: 1px solid #2a3440; border-radius: 3px; color: #dce5ee; background: #151b22; font: 12px 'DM Mono', monospace; }
|
||||
.quiet-button, .viewport-tools button { border: 1px solid #303b48; border-radius: 3px; color: #aebdcd; background: #151b22; cursor: pointer; font: 500 10px 'DM Mono', monospace; letter-spacing: .04em; }
|
||||
.quiet-button { display: inline-flex; align-items: center; gap: 7px; padding: 8px 11px; }
|
||||
.quiet-button:hover, .viewport-tools button:hover { border-color: #b3e36b; color: #b3e36b; }
|
||||
.workspace { --navigator-width: 256px; --inspector-width: 278px; display: grid; grid-template-columns: var(--navigator-width) 7px minmax(0, 1fr) 7px var(--inspector-width); min-width: 0; min-height: 0; overflow: hidden; }
|
||||
.panel { display: flex; min-width: 0; min-height: 0; flex-direction: column; overflow: hidden; background: #10141a; }
|
||||
.panel > .panel-heading { flex: 0 0 auto; }
|
||||
.tree-panel { grid-column: 1; }
|
||||
.viewport-wrap { grid-column: 3; }
|
||||
.details-panel { grid-column: 5; }
|
||||
.panel-resizer { position: relative; z-index: 4; min-width: 0; cursor: col-resize; touch-action: none; background: #10141a; }
|
||||
.panel-resizer::before { position: absolute; top: 0; bottom: 0; left: 3px; width: 1px; content: ''; background: #202832; transition: background .15s, box-shadow .15s; }
|
||||
.panel-resizer:hover::before, .panel-resizer.dragging::before, .panel-resizer:focus-visible::before { background: #b3e36b; box-shadow: 0 0 8px rgba(179,227,107,.5); }
|
||||
#navigator-resizer { grid-column: 2; }
|
||||
#inspector-resizer { grid-column: 4; }
|
||||
.panel-heading { display: flex; align-items: flex-start; justify-content: space-between; min-height: 80px; padding: 21px 17px 15px; border-bottom: 1px solid #202832; }
|
||||
.eyebrow { display: block; color: #718096; font: 500 9px 'DM Mono', monospace; letter-spacing: .15em; }
|
||||
h1 { margin: 7px 0 0; color: #eef4fb; font-size: 17px; font-weight: 600; letter-spacing: -.04em; text-transform: capitalize; }
|
||||
.count { min-width: 27px; padding: 4px 6px; border: 1px solid #2b3540; border-radius: 3px; color: #8190a3; text-align: center; font: 10px 'DM Mono', monospace; }
|
||||
.tree { min-height: 0; flex: 1 1 auto; padding: 12px 0; overflow: auto; overscroll-behavior: contain; }
|
||||
.tree-empty { padding: 24px 16px; color: #718094; font: 10px/1.6 'DM Mono', monospace; }
|
||||
.tree-row { display: flex; align-items: center; gap: 7px; width: 100%; padding: 8px 12px 8px calc(12px + var(--depth) * 16px); border: 0; border-left: 2px solid transparent; color: #94a1b2; background: transparent; text-align: left; cursor: pointer; }
|
||||
.tree-row:hover { color: #edf3f9; background: #171d24; }
|
||||
.tree-row.selected { border-left-color: #b3e36b; color: #f2f8fb; background: #1a2324; }
|
||||
.tree-row.hidden-node { color: #4d5a68; }.tree-row.hidden-node .tree-visibility { color: #b3e36b; opacity: .55; }
|
||||
.tree-chevron { display: grid; flex: 0 0 10px; place-items: center; width: 10px; color: #697889; }
|
||||
.tree-chevron-icon { display: block; width: 10px; height: 10px; }
|
||||
.tree-glyph { display: grid; flex: 0 0 14px; place-items: center; width: 14px; color: #b3e36b; }
|
||||
.tree-type-icon { display: block; width: 14px; height: 14px; }
|
||||
.tree-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; }
|
||||
.tree-visibility { display: grid; flex: 0 0 18px; place-items: center; margin-left: auto; color: #43505e; }
|
||||
.tree-visibility-icon { display: block; width: 14px; height: 14px; }
|
||||
.navigator-tabs { display: grid; grid-template-columns: 1fr 1fr; border-bottom: 1px solid #202832; background: #0d1218; }
|
||||
.navigator-tab { display: flex; align-items: center; justify-content: center; gap: 6px; min-width: 0; padding: 10px 8px; border: 0; border-bottom: 2px solid transparent; color: #718094; background: transparent; cursor: pointer; font: 10px 'DM Mono', monospace; text-transform: uppercase; }
|
||||
.navigator-tab:hover { color: #dce5ee; background: #151b22; }
|
||||
.navigator-tab.active { border-bottom-color: #b3e36b; color: #b3e36b; background: #151d1b; }
|
||||
.navigator-tab .count { min-width: 22px; padding: 3px 5px; font-size: 9px; }
|
||||
.tab-icon { display: flex; flex: 0 0 auto; }
|
||||
.tab-icon svg { display: block; width: 13px; height: 13px; }
|
||||
.navigator-view { display: flex; min-width: 0; min-height: 0; flex: 1 1 auto; flex-direction: column; overflow: hidden; }
|
||||
.navigator-view[hidden] { display: none; }
|
||||
.feature-tree { padding-top: 12px; }
|
||||
.feature-tree-row { padding-right: 10px; }
|
||||
.feature-tree-children { display: block; }
|
||||
.feature-glyph { color: #91b8ed; }
|
||||
.feature-tree-row.selected .feature-glyph { color: #b3e36b; }
|
||||
.feature-tag-mark { margin-left: auto; color: #718094; font: 8px 'DM Mono', monospace; letter-spacing: .06em; }
|
||||
.viewport-wrap { display: block; position: relative; min-width: 0; min-height: 0; overflow: hidden; background: radial-gradient(circle at 52% 44%, #18222a 0, #0d1218 47%, #0b0e12 100%); }
|
||||
.viewport-stage { position: absolute; inset: 0; min-width: 0; min-height: 0; overflow: hidden; }
|
||||
.viewport { position: absolute; inset: 0; overflow: hidden; }
|
||||
.viewport.drop-target { outline: 2px solid #b3e36b; outline-offset: -8px; }
|
||||
.viewport canvas { display: block; width: 100%; height: 100%; }
|
||||
.viewport::after { position: absolute; inset: 0; pointer-events: none; content: ''; background: linear-gradient(90deg, rgba(179,227,107,.04) 1px, transparent 1px), linear-gradient(rgba(179,227,107,.04) 1px, transparent 1px); background-size: 64px 64px; mask-image: linear-gradient(to bottom, transparent 0, rgba(0,0,0,.45) 70%, transparent 100%); }
|
||||
.hud { position: absolute; z-index: 2; left: 17px; bottom: 16px; display: flex; align-items: center; gap: 7px; padding: 7px 9px; border: 1px solid #27323d; border-radius: 3px; color: #8898aa; background: rgba(14, 19, 24, .8); font: 10px 'DM Mono', monospace; backdrop-filter: blur(8px); }
|
||||
.status-dot { width: 6px; height: 6px; border-radius: 50%; background: #697583; }.status-dot.ready { background: #b3e36b; box-shadow: 0 0 10px #b3e36b; }
|
||||
.viewport-tools { position: absolute; z-index: 2; top: 15px; right: 15px; display: flex; align-items: stretch; gap: 7px; }
|
||||
.viewport-tools button { display: inline-flex; align-items: center; justify-content: center; gap: 5px; padding: 7px 9px; font-size: 9px; }
|
||||
.viewport-tools button.active { border-color: #526d40; color: #b3e36b; background: #18221c; }
|
||||
.selection-tools { display: flex; align-items: center; padding-left: 8px; border: 1px solid #303b48; border-radius: 3px; background: rgba(21, 27, 34, .92); }
|
||||
.selection-tools .tool-label { margin-right: 4px; color: #657386; font: 8px 'DM Mono', monospace; letter-spacing: .08em; }
|
||||
.selection-tools .selection-mode { border-width: 0 0 0 1px; border-radius: 0; background: transparent; }
|
||||
.selection-tools .selection-mode:first-of-type { border-left: 0; }
|
||||
.loading { position: absolute; z-index: 3; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 13px; color: #94a5b7; font: 11px 'DM Mono', monospace; background: rgba(11,14,18,.75); transition: opacity .2s; }.loading.hidden { opacity: 0; pointer-events: none; }
|
||||
.spinner { width: 18px; height: 18px; border: 1px solid #364352; border-top-color: #b3e36b; border-radius: 50%; animation: spin .7s linear infinite; }@keyframes spin { to { transform: rotate(360deg); } }
|
||||
.tag { padding: 4px 6px; border: 1px solid #39484d; border-radius: 3px; color: #b3e36b; background: #18221c; font: 9px 'DM Mono', monospace; }
|
||||
.details { min-width: 0; min-height: 0; flex: 1 1 auto; overflow: auto; overscroll-behavior: contain; padding: 20px 17px; font-size: 13px; }.empty-state { display: flex; flex-direction: column; gap: 8px; padding: 34px 4px; color: #718094; font-size: 13px; line-height: 1.55; }.empty-state strong { color: #bbc7d4; font-size: 15px; }.empty-cross { display: block; width: 28px; height: 28px; color: #536475; }.empty-state-icon { display: block; width: 28px; height: 28px; }
|
||||
.detail-title { display: flex; gap: 11px; min-width: 0; padding-bottom: 19px; border-bottom: 1px solid #202832; }.detail-icon { display: block; flex: 0 0 auto; width: 24px; color: #b3e36b; }.detail-icon-svg { display: block; width: 24px; height: 24px; }.detail-title > div { min-width: 0; }.detail-title > div > strong, .detail-title > div > span { display: block; }.detail-title strong { margin: 1px 0 6px; overflow-wrap: anywhere; color: #edf3f9; font-size: 16px; line-height: 1.35; }.detail-title > div > span { color: #718096; font: 11px/1.5 'DM Mono', monospace; }.detail-definition-path { overflow-wrap: anywhere; word-break: break-word; }
|
||||
.detail-section { padding: 19px 0 4px; }.detail-section-heading { display: flex; align-items: center; justify-content: space-between; gap: 10px; }.detail-section dl { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr); gap: 10px 12px; margin: 13px 0 0; font: 11px/1.45 'DM Mono', monospace; }.detail-section dt { color: #657386; }.detail-section dd { min-width: 0; margin: 0; overflow-wrap: anywhere; color: #c5d0dc; text-align: right; word-break: break-word; }.path-value { white-space: normal; }.detail-muted, .selector-warning { color: #718094; font: 11px/1.6 'DM Mono', monospace; }.selector-warning { color: #c19a62; }
|
||||
.params { max-height: 260px; margin: 12px 0 0; padding: 10px; overflow: auto; border: 1px solid #202832; color: #a9c77b; background: #0b0e12; font: 9px/1.5 'DM Mono', monospace; white-space: pre-wrap; word-break: break-word; }
|
||||
.source-file-path { margin-top: 12px; overflow-wrap: anywhere; color: #91b8ed; font: 9px/1.5 'DM Mono', monospace; }
|
||||
.source-code { max-height: 360px; margin: 8px 0 0; padding: 8px 0; overflow: auto; border: 1px solid #202832; color: #b8c4d1; background: #090c10; font: 10px/1.55 'DM Mono', monospace; tab-size: 4; }
|
||||
.source-code code { display: block; min-width: max-content; }
|
||||
.source-line { display: grid; grid-template-columns: 42px minmax(max-content, 1fr); min-height: 16px; }
|
||||
.source-line.active { color: #f2f7ee; background: rgba(179, 227, 107, .13); box-shadow: inset 2px 0 #b3e36b; }
|
||||
.source-line-number { padding-right: 10px; color: #465363; text-align: right; user-select: none; }
|
||||
.source-line.active .source-line-number { color: #9abf66; }
|
||||
.source-line-text { padding-right: 12px; white-space: pre; }
|
||||
.selector-code { max-height: 240px; margin: 12px 0 0; padding: 10px; overflow: auto; border: 1px solid #39484d; color: #b3e36b; background: #101a16; font: 10px/1.55 'DM Mono', monospace; white-space: pre-wrap; word-break: break-word; }.copy-button { display: inline-flex; align-items: center; gap: 5px; padding: 5px 7px; border: 1px solid #39484d; border-radius: 3px; color: #b3e36b; background: #18221c; cursor: pointer; font: 9px 'DM Mono', monospace; letter-spacing: .08em; }.copy-button:hover { border-color: #b3e36b; }
|
||||
.tag-list { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 11px; }.tag-list span { padding: 4px 6px; border: 1px solid #39484d; border-radius: 3px; color: #b3e36b; background: #18221c; font: 8px 'DM Mono', monospace; }
|
||||
.detail-summary { color: #aebdcd; font: 12px/1.6 'DM Mono', monospace; }
|
||||
.footer { display: flex; justify-content: space-between; align-items: center; padding: 0 17px; border-top: 1px solid #202832; color: #657487; background: #10141a; font: 9px 'DM Mono', monospace; }.footer-note { color: #4d5a68; }
|
||||
@media (max-width: 900px) { body { overflow: auto; }.shell { height: auto; min-height: 100vh; grid-template-rows: 64px auto 32px; }.topbar { padding: 0 14px; }.case-picker { display: none; }.workspace { grid-template-columns: 210px minmax(0, 1fr); grid-template-rows: minmax(620px, 78vh) auto; overflow: visible; }.panel-resizer { display: none; }.tree-panel { grid-column: 1; }.viewport-wrap { grid-column: 2; min-height: 620px; }.details-panel { grid-column: 1 / -1; border-top: 1px solid #202832; }.details { max-height: 55vh; } }
|
||||
@media (max-width: 560px) { .top-actions { gap: 0; }.workspace { grid-template-columns: 1fr; grid-template-rows: auto minmax(420px, 62vh) auto; }.tree-panel { grid-column: 1; grid-row: 1; border-bottom: 1px solid #202832; }.tree { max-height: 210px; }.viewport-wrap { grid-column: 1; grid-row: 2; }.details-panel { grid-column: 1; grid-row: 3; }.footer-note { display: none; }.viewport-tools { left: 10px; right: 10px; overflow-x: auto; }.selection-tools { flex: 0 0 auto; }.viewport-tools > #fit-button { flex: 0 0 auto; } }
|
||||
Reference in New Issue
Block a user