Initial commit: Calendar Plantempus project setup with TypeScript, ASP.NET Core, and event-driven architecture
This commit is contained in:
commit
f06c02121c
38 changed files with 8233 additions and 0 deletions
190
wwwroot/css/calendar-base-css.css
Normal file
190
wwwroot/css/calendar-base-css.css
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
/* styles/base.css */
|
||||
|
||||
/* CSS Reset and Base */
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* CSS Variables */
|
||||
:root {
|
||||
/* Grid measurements */
|
||||
--hour-height: 60px;
|
||||
--minute-height: 1px;
|
||||
--snap-interval: 15;
|
||||
|
||||
/* Time boundaries */
|
||||
--day-start-hour: 7;
|
||||
--day-end-hour: 19;
|
||||
--work-start-hour: 8;
|
||||
--work-end-hour: 17;
|
||||
|
||||
/* Colors */
|
||||
--color-primary: #2196f3;
|
||||
--color-secondary: #ff9800;
|
||||
--color-success: #4caf50;
|
||||
--color-danger: #f44336;
|
||||
--color-warning: #ff9800;
|
||||
|
||||
/* Grid colors */
|
||||
--color-grid-line: #e0e0e0;
|
||||
--color-grid-line-light: rgba(0, 0, 0, 0.05);
|
||||
--color-work-hours: rgba(0, 100, 0, 0.02);
|
||||
--color-current-time: #ff0000;
|
||||
|
||||
/* Event colors */
|
||||
--color-event-meeting: #e3f2fd;
|
||||
--color-event-meeting-border: #2196f3;
|
||||
--color-event-meal: #fff3e0;
|
||||
--color-event-meal-border: #ff9800;
|
||||
--color-event-work: #f3e5f5;
|
||||
--color-event-work-border: #9c27b0;
|
||||
--color-event-milestone: #e8f5e9;
|
||||
--color-event-milestone-border: #4caf50;
|
||||
|
||||
/* UI colors */
|
||||
--color-background: #ffffff;
|
||||
--color-surface: #f5f5f5;
|
||||
--color-text: #333333;
|
||||
--color-text-secondary: #666666;
|
||||
--color-border: #e0e0e0;
|
||||
|
||||
/* Shadows */
|
||||
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
--shadow-lg: 0 10px 20px rgba(0, 0, 0, 0.1);
|
||||
--shadow-popup: 0 4px 20px rgba(0, 0, 0, 0.15);
|
||||
|
||||
/* Transitions */
|
||||
--transition-fast: 150ms ease;
|
||||
--transition-normal: 300ms ease;
|
||||
--transition-slow: 500ms ease;
|
||||
|
||||
/* Z-index layers */
|
||||
--z-grid: 1;
|
||||
--z-event: 10;
|
||||
--z-event-hover: 20;
|
||||
--z-drag-ghost: 30;
|
||||
--z-current-time: 40;
|
||||
--z-popup: 100;
|
||||
--z-loading: 200;
|
||||
}
|
||||
|
||||
/* Base styles */
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
color: var(--color-text);
|
||||
background-color: var(--color-surface);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
/* Custom elements default display */
|
||||
swp-calendar,
|
||||
swp-calendar-nav,
|
||||
swp-calendar-container,
|
||||
swp-time-axis,
|
||||
swp-week-header,
|
||||
swp-scrollable-content,
|
||||
swp-time-grid,
|
||||
swp-day-columns,
|
||||
swp-day-column,
|
||||
swp-events-layer,
|
||||
swp-event,
|
||||
swp-allday-container,
|
||||
swp-loading-overlay,
|
||||
swp-event-popup {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Scrollbar styling */
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: var(--color-surface);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #bbb;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #999;
|
||||
}
|
||||
|
||||
/* Selection styling */
|
||||
::selection {
|
||||
background-color: rgba(33, 150, 243, 0.2);
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/* Focus styles */
|
||||
:focus {
|
||||
outline: 2px solid var(--color-primary);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
:focus:not(:focus-visible) {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* Utility classes */
|
||||
.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
visibility: hidden !important;
|
||||
}
|
||||
|
||||
.transparent {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
opacity: 0.6;
|
||||
transform: scale(1.2);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideIn {
|
||||
from {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
to {
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
184
wwwroot/css/calendar-components-css.css
Normal file
184
wwwroot/css/calendar-components-css.css
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
/* styles/components/navigation.css */
|
||||
|
||||
/* Navigation bar */
|
||||
swp-calendar-nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 24px;
|
||||
padding: 12px 16px;
|
||||
background: var(--color-background);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
/* Navigation groups */
|
||||
swp-nav-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
/* Navigation buttons */
|
||||
swp-nav-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 8px 16px;
|
||||
border: 1px solid var(--color-border);
|
||||
background: var(--color-background);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
transition: all var(--transition-fast);
|
||||
min-width: 40px;
|
||||
height: 36px;
|
||||
|
||||
&:hover {
|
||||
background: var(--color-surface);
|
||||
border-color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: translateY(1px);
|
||||
}
|
||||
|
||||
/* Icon buttons */
|
||||
svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
stroke-width: 2;
|
||||
}
|
||||
|
||||
/* Today button */
|
||||
&[data-action="today"] {
|
||||
min-width: 70px;
|
||||
}
|
||||
}
|
||||
|
||||
/* View selector */
|
||||
swp-view-selector {
|
||||
display: flex;
|
||||
background: var(--color-surface);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
swp-view-button {
|
||||
padding: 8px 16px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
transition: all var(--transition-fast);
|
||||
position: relative;
|
||||
|
||||
&:not(:last-child) {
|
||||
border-right: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
&:hover:not([disabled]) {
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
&[data-active="true"] {
|
||||
background: var(--color-primary);
|
||||
color: white;
|
||||
|
||||
&:hover {
|
||||
background: var(--color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
&[disabled] {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
/* Search container */
|
||||
swp-search-container {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
|
||||
swp-search-icon {
|
||||
position: absolute;
|
||||
left: 12px;
|
||||
pointer-events: none;
|
||||
color: var(--color-text-secondary);
|
||||
|
||||
svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
input[type="search"] {
|
||||
padding: 8px 36px 8px 36px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 20px;
|
||||
background: var(--color-surface);
|
||||
font-size: 0.875rem;
|
||||
width: 250px;
|
||||
transition: all var(--transition-fast);
|
||||
|
||||
&::-webkit-search-cancel-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: var(--color-primary);
|
||||
background: var(--color-background);
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
}
|
||||
|
||||
swp-search-clear {
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
border-radius: 50%;
|
||||
transition: all var(--transition-fast);
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
stroke: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
&[hidden] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Calendar search active state */
|
||||
swp-calendar[data-searching="true"] {
|
||||
swp-event {
|
||||
opacity: 0.15;
|
||||
transition: opacity var(--transition-normal);
|
||||
|
||||
&[data-search-match="true"] {
|
||||
opacity: 1;
|
||||
box-shadow: 0 0 0 2px rgba(33, 150, 243, 0.3);
|
||||
}
|
||||
}
|
||||
}
|
||||
263
wwwroot/css/calendar-events-css.css
Normal file
263
wwwroot/css/calendar-events-css.css
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
/* styles/components/events.css */
|
||||
|
||||
/* Event base styles */
|
||||
swp-event {
|
||||
position: absolute;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
cursor: move;
|
||||
transition: box-shadow var(--transition-fast), transform var(--transition-fast);
|
||||
z-index: var(--z-event);
|
||||
|
||||
/* CSS-based positioning */
|
||||
top: calc(var(--start-minutes) * var(--minute-height));
|
||||
height: calc(var(--duration-minutes) * var(--minute-height));
|
||||
|
||||
/* Event types */
|
||||
&[data-type="meeting"] {
|
||||
background: var(--color-event-meeting);
|
||||
border-left: 4px solid var(--color-event-meeting-border);
|
||||
}
|
||||
|
||||
&[data-type="meal"] {
|
||||
background: var(--color-event-meal);
|
||||
border-left: 4px solid var(--color-event-meal-border);
|
||||
}
|
||||
|
||||
&[data-type="work"] {
|
||||
background: var(--color-event-work);
|
||||
border-left: 4px solid var(--color-event-work-border);
|
||||
}
|
||||
|
||||
&[data-type="milestone"] {
|
||||
background: var(--color-event-milestone);
|
||||
border-left: 4px solid var(--color-event-milestone-border);
|
||||
}
|
||||
|
||||
/* Hover state */
|
||||
&:hover {
|
||||
box-shadow: var(--shadow-md);
|
||||
transform: scale(1.02);
|
||||
z-index: var(--z-event-hover);
|
||||
|
||||
swp-resize-handle {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Active/selected state */
|
||||
&[data-selected="true"] {
|
||||
box-shadow: 0 0 0 2px var(--color-primary);
|
||||
z-index: var(--z-event-hover);
|
||||
}
|
||||
|
||||
/* Dragging state */
|
||||
&[data-dragging="true"] {
|
||||
opacity: 0.5;
|
||||
cursor: grabbing;
|
||||
z-index: var(--z-drag-ghost);
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: -2px;
|
||||
border: 2px solid var(--color-primary);
|
||||
border-radius: 6px;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Resizing state */
|
||||
&[data-resizing="true"] {
|
||||
opacity: 0.8;
|
||||
|
||||
swp-resize-handle {
|
||||
opacity: 1;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
background: var(--color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Sync status indicators */
|
||||
&[data-sync-status="pending"] {
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: var(--color-warning);
|
||||
border-radius: 50%;
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
}
|
||||
|
||||
&[data-sync-status="error"] {
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: var(--color-danger);
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Event header */
|
||||
swp-event-header {
|
||||
padding: 8px 12px 4px;
|
||||
|
||||
swp-event-time {
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
/* Event body */
|
||||
swp-event-body {
|
||||
padding: 0 12px 8px;
|
||||
|
||||
swp-event-title {
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.3;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
/* Multi-line ellipsis */
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
}
|
||||
|
||||
/* Resize handles */
|
||||
swp-resize-handle {
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
right: 8px;
|
||||
height: 4px;
|
||||
opacity: 0;
|
||||
transition: opacity var(--transition-fast);
|
||||
|
||||
/* The two lines */
|
||||
&::before,
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 1px;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
&::before {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
&::after {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
/* Hit area */
|
||||
swp-handle-hitarea {
|
||||
position: absolute;
|
||||
left: -8px;
|
||||
right: -8px;
|
||||
top: -6px;
|
||||
bottom: -6px;
|
||||
cursor: ns-resize;
|
||||
}
|
||||
|
||||
&[data-position="top"] {
|
||||
top: 4px;
|
||||
}
|
||||
|
||||
&[data-position="bottom"] {
|
||||
bottom: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Multi-day events */
|
||||
swp-multi-day-event {
|
||||
position: relative;
|
||||
height: 28px;
|
||||
margin: 2px 4px;
|
||||
padding: 0 8px;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all var(--transition-fast);
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
/* Event type colors */
|
||||
&[data-type="milestone"] {
|
||||
background: var(--color-event-milestone);
|
||||
color: var(--color-event-milestone-border);
|
||||
}
|
||||
|
||||
/* Continuation indicators */
|
||||
&[data-continues-before="true"] {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
margin-left: 0;
|
||||
padding-left: 20px;
|
||||
|
||||
&::before {
|
||||
content: '◀';
|
||||
position: absolute;
|
||||
left: 4px;
|
||||
opacity: 0.6;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
&[data-continues-after="true"] {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
margin-right: 0;
|
||||
padding-right: 20px;
|
||||
|
||||
&::after {
|
||||
content: '▶';
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
opacity: 0.6;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
}
|
||||
|
||||
/* Event creation preview */
|
||||
swp-event-preview {
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
right: 8px;
|
||||
background: rgba(33, 150, 243, 0.1);
|
||||
border: 2px dashed var(--color-primary);
|
||||
border-radius: 4px;
|
||||
pointer-events: none;
|
||||
|
||||
/* Position via CSS variables */
|
||||
top: calc(var(--preview-start) * var(--minute-height));
|
||||
height: calc(var(--preview-duration) * var(--minute-height));
|
||||
}
|
||||
257
wwwroot/css/calendar-layout-css.css
Normal file
257
wwwroot/css/calendar-layout-css.css
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
/* styles/layout.css */
|
||||
|
||||
/* Main calendar container */
|
||||
swp-calendar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
background: var(--color-background);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Calendar container grid */
|
||||
swp-calendar-container {
|
||||
flex: 1;
|
||||
display: grid;
|
||||
grid-template-columns: 60px 1fr;
|
||||
grid-template-rows: auto 1fr;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Time axis (left side) */
|
||||
swp-time-axis {
|
||||
grid-column: 1;
|
||||
grid-row: 2;
|
||||
background: var(--color-surface);
|
||||
border-right: 1px solid var(--color-border);
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
swp-hour-marker {
|
||||
height: var(--hour-height);
|
||||
padding: 8px;
|
||||
font-size: 0.75rem;
|
||||
color: var(--color-text-secondary);
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
position: relative;
|
||||
|
||||
/* Hour line extending into calendar */
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 100%;
|
||||
width: 100vw;
|
||||
height: 1px;
|
||||
background: var(--color-grid-line);
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Week header */
|
||||
swp-week-header {
|
||||
grid-column: 2;
|
||||
grid-row: 1;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(var(--week-days, 7), 1fr);
|
||||
background: var(--color-surface);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
swp-day-header {
|
||||
padding: 12px;
|
||||
text-align: center;
|
||||
border-right: 1px solid var(--color-grid-line);
|
||||
|
||||
&:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
swp-day-name {
|
||||
display: block;
|
||||
font-weight: 500;
|
||||
font-size: 0.875rem;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
swp-day-date {
|
||||
display: block;
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* Today indicator */
|
||||
&[data-today="true"] {
|
||||
swp-day-date {
|
||||
color: var(--color-primary);
|
||||
background: rgba(33, 150, 243, 0.1);
|
||||
border-radius: 50%;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 4px auto 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Scrollable content */
|
||||
swp-scrollable-content {
|
||||
grid-column: 2;
|
||||
grid-row: 2;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
scroll-behavior: smooth;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* All-day events container */
|
||||
swp-allday-container {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
background: var(--color-background);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
min-height: 0;
|
||||
z-index: 2;
|
||||
|
||||
&:not(:empty) {
|
||||
padding: 8px 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Time grid */
|
||||
swp-time-grid {
|
||||
position: relative;
|
||||
height: calc(var(--total-hours, 12) * var(--hour-height));
|
||||
|
||||
/* Work hours background */
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: calc((var(--work-start-hour) - var(--day-start-hour)) * var(--hour-height));
|
||||
height: calc((var(--work-end-hour) - var(--work-start-hour)) * var(--hour-height));
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: var(--color-work-hours);
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Grid lines */
|
||||
swp-grid-lines {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
pointer-events: none;
|
||||
|
||||
/* 15-minute intervals */
|
||||
background-image: repeating-linear-gradient(
|
||||
to bottom,
|
||||
transparent,
|
||||
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)
|
||||
);
|
||||
|
||||
/* Show stronger lines when dragging */
|
||||
&[data-dragging="true"] {
|
||||
background-image: repeating-linear-gradient(
|
||||
to bottom,
|
||||
transparent,
|
||||
transparent calc(var(--hour-height) / 4 - 1px),
|
||||
rgba(33, 150, 243, 0.2) calc(var(--hour-height) / 4 - 1px),
|
||||
rgba(33, 150, 243, 0.2) calc(var(--hour-height) / 4)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/* Day columns */
|
||||
swp-day-columns {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(var(--week-days, 7), 1fr);
|
||||
}
|
||||
|
||||
swp-day-column {
|
||||
position: relative;
|
||||
border-right: 1px solid var(--color-grid-line);
|
||||
|
||||
&:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
/* Hover effect for empty slots */
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.01);
|
||||
}
|
||||
}
|
||||
|
||||
/* Events layer */
|
||||
swp-events-layer {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
|
||||
/* Layout modes */
|
||||
&[data-layout="overlap"] {
|
||||
swp-event {
|
||||
width: calc(100% - 16px);
|
||||
left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&[data-layout="side-by-side"] {
|
||||
swp-event {
|
||||
width: calc(var(--event-width, 100%) - 16px);
|
||||
left: calc(8px + var(--event-offset, 0px));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Current time indicator */
|
||||
swp-current-time-indicator {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 2px;
|
||||
background: var(--color-current-time);
|
||||
pointer-events: none;
|
||||
z-index: var(--z-current-time);
|
||||
|
||||
/* Time label */
|
||||
&::before {
|
||||
content: attr(data-time);
|
||||
position: absolute;
|
||||
left: -55px;
|
||||
top: -10px;
|
||||
background: var(--color-current-time);
|
||||
color: white;
|
||||
padding: 2px 6px;
|
||||
font-size: 0.75rem;
|
||||
border-radius: 3px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Animated dot */
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: -4px;
|
||||
top: -4px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: var(--color-current-time);
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 0 2px rgba(255, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
/* Position based on current time */
|
||||
top: calc(var(--current-minutes) * var(--minute-height));
|
||||
}
|
||||
190
wwwroot/css/calendar-popup-css.css
Normal file
190
wwwroot/css/calendar-popup-css.css
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
/* styles/components/popup.css */
|
||||
|
||||
/* Event popup */
|
||||
swp-event-popup {
|
||||
position: fixed;
|
||||
background: #f9f5f0;
|
||||
border-radius: 8px;
|
||||
box-shadow: var(--shadow-popup);
|
||||
padding: 16px;
|
||||
min-width: 300px;
|
||||
z-index: var(--z-popup);
|
||||
animation: fadeIn var(--transition-fast);
|
||||
|
||||
/* Chevron arrow */
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: inherit;
|
||||
transform: rotate(45deg);
|
||||
top: 50%;
|
||||
margin-top: -8px;
|
||||
}
|
||||
|
||||
/* Right-side popup (arrow on left) */
|
||||
&[data-align="right"] {
|
||||
&::before {
|
||||
left: -8px;
|
||||
box-shadow: -2px 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Left-side popup (arrow on right) */
|
||||
&[data-align="left"] {
|
||||
&::before {
|
||||
right: -8px;
|
||||
box-shadow: 2px -2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
&[hidden] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Popup header */
|
||||
swp-popup-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 16px;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
swp-popup-title {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-text);
|
||||
line-height: 1.4;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* Popup actions */
|
||||
swp-popup-actions {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
swp-action-button {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: background var(--transition-fast);
|
||||
color: var(--color-text-secondary);
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
/* Specific button styles */
|
||||
&[data-action="delete"]:hover {
|
||||
color: var(--color-danger);
|
||||
}
|
||||
|
||||
&[data-action="close"]:hover {
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Popup content */
|
||||
swp-popup-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
swp-time-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
color: var(--color-text-secondary);
|
||||
font-size: 0.875rem;
|
||||
|
||||
swp-icon {
|
||||
font-size: 1.25rem;
|
||||
color: var(--color-secondary);
|
||||
}
|
||||
}
|
||||
|
||||
/* Loading overlay */
|
||||
swp-loading-overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: var(--z-loading);
|
||||
backdrop-filter: blur(2px);
|
||||
|
||||
&[hidden] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
swp-spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 3px solid var(--color-surface);
|
||||
border-top-color: var(--color-primary);
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
/* Snap indicator */
|
||||
swp-snap-indicator {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 2px;
|
||||
background: var(--color-primary);
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
transition: opacity var(--transition-fast);
|
||||
z-index: var(--z-drag-ghost);
|
||||
|
||||
&[data-active="true"] {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: attr(data-time);
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
top: -24px;
|
||||
background: var(--color-primary);
|
||||
color: white;
|
||||
padding: 2px 8px;
|
||||
font-size: 0.75rem;
|
||||
border-radius: 3px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 768px) {
|
||||
swp-event-popup {
|
||||
min-width: 250px;
|
||||
max-width: calc(100vw - 32px);
|
||||
}
|
||||
|
||||
swp-popup-title {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
498
wwwroot/css/calendar.css
Normal file
498
wwwroot/css/calendar.css
Normal file
|
|
@ -0,0 +1,498 @@
|
|||
/* Base CSS */
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:root {
|
||||
/* Grid measurements */
|
||||
--hour-height: 60px;
|
||||
--minute-height: 1px;
|
||||
--snap-interval: 15;
|
||||
|
||||
/* Time boundaries */
|
||||
--day-start-hour: 7;
|
||||
--day-end-hour: 19;
|
||||
--work-start-hour: 8;
|
||||
--work-end-hour: 17;
|
||||
|
||||
/* Colors */
|
||||
--color-primary: #2196f3;
|
||||
--color-grid-line: #e0e0e0;
|
||||
--color-grid-line-light: rgba(0, 0, 0, 0.03);
|
||||
--color-work-hours: rgba(0, 100, 0, 0.02);
|
||||
--color-current-time: #ff0000;
|
||||
|
||||
/* Event colors */
|
||||
--color-event-meeting: #e3f2fd;
|
||||
--color-event-meeting-border: #2196f3;
|
||||
--color-event-meal: #fff3e0;
|
||||
--color-event-meal-border: #ff9800;
|
||||
--color-event-work: #f3e5f5;
|
||||
--color-event-work-border: #9c27b0;
|
||||
|
||||
/* UI colors */
|
||||
--color-background: #ffffff;
|
||||
--color-surface: #f5f5f5;
|
||||
--color-text: #333333;
|
||||
--color-text-secondary: #666666;
|
||||
--color-border: #e0e0e0;
|
||||
|
||||
/* Shadows */
|
||||
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
color: var(--color-text);
|
||||
background-color: var(--color-surface);
|
||||
}
|
||||
|
||||
/* Custom elements default display */
|
||||
swp-calendar,
|
||||
swp-calendar-nav,
|
||||
swp-calendar-container,
|
||||
swp-time-axis,
|
||||
swp-week-header,
|
||||
swp-scrollable-content,
|
||||
swp-time-grid,
|
||||
swp-day-columns,
|
||||
swp-day-column,
|
||||
swp-events-layer,
|
||||
swp-event,
|
||||
swp-loading-overlay,
|
||||
swp-week-container,
|
||||
swp-grid-lines {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Main calendar container */
|
||||
swp-calendar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
background: var(--color-background);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Navigation bar */
|
||||
swp-calendar-nav {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto auto;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
padding: 12px 16px;
|
||||
background: var(--color-background);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
swp-nav-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
swp-nav-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 8px 16px;
|
||||
border: 1px solid var(--color-border);
|
||||
background: var(--color-background);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
transition: all 150ms ease;
|
||||
min-width: 40px;
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
swp-nav-button:hover {
|
||||
background: var(--color-surface);
|
||||
border-color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
/* Search container */
|
||||
swp-search-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
justify-self: end;
|
||||
}
|
||||
|
||||
swp-search-icon {
|
||||
position: absolute;
|
||||
left: 12px;
|
||||
pointer-events: none;
|
||||
color: var(--color-text-secondary);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
swp-search-icon svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
swp-search-container input[type="search"] {
|
||||
padding: 8px 36px 8px 36px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 20px;
|
||||
background: var(--color-surface);
|
||||
font-size: 0.875rem;
|
||||
width: 200px;
|
||||
transition: all 150ms ease;
|
||||
}
|
||||
|
||||
swp-search-container input[type="search"]::-webkit-search-cancel-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
swp-search-container input[type="search"]:focus {
|
||||
outline: none;
|
||||
border-color: var(--color-primary);
|
||||
background: var(--color-background);
|
||||
width: 250px;
|
||||
box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);
|
||||
}
|
||||
|
||||
swp-search-container input[type="search"]::placeholder {
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
swp-search-clear {
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
border-radius: 50%;
|
||||
transition: all 150ms ease;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
swp-search-clear:hover {
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
swp-search-clear svg {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
swp-search-clear[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
swp-view-button {
|
||||
padding: 8px 16px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
transition: all 150ms ease;
|
||||
}
|
||||
|
||||
swp-view-button:not(:last-child) {
|
||||
border-right: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
swp-view-button[data-active="true"] {
|
||||
background: var(--color-primary);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Calendar container grid */
|
||||
swp-calendar-container {
|
||||
flex: 1;
|
||||
display: grid;
|
||||
grid-template-columns: 60px 1fr;
|
||||
grid-template-rows: 1fr;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Week container for sliding */
|
||||
swp-week-container {
|
||||
grid-column: 2;
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
transition: transform 400ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
swp-week-container.slide-out-left {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
swp-week-container.slide-out-right {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
swp-week-container.slide-in-left {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
swp-week-container.slide-in-right {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
/* Time axis */
|
||||
swp-time-axis {
|
||||
grid-column: 1;
|
||||
grid-row: 1;
|
||||
background: var(--color-surface);
|
||||
border-right: 1px solid var(--color-border);
|
||||
position: sticky;
|
||||
left: 0;
|
||||
z-index: 4;
|
||||
padding-top: 80px; /* Match header height */
|
||||
}
|
||||
|
||||
swp-hour-marker {
|
||||
height: var(--hour-height);
|
||||
padding: 0 8px 8px 8px;
|
||||
font-size: 0.75rem;
|
||||
color: var(--color-text-secondary);
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
swp-hour-marker::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 100%;
|
||||
width: 100vw;
|
||||
height: 1px;
|
||||
background: var(--color-grid-line);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Week header */
|
||||
swp-week-header {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(7, 1fr);
|
||||
background: var(--color-surface);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 3;
|
||||
height: 80px; /* Fixed height */
|
||||
}
|
||||
|
||||
swp-day-header {
|
||||
padding: 12px;
|
||||
text-align: center;
|
||||
border-right: 1px solid var(--color-grid-line);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
swp-day-header:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
swp-day-name {
|
||||
display: block;
|
||||
font-weight: 500;
|
||||
font-size: 0.875rem;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
swp-day-date {
|
||||
display: block;
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
swp-day-header[data-today="true"] swp-day-date {
|
||||
color: var(--color-primary);
|
||||
background: rgba(33, 150, 243, 0.1);
|
||||
border-radius: 50%;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 4px auto 0;
|
||||
}
|
||||
|
||||
/* Scrollable content */
|
||||
swp-scrollable-content {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
scroll-behavior: smooth;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Time grid */
|
||||
swp-time-grid {
|
||||
position: relative;
|
||||
height: calc(12 * var(--hour-height));
|
||||
}
|
||||
|
||||
swp-time-grid::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: calc((var(--work-start-hour) - var(--day-start-hour)) * var(--hour-height));
|
||||
height: calc((var(--work-end-hour) - var(--work-start-hour)) * var(--hour-height));
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: var(--color-work-hours);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Grid lines */
|
||||
swp-grid-lines {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
pointer-events: none;
|
||||
background-image: repeating-linear-gradient(
|
||||
to bottom,
|
||||
transparent,
|
||||
transparent calc(var(--hour-height) / 4 - 1px),
|
||||
rgba(0, 0, 0, 0.03) calc(var(--hour-height) / 4 - 1px),
|
||||
rgba(0, 0, 0, 0.03) calc(var(--hour-height) / 4)
|
||||
);
|
||||
}
|
||||
|
||||
/* Day columns */
|
||||
swp-day-columns {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(7, 1fr);
|
||||
}
|
||||
|
||||
swp-day-column {
|
||||
position: relative;
|
||||
border-right: 1px solid var(--color-grid-line);
|
||||
}
|
||||
|
||||
swp-day-column:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
swp-events-layer {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
}
|
||||
|
||||
/* Events */
|
||||
swp-event {
|
||||
position: absolute;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
cursor: move;
|
||||
transition: box-shadow 150ms ease, transform 150ms ease;
|
||||
z-index: 10;
|
||||
left: 1px;
|
||||
right: 1px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
swp-event[data-type="meeting"] {
|
||||
background: var(--color-event-meeting);
|
||||
border-left: 4px solid var(--color-event-meeting-border);
|
||||
}
|
||||
|
||||
swp-event[data-type="meal"] {
|
||||
background: var(--color-event-meal);
|
||||
border-left: 4px solid var(--color-event-meal-border);
|
||||
}
|
||||
|
||||
swp-event[data-type="work"] {
|
||||
background: var(--color-event-work);
|
||||
border-left: 4px solid var(--color-event-work-border);
|
||||
}
|
||||
|
||||
swp-event:hover {
|
||||
box-shadow: var(--shadow-md);
|
||||
transform: scale(1.02);
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
swp-event-time {
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
opacity: 0.8;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
swp-event-title {
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
/* Loading */
|
||||
swp-loading-overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 200;
|
||||
}
|
||||
|
||||
swp-loading-overlay[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
swp-spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 3px solid #f3f3f3;
|
||||
border-top: 3px solid var(--color-primary);
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* Week info styles */
|
||||
swp-week-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
swp-week-number {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
swp-date-range {
|
||||
font-size: 0.875rem;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
swp-view-selector {
|
||||
display: flex;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
122
wwwroot/index.html
Normal file
122
wwwroot/index.html
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Calendar Plantempus - Week View</title>
|
||||
|
||||
<!-- CSS Files -->
|
||||
<link rel="stylesheet" href="css/calendar.css">
|
||||
|
||||
<!-- Additional styles for view selector -->
|
||||
<style>
|
||||
swp-view-selector {
|
||||
display: flex;
|
||||
background: var(--color-surface);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
swp-view-button {
|
||||
padding: 8px 16px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
transition: all 150ms ease;
|
||||
}
|
||||
|
||||
swp-view-button:not(:last-child) {
|
||||
border-right: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
swp-view-button[data-active="true"] {
|
||||
background: var(--color-primary);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Week info display */
|
||||
swp-week-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
font-size: 0.875rem;
|
||||
color: var(--color-text-secondary);
|
||||
justify-self: start;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
swp-week-number {
|
||||
font-weight: 600;
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
swp-date-range {
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<swp-calendar data-view="week" data-week-days="7" data-snap-interval="15">
|
||||
<!-- Navigation Bar -->
|
||||
<swp-calendar-nav>
|
||||
<swp-nav-group>
|
||||
<swp-nav-button data-action="prev">←</swp-nav-button>
|
||||
<swp-nav-button data-action="next">→</swp-nav-button>
|
||||
<swp-nav-button data-action="today">Today</swp-nav-button>
|
||||
</swp-nav-group>
|
||||
|
||||
<swp-week-info>
|
||||
<swp-week-number>Week 3</swp-week-number>
|
||||
<swp-date-range>Jan 15 - Jan 21, 2024</swp-date-range>
|
||||
</swp-week-info>
|
||||
|
||||
<swp-search-container>
|
||||
<swp-search-icon>
|
||||
<svg width="16" height="16" viewBox="0 0 16 16">
|
||||
<circle cx="6" cy="6" r="5" stroke="currentColor" fill="none" stroke-width="1.5"/>
|
||||
<path d="M10 10l4 4" stroke="currentColor" stroke-width="1.5"/>
|
||||
</svg>
|
||||
</swp-search-icon>
|
||||
<input type="search" placeholder="Search events..." />
|
||||
<swp-search-clear hidden>
|
||||
<svg width="14" height="14" viewBox="0 0 16 16">
|
||||
<path d="M5 5l6 6M11 5l-6 6" stroke="currentColor" stroke-width="2"/>
|
||||
</svg>
|
||||
</swp-search-clear>
|
||||
</swp-search-container>
|
||||
|
||||
<swp-view-selector>
|
||||
<swp-view-button data-view="day">Day</swp-view-button>
|
||||
<swp-view-button data-view="week" data-active="true">Week</swp-view-button>
|
||||
<swp-view-button data-view="month" disabled>Month</swp-view-button>
|
||||
</swp-view-selector>
|
||||
</swp-calendar-nav>
|
||||
|
||||
<!-- Calendar Grid -->
|
||||
<swp-calendar-container>
|
||||
<swp-time-axis></swp-time-axis>
|
||||
|
||||
<swp-week-container>
|
||||
<swp-week-header></swp-week-header>
|
||||
|
||||
<swp-scrollable-content>
|
||||
<swp-time-grid>
|
||||
<swp-grid-lines></swp-grid-lines>
|
||||
<swp-day-columns></swp-day-columns>
|
||||
</swp-time-grid>
|
||||
</swp-scrollable-content>
|
||||
</swp-week-container>
|
||||
</swp-calendar-container>
|
||||
|
||||
<swp-loading-overlay hidden>
|
||||
<swp-spinner></swp-spinner>
|
||||
</swp-loading-overlay>
|
||||
</swp-calendar>
|
||||
|
||||
<!-- JavaScript Bundle -->
|
||||
<script type="module" src="js/calendar.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue