Files
advanced-camera-card/src/scss/timeline-core.scss
T
Dermot Duffy fc32727860 feat: Add support for Frigate reviews / detections [initial PR] (#2315)
- Add support for Frigate reviews / detections.
 - Add support for GenAI metadata.
- Significant internal refactor to more flexible "UnifiedQuery" to allow
mixing cameras with simple metadata and review metadata (e.g. a timeline
view of a Frigate camera with reviews, and a Reolink camera with simple
metadata).
 - Add support for folder media as camera media.

There are a few more PRs to commit prior to this going live, but
commiting this for now due to the scale of the change.

BREAKING CHANGE: `media_type` and `events_type` are retired under
`live`, `viewer` and `timeline` configuration sections, instead media
type is associated (once) with the camera under `media`.
2026-01-19 13:32:50 -08:00

211 lines
5.4 KiB
SCSS

@use 'vis-timeline/dist/vis-timeline-graph2d.css';
@use 'drawer';
@use 'const.scss';
:host {
width: 100%;
// Share the screen space with thumbnails that may be above/below.
display: flex;
flex-direction: column;
// So that absolute sidedrawer is relative to this host.
position: relative;
background-color: var(--advanced-camera-card-timeline-background);
}
:host(:not([mini])) {
// Timeline covers 100% of the parent unless it's in mini-mode.
height: 100%;
}
advanced-camera-card-thumbnail {
height: var(--advanced-camera-card-thumbnail-size);
width: var(--advanced-camera-card-thumbnail-size);
}
advanced-camera-card-thumbnail[details] {
width: var(--advanced-camera-card-thumbnail-details-width);
}
div.timeline {
flex: 1;
}
.vis-text {
color: var(--advanced-camera-card-timeline-text-color) !important;
}
.vis-timeline {
border: none;
}
.vis-labelset .vis-label {
// Group labels.
color: var(--advanced-camera-card-timeline-text-color);
}
:host([ribbon]:not([groups])) .vis-item:not(.vis-background) {
// When a ribbon timeline is used without groups, we need to add extra margin
// to the top to center the bar vertically within the mini-timeline.
margin-top: 7px;
}
:host([ribbon]) .vis-item:not(.vis-background) {
// Ribbon timelines have a much shorter 'bar'.
height: 6px;
}
.vis-item {
border-color: var(--advanced-camera-card-timeline-item-color);
background: none;
color: var(--advanced-camera-card-timeline-text-color);
background-color: var(--advanced-camera-card-timeline-item-color);
transition:
background-color ease-in-out 1s,
border-color ease-in-out 1s,
box-shadow ease-in-out 1s;
}
.vis-item[data-severity='high'] {
border-color: var(--advanced-camera-card-timeline-item-severity-high-color);
background-color: var(--advanced-camera-card-timeline-item-severity-high-color);
}
.vis-item[data-severity='medium'] {
border-color: var(--advanced-camera-card-timeline-item-severity-medium-color);
background-color: var(--advanced-camera-card-timeline-item-severity-medium-color);
}
.vis-item[data-severity='low'] {
border-color: var(--advanced-camera-card-timeline-item-severity-low-color);
background-color: var(--advanced-camera-card-timeline-item-severity-low-color);
}
.vis-item.vis-selected {
border-color: var(--advanced-camera-card-active-color);
background-color: var(--advanced-camera-card-active-color);
box-shadow: var(
--advanced-camera-card-box-shadow-override,
0px 0px 5px 1px var(--advanced-camera-card-active-color)
);
}
.vis-item.vis-background {
background-color: var(--advanced-camera-card-timeline-background-item-color);
}
// If there are no timeline groups shown (e.g. mini mode with a single camera),
// ensure the background (recordings) always span the full height. Otherwise, in
// cases where there are no events, the background is incorrectly rendered too
// short by visjs.
:host(:not([groups])) .vis-item.vis-background {
min-height: 100%;
}
.vis-item:not(.vis-background) {
cursor: pointer;
}
:host([recordings]) .vis-item.vis-background,
:host([recordings]) .vis-time-axis {
cursor: crosshair;
}
.vis-item:active {
cursor: unset;
}
.vis-item.vis-box {
border: none;
}
.vis-item .vis-item-content {
padding: 0px;
}
.vis-item.vis-cluster {
border-style: dotted;
color: var(--advanced-camera-card-timeline-text-color);
background-color: var(--advanced-camera-card-timeline-background);
box-shadow: var(
--advanced-camera-card-box-shadow-override,
0px 0px 5px 1px var(--advanced-camera-card-timeline-item-color)
);
}
.vis-item.vis-range {
border-radius: var(--advanced-camera-card-border-radius-final);
}
.vis-time-axis .vis-grid.vis-minor {
border-color: var(--advanced-camera-card-timeline-divider-color);
}
// Give an indication that the user can interact with the axes.
.vis-text.vis-minor,
.vis-label {
transition: background-color 0.5s ease-out;
}
:host([recordings]) .vis-text.vis-minor:hover {
background-color: color-mix(
in oklab,
var(--advanced-camera-card-timeline-text-color),
transparent 80%
);
}
.vis-time-axis .vis-grid.vis-major {
border-color: var(--advanced-camera-card-timeline-divider-color);
}
.vis-label {
display: flex;
justify-content: center;
align-items: center;
}
div.vis-tooltip {
padding: 0px;
background-color: unset;
border: none;
// Use browser default font-family for tooltips.
font-family: unset;
z-index: 30;
}
.target_bar {
background-color: var(--advanced-camera-card-timeline-target-bar-color);
width: 2px;
z-index: 20;
// Prevent the mouse interacting with the custom time.
pointer-events: none;
}
.target_bar .vis-custom-time-marker {
background-color: var(--advanced-camera-card-timeline-background);
color: var(--advanced-camera-card-timeline-text-color);
bottom: 0px;
top: unset;
}
:host([target-bar-marker-direction='right']) .target_bar .vis-custom-time-marker {
left: 2px;
}
:host([target-bar-marker-direction='left']) .target_bar .vis-custom-time-marker {
right: 2px;
}
:host([target-bar-marker-direction='center']) .target_bar .vis-custom-time-marker {
left: 0px;
transform: translateX(-50%);
}
.timeline-tools {
display: inline-flex;
position: absolute;
right: 0px;
bottom: 0px;
color: var(--advanced-camera-card-timeline-tool-color);
z-index: 10;
}
.timeline-tools * {
margin: 2px 5px;
cursor: pointer;
}
.timeline-tools *:last-child {
margin-right: 10px;
}