This commit is contained in:
Janus C. H. Knudsen 2025-12-07 17:44:52 +01:00
parent 70e505526f
commit 9d011ff305
5 changed files with 121 additions and 6 deletions

View file

@ -10,6 +10,7 @@ import { RendererRegistry } from './core/RendererRegistry';
import { CalendarOrchestrator } from './core/CalendarOrchestrator'; import { CalendarOrchestrator } from './core/CalendarOrchestrator';
import { TimeAxisRenderer } from './features/timeaxis/TimeAxisRenderer'; import { TimeAxisRenderer } from './features/timeaxis/TimeAxisRenderer';
import { ScrollManager } from './core/ScrollManager'; import { ScrollManager } from './core/ScrollManager';
import { HeaderDrawerManager } from './core/HeaderDrawerManager';
import { MockTeamStore, MockResourceStore } from './demo/MockStores'; import { MockTeamStore, MockResourceStore } from './demo/MockStores';
import { DemoApp } from './demo/DemoApp'; import { DemoApp } from './demo/DemoApp';
@ -47,6 +48,7 @@ export function createV2Container(): Container {
builder.registerType(CalendarOrchestrator).as<CalendarOrchestrator>(); builder.registerType(CalendarOrchestrator).as<CalendarOrchestrator>();
builder.registerType(TimeAxisRenderer).as<TimeAxisRenderer>(); builder.registerType(TimeAxisRenderer).as<TimeAxisRenderer>();
builder.registerType(ScrollManager).as<ScrollManager>(); builder.registerType(ScrollManager).as<ScrollManager>();
builder.registerType(HeaderDrawerManager).as<HeaderDrawerManager>();
// Demo app // Demo app
builder.registerType(DemoApp).as<DemoApp>(); builder.registerType(DemoApp).as<DemoApp>();

View file

@ -0,0 +1,47 @@
export class HeaderDrawerManager {
private drawer!: HTMLElement;
private spacer!: HTMLElement;
private expanded = false;
private readonly expandedHeight = 24;
private readonly duration = 200;
init(container: HTMLElement): void {
this.drawer = container.querySelector('swp-header-drawer')!;
this.spacer = container.querySelector('swp-header-spacer')!;
}
toggle(): void {
this.expanded ? this.collapse() : this.expand();
}
expand(): void {
if (this.expanded) return;
this.expanded = true;
this.animate(0, this.expandedHeight);
}
collapse(): void {
if (!this.expanded) return;
this.expanded = false;
this.animate(this.expandedHeight, 0);
}
private animate(from: number, to: number): void {
const keyframes = [
{ height: `${from}px` },
{ height: `${to}px` }
];
const options: KeyframeAnimationOptions = {
duration: this.duration,
easing: 'ease',
fill: 'forwards'
};
this.drawer.animate(keyframes, options);
this.spacer.animate(keyframes, options);
}
isExpanded(): boolean {
return this.expanded;
}
}

View file

@ -3,6 +3,7 @@ import { TimeAxisRenderer } from '../features/timeaxis/TimeAxisRenderer';
import { NavigationAnimator } from '../core/NavigationAnimator'; import { NavigationAnimator } from '../core/NavigationAnimator';
import { DateService } from '../core/DateService'; import { DateService } from '../core/DateService';
import { ScrollManager } from '../core/ScrollManager'; import { ScrollManager } from '../core/ScrollManager';
import { HeaderDrawerManager } from '../core/HeaderDrawerManager';
import { ViewConfig } from '../core/ViewConfig'; import { ViewConfig } from '../core/ViewConfig';
export class DemoApp { export class DemoApp {
@ -15,7 +16,8 @@ export class DemoApp {
private orchestrator: CalendarOrchestrator, private orchestrator: CalendarOrchestrator,
private timeAxisRenderer: TimeAxisRenderer, private timeAxisRenderer: TimeAxisRenderer,
private dateService: DateService, private dateService: DateService,
private scrollManager: ScrollManager private scrollManager: ScrollManager,
private headerDrawerManager: HeaderDrawerManager
) {} ) {}
init(): void { init(): void {
@ -54,9 +56,13 @@ export class DemoApp {
// Init scroll synkronisering // Init scroll synkronisering
this.scrollManager.init(this.container); this.scrollManager.init(this.container);
// Init header drawer
this.headerDrawerManager.init(this.container);
// Setup event handlers // Setup event handlers
this.setupNavigation(); this.setupNavigation();
this.setupViewSwitchers(); this.setupViewSwitchers();
this.setupDrawerToggle();
// Initial render // Initial render
this.orchestrator.render(this.views.simple, this.container); this.orchestrator.render(this.views.simple, this.container);
@ -86,4 +92,10 @@ export class DemoApp {
document.getElementById('btn-team')!.onclick = () => document.getElementById('btn-team')!.onclick = () =>
this.animator.slide('left', () => this.orchestrator.render(this.views.team, this.container)); this.animator.slide('left', () => this.orchestrator.render(this.views.team, this.container));
} }
private setupDrawerToggle(): void {
document.getElementById('btn-drawer')!.onclick = () => {
this.headerDrawerManager.toggle();
};
}
} }

View file

@ -1,5 +1,5 @@
:root { :root {
--hour-height: 60px; --hour-height: 64px;
--time-axis-width: 60px; --time-axis-width: 60px;
--grid-columns: 5; --grid-columns: 5;
--day-start-hour: 0; --day-start-hour: 0;
@ -8,6 +8,8 @@
--color-surface: #fff; --color-surface: #fff;
--color-text-secondary: #666; --color-text-secondary: #666;
--color-primary: #1976d2; --color-primary: #1976d2;
--color-hour-line: rgba(0, 0, 0, 0.2);
--color-grid-line-light: rgba(0, 0, 0, 0.05);
} }
* { box-sizing: border-box; margin: 0; padding: 0; } * { box-sizing: border-box; margin: 0; padding: 0; }
@ -85,6 +87,16 @@ swp-time-axis {
} }
swp-header-spacer { swp-header-spacer {
height: 0;
overflow: hidden;
border-bottom: 1px solid var(--color-border);
}
swp-header-drawer {
display: block;
height: 0;
overflow: hidden;
background: #fafafa;
border-bottom: 1px solid var(--color-border); border-bottom: 1px solid var(--color-border);
} }
@ -100,6 +112,17 @@ swp-hour-marker {
font-size: 11px; font-size: 11px;
color: var(--color-text-secondary); color: var(--color-text-secondary);
text-align: right; text-align: right;
position: relative;
}
swp-hour-marker::after {
content: '';
position: absolute;
top: -1px;
right: 0;
width: 5px;
height: 1px;
background: var(--color-hour-line);
} }
/* Grid container */ /* Grid container */
@ -211,15 +234,44 @@ swp-time-grid {
min-height: calc((var(--day-end-hour) - var(--day-start-hour)) * var(--hour-height)); min-height: calc((var(--day-end-hour) - var(--day-start-hour)) * var(--hour-height));
} }
swp-grid-lines { /* Timelinjer via ::after */
swp-time-grid::after {
content: '';
position: absolute; position: absolute;
inset: 0; inset: 0;
background: repeating-linear-gradient( z-index: 2;
background-image: repeating-linear-gradient(
to bottom, to bottom,
transparent, transparent,
transparent calc(var(--hour-height) - 1px), transparent calc(var(--hour-height) - 1px),
var(--color-border) calc(var(--hour-height) - 1px), var(--color-hour-line) calc(var(--hour-height) - 1px),
var(--color-border) var(--hour-height) var(--color-hour-line) var(--hour-height)
);
pointer-events: none;
}
/* Kvarterlinjer - 3 linjer per time (15, 30, 45 min), ikke ved timegrænsen */
swp-grid-lines {
display: block;
position: absolute;
inset: 0;
z-index: 1;
background-image: repeating-linear-gradient(
to bottom,
transparent 0,
transparent calc(var(--hour-height) / 4 - 1px),
var(--color-grid-line-light) calc(var(--hour-height) / 4 - 1px),
var(--color-grid-line-light) calc(var(--hour-height) / 4),
transparent calc(var(--hour-height) / 4),
transparent calc(var(--hour-height) / 2 - 1px),
var(--color-grid-line-light) calc(var(--hour-height) / 2 - 1px),
var(--color-grid-line-light) calc(var(--hour-height) / 2),
transparent calc(var(--hour-height) / 2),
transparent calc(var(--hour-height) * 3 / 4 - 1px),
var(--color-grid-line-light) calc(var(--hour-height) * 3 / 4 - 1px),
var(--color-grid-line-light) calc(var(--hour-height) * 3 / 4),
transparent calc(var(--hour-height) * 3 / 4),
transparent var(--hour-height)
); );
} }

View file

@ -19,6 +19,7 @@
</swp-week-info> </swp-week-info>
<swp-nav-button id="btn-prev"></swp-nav-button> <swp-nav-button id="btn-prev"></swp-nav-button>
<swp-nav-button id="btn-next"></swp-nav-button> <swp-nav-button id="btn-next"></swp-nav-button>
<swp-nav-button id="btn-drawer">Toggle</swp-nav-button>
</swp-calendar-nav> </swp-calendar-nav>
<swp-calendar-container> <swp-calendar-container>
@ -31,6 +32,7 @@
<swp-header-track> <swp-header-track>
<swp-calendar-header></swp-calendar-header> <swp-calendar-header></swp-calendar-header>
</swp-header-track> </swp-header-track>
<swp-header-drawer></swp-header-drawer>
</swp-header-viewport> </swp-header-viewport>
<swp-content-viewport> <swp-content-viewport>
<swp-content-track> <swp-content-track>