Update dimensions and media layout options to be per camera.
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import { StyleInfo } from 'lit/directives/style-map';
|
||||
import { FrigateCardConfig } from '../config/types';
|
||||
import { setPerformanceCSSStyles } from '../performance';
|
||||
import { aspectRatioToStyle, setOrRemoveAttribute } from '../utils/basic';
|
||||
import { View } from '../view/view';
|
||||
import { setOrRemoveAttribute } from '../utils/basic';
|
||||
import { CardStyleAPI } from './types';
|
||||
|
||||
export class StyleManager {
|
||||
@@ -103,24 +104,23 @@ export class StyleManager {
|
||||
* required).
|
||||
* @returns A padding percentage.
|
||||
*/
|
||||
public getAspectRatioStyle(): string {
|
||||
public getAspectRatioStyle(): StyleInfo {
|
||||
const config = this._api.getConfigManager().getConfig();
|
||||
const view = this._api.getViewManager().getView();
|
||||
|
||||
if (config) {
|
||||
if (!this._isAspectRatioEnforced(config, view)) {
|
||||
return 'auto';
|
||||
return aspectRatioToStyle();
|
||||
}
|
||||
|
||||
const aspectRatioMode = config.dimensions.aspect_ratio_mode;
|
||||
|
||||
const lastKnown = this._api.getMediaLoadedInfoManager().getLastKnown();
|
||||
if (lastKnown && aspectRatioMode === 'dynamic') {
|
||||
return `${lastKnown.width} / ${lastKnown.height}`;
|
||||
return aspectRatioToStyle({ ratio: [lastKnown.width, lastKnown.height] });
|
||||
}
|
||||
|
||||
return `${config.dimensions.aspect_ratio[0]} / ${config.dimensions.aspect_ratio[1]}`;
|
||||
return aspectRatioToStyle({ ratio: config.dimensions.aspect_ratio });
|
||||
}
|
||||
return '16 / 9';
|
||||
return aspectRatioToStyle({ defaultStatic: true });
|
||||
}
|
||||
}
|
||||
|
||||
+1
-4
@@ -242,9 +242,6 @@ class FrigateCard extends LitElement {
|
||||
return;
|
||||
}
|
||||
|
||||
const cardStyle = {
|
||||
'aspect-ratio': this._controller.getStyleManager().getAspectRatioStyle(),
|
||||
};
|
||||
const mainClasses = {
|
||||
main: true,
|
||||
'curve-top':
|
||||
@@ -266,7 +263,7 @@ class FrigateCard extends LitElement {
|
||||
hasHold: frigateCardHasAction(actions.hold_action),
|
||||
hasDoubleClick: frigateCardHasAction(actions.double_tap_action),
|
||||
})}
|
||||
style="${styleMap(cardStyle)}"
|
||||
style="${styleMap(this._controller.getStyleManager().getAspectRatioStyle())}"
|
||||
@frigate-card:message=${(ev: CustomEvent<Message>) =>
|
||||
this._controller.getMessageManager().setMessageIfHigherPriority(ev.detail)}
|
||||
@frigate-card:view:change=${(ev: CustomEvent<View>) =>
|
||||
|
||||
@@ -41,7 +41,7 @@ import {
|
||||
Message,
|
||||
} from '../../types.js';
|
||||
import { stopEventFromActivatingCardWideActions } from '../../utils/action.js';
|
||||
import { contentsChanged } from '../../utils/basic.js';
|
||||
import { aspectRatioToString, contentsChanged } from '../../utils/basic.js';
|
||||
import { CarouselSelected } from '../../utils/embla/carousel-controller.js';
|
||||
import { AutoLazyLoad } from '../../utils/embla/plugins/auto-lazy-load/auto-lazy-load.js';
|
||||
import { AutoMediaActions } from '../../utils/embla/plugins/auto-media-actions/auto-media-actions.js';
|
||||
@@ -900,7 +900,6 @@ export class FrigateCardLiveProvider
|
||||
}
|
||||
}
|
||||
if (changedProps.has('liveConfig')) {
|
||||
updateElementStyleFromMediaLayoutConfig(this, this.liveConfig?.layout);
|
||||
if (this.liveConfig?.show_image_during_load) {
|
||||
this._importPromises.push(import('./live-image.js'));
|
||||
}
|
||||
@@ -908,6 +907,7 @@ export class FrigateCardLiveProvider
|
||||
this._importPromises.push(import('./../zoomer.js'));
|
||||
}
|
||||
}
|
||||
|
||||
if (changedProps.has('cameraConfig')) {
|
||||
const provider = this._getResolvedProvider();
|
||||
if (provider === 'jsmpeg') {
|
||||
@@ -921,6 +921,14 @@ export class FrigateCardLiveProvider
|
||||
} else if (provider === 'go2rtc') {
|
||||
this._importPromises.push(import('./live-go2rtc.js'));
|
||||
}
|
||||
|
||||
updateElementStyleFromMediaLayoutConfig(
|
||||
this,
|
||||
this.cameraConfig?.dimensions?.layout,
|
||||
);
|
||||
this.style.aspectRatio = aspectRatioToString({
|
||||
ratio: this.cameraConfig?.dimensions?.aspect_ratio,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ import {
|
||||
import { stopEventFromActivatingCardWideActions } from '../utils/action.js';
|
||||
import { mayHaveAudio } from '../utils/audio.js';
|
||||
import {
|
||||
aspectRatioToString,
|
||||
contentsChanged,
|
||||
errorToConsole,
|
||||
setOrRemoveAttribute,
|
||||
@@ -396,10 +397,6 @@ export class FrigateCardViewerCarousel extends LitElement {
|
||||
* @param changedProps The changed properties
|
||||
*/
|
||||
protected willUpdate(changedProps: PropertyValues): void {
|
||||
if (changedProps.has('viewerConfig')) {
|
||||
updateElementStyleFromMediaLayoutConfig(this, this.viewerConfig?.layout);
|
||||
}
|
||||
|
||||
if (changedProps.has('view')) {
|
||||
const newMedia =
|
||||
this.view?.queryResults?.getResults(this.viewFilterCameraID) ?? null;
|
||||
@@ -853,6 +850,18 @@ export class FrigateCardViewerProvider
|
||||
if (changedProps.has('viewerConfig') && this.viewerConfig?.zoomable) {
|
||||
import('./zoomer.js');
|
||||
}
|
||||
|
||||
if (changedProps.has('media') || changedProps.has('cameraManager')) {
|
||||
const cameraID = this.media?.getCameraID();
|
||||
const cameraConfig = cameraID
|
||||
? this.cameraManager?.getStore().getCameraConfig(cameraID)
|
||||
: null;
|
||||
updateElementStyleFromMediaLayoutConfig(this, cameraConfig?.dimensions?.layout);
|
||||
|
||||
this.style.aspectRatio = aspectRatioToString({
|
||||
ratio: cameraConfig?.dimensions?.aspect_ratio,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected _useZoomIfRequired(template: TemplateResult): TemplateResult {
|
||||
|
||||
@@ -6,6 +6,7 @@ import unset from 'lodash-es/unset';
|
||||
import { RawFrigateCardConfig, RawFrigateCardConfigArray } from './config/types';
|
||||
import {
|
||||
CONF_CAMERAS,
|
||||
CONF_CAMERAS_GLOBAL_DIMENSIONS_LAYOUT,
|
||||
CONF_CAMERAS_GLOBAL_IMAGE,
|
||||
CONF_CAMERAS_GLOBAL_JSMPEG,
|
||||
CONF_CAMERAS_GLOBAL_WEBRTC_CARD,
|
||||
@@ -565,4 +566,7 @@ const UPGRADES = [
|
||||
transform: (val) => (val ? 'default' : null),
|
||||
},
|
||||
),
|
||||
upgradeMoveToWithOverrides('live.layout', CONF_CAMERAS_GLOBAL_DIMENSIONS_LAYOUT),
|
||||
deleteWithOverrides('media_viewer.layout'),
|
||||
deleteWithOverrides('image.layout'),
|
||||
];
|
||||
|
||||
+31
-21
@@ -524,19 +524,19 @@ export type FrigateConditional = z.infer<typeof frigateConditionalSchema>;
|
||||
// Cannot use discriminatedUnion since customSchema uses a superRefine, which
|
||||
// causes false rejections.
|
||||
const pictureElementSchema = z.union([
|
||||
menuStateIconSchema,
|
||||
conditionalSchema,
|
||||
customSchema,
|
||||
frigateConditionalSchema,
|
||||
iconSchema,
|
||||
imageSchema,
|
||||
menuIconSchema,
|
||||
menuStateIconSchema,
|
||||
menuSubmenuSchema,
|
||||
menuSubmenuSelectSchema,
|
||||
frigateConditionalSchema,
|
||||
serviceCallButtonSchema,
|
||||
stateBadgeIconSchema,
|
||||
stateIconSchema,
|
||||
stateLabelSchema,
|
||||
serviceCallButtonSchema,
|
||||
iconSchema,
|
||||
imageSchema,
|
||||
conditionalSchema,
|
||||
customSchema,
|
||||
]);
|
||||
const pictureElementsSchema = pictureElementSchema.array().optional();
|
||||
export type PictureElements = z.infer<typeof pictureElementsSchema>;
|
||||
@@ -556,6 +556,21 @@ const mediaLayoutConfigSchema = z.object({
|
||||
});
|
||||
export type MediaLayoutConfig = z.infer<typeof mediaLayoutConfigSchema>;
|
||||
|
||||
// *************************************************************************
|
||||
// Aspect Ratio Configuration
|
||||
// *************************************************************************
|
||||
|
||||
const aspectRatioSchema = z
|
||||
.number()
|
||||
.array()
|
||||
.length(2)
|
||||
.or(
|
||||
z
|
||||
.string()
|
||||
.regex(/^\s*\d+\.?\d*\s*[:/]\s*\d+\.?\d*\s*$/)
|
||||
.transform((input) => input.split(/[:\/]/).map((d) => Number(d))),
|
||||
);
|
||||
|
||||
// *************************************************************************
|
||||
// Image Configuration
|
||||
// Image config base options are used both for the `image` live provider and the
|
||||
@@ -581,7 +596,6 @@ const imageConfigDefault = {
|
||||
const imageConfigSchema = imageBaseConfigSchema
|
||||
.extend({
|
||||
mode: z.enum(IMAGE_MODES).default(imageConfigDefault.mode),
|
||||
layout: mediaLayoutConfigSchema.optional(),
|
||||
zoomable: z.boolean().default(imageConfigDefault.zoomable),
|
||||
})
|
||||
.merge(actionsSchema)
|
||||
@@ -711,6 +725,7 @@ export type TimelineConfig = z.infer<typeof timelineConfigSchema>;
|
||||
// *************************************************************************
|
||||
// Next/Previous Control Configuration
|
||||
// *************************************************************************
|
||||
|
||||
const nextPreviousControlConfigSchema = z.object({
|
||||
style: z.enum(['none', 'chevrons', 'icons', 'thumbnails']),
|
||||
size: z.number().min(BUTTON_SIZE_MIN),
|
||||
@@ -950,7 +965,6 @@ const liveOverridableConfigSchema = z
|
||||
show_image_during_load: z
|
||||
.boolean()
|
||||
.default(liveConfigDefault.show_image_during_load),
|
||||
layout: mediaLayoutConfigSchema.optional(),
|
||||
microphone: microphoneConfigSchema.default(liveConfigDefault.microphone),
|
||||
zoomable: z.boolean().default(liveConfigDefault.zoomable),
|
||||
display: viewDisplaySchema,
|
||||
@@ -1138,6 +1152,13 @@ export const cameraConfigSchema = z
|
||||
webrtc_card: webrtcCardConfigSchema.optional(),
|
||||
|
||||
cast: castSchema.optional(),
|
||||
|
||||
dimensions: z
|
||||
.object({
|
||||
aspect_ratio: aspectRatioSchema.optional(),
|
||||
layout: mediaLayoutConfigSchema.optional(),
|
||||
})
|
||||
.optional(),
|
||||
})
|
||||
.default(cameraConfigDefault);
|
||||
export type CameraConfig = z.infer<typeof cameraConfigSchema>;
|
||||
@@ -1412,7 +1433,6 @@ const viewerConfigSchema = z
|
||||
title: titleControlConfigSchema.optional(),
|
||||
})
|
||||
.default(viewerConfigDefault.controls),
|
||||
layout: mediaLayoutConfigSchema.optional(),
|
||||
})
|
||||
.merge(actionsSchema)
|
||||
.default(viewerConfigDefault);
|
||||
@@ -1477,17 +1497,7 @@ export const dimensionsConfigSchema = z
|
||||
aspect_ratio_mode: z
|
||||
.enum(['dynamic', 'static', 'unconstrained'])
|
||||
.default(dimensionsConfigDefault.aspect_ratio_mode),
|
||||
aspect_ratio: z
|
||||
.number()
|
||||
.array()
|
||||
.length(2)
|
||||
.or(
|
||||
z
|
||||
.string()
|
||||
.regex(/^\s*\d+\s*[:/]\s*\d+\s*$/)
|
||||
.transform((input) => input.split(/[:\/]/).map((d) => Number(d))),
|
||||
)
|
||||
.default(dimensionsConfigDefault.aspect_ratio),
|
||||
aspect_ratio: aspectRatioSchema.default(dimensionsConfigDefault.aspect_ratio),
|
||||
max_height: z.string().default(dimensionsConfigDefault.max_height),
|
||||
min_height: z.string().default(dimensionsConfigDefault.min_height),
|
||||
})
|
||||
|
||||
+10
-11
@@ -11,6 +11,8 @@ export const CONF_CAMERAS_ARRAY_CAST_DASHBOARD_DASHBOARD_PATH =
|
||||
`${CONF_CAMERAS}.#.cast.dashboard.dashboard_path` as const;
|
||||
export const CONF_CAMERAS_ARRAY_CAST_DASHBOARD_VIEW_PATH =
|
||||
`${CONF_CAMERAS}.#.cast.dashboard.view_path` as const;
|
||||
export const CONF_CAMERAS_ARRAY_DIMENSIONS_ASPECT_RATIO =
|
||||
`${CONF_CAMERAS}.#.dimensions.aspect_ratio` as const;
|
||||
export const CONF_CAMERAS_ARRAY_FRIGATE_CLIENT_ID =
|
||||
`${CONF_CAMERAS}.#.frigate.client_id` as const;
|
||||
export const CONF_CAMERAS_ARRAY_FRIGATE_LABELS =
|
||||
@@ -48,6 +50,12 @@ export const CONF_CAMERAS_ARRAY_DEPENDENCIES_CAMERAS =
|
||||
`${CONF_CAMERAS}.#.dependencies.cameras` as const;
|
||||
export const CONF_CAMERAS_ARRAY_DEPENDENCIES_ALL_CAMERAS =
|
||||
`${CONF_CAMERAS}.#.dependencies.all_cameras` as const;
|
||||
export const CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_FIT =
|
||||
`${CONF_CAMERAS}.#.dimensions.layout.fit` as const;
|
||||
export const CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_POSITION_X =
|
||||
`${CONF_CAMERAS}.#.dimensions.layout.position.x` as const;
|
||||
export const CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_POSITION_Y =
|
||||
`${CONF_CAMERAS}.#.dimensions.layout.position.y` as const;
|
||||
export const CONF_CAMERAS_ARRAY_TRIGGERS_MOTION =
|
||||
`${CONF_CAMERAS}.#.triggers.motion` as const;
|
||||
export const CONF_CAMERAS_ARRAY_TRIGGERS_OCCUPANCY =
|
||||
@@ -66,6 +74,8 @@ export const CONF_CAMERAS_GLOBAL_TRIGGERS_OCCUPANCY =
|
||||
`${CONF_CAMERAS_GLOBAL}.triggers.occupancy` as const;
|
||||
export const CONF_CAMERAS_GLOBAL_IMAGE_REFRESH_SECONDS =
|
||||
`${CONF_CAMERAS_GLOBAL}.image.refresh_seconds` as const;
|
||||
export const CONF_CAMERAS_GLOBAL_DIMENSIONS_LAYOUT =
|
||||
`${CONF_CAMERAS_GLOBAL}.dimensions.layout` as const;
|
||||
|
||||
export const CONF_ELEMENTS = 'elements' as const;
|
||||
|
||||
@@ -163,11 +173,6 @@ export const CONF_MEDIA_VIEWER_CONTROLS_TITLE_MODE =
|
||||
`${CONF_MEDIA_VIEWER}.controls.title.mode` as const;
|
||||
export const CONF_MEDIA_VIEWER_CONTROLS_TITLE_DURATION_SECONDS =
|
||||
`${CONF_MEDIA_VIEWER}.controls.title.duration_seconds` as const;
|
||||
export const CONF_MEDIA_VIEWER_LAYOUT_FIT = `${CONF_MEDIA_VIEWER}.layout.fit` as const;
|
||||
export const CONF_MEDIA_VIEWER_LAYOUT_POSITION_X =
|
||||
`${CONF_MEDIA_VIEWER}.layout.position.x` as const;
|
||||
export const CONF_MEDIA_VIEWER_LAYOUT_POSITION_Y =
|
||||
`${CONF_MEDIA_VIEWER}.layout.position.y` as const;
|
||||
|
||||
const CONF_LIVE = 'live' as const;
|
||||
export const CONF_LIVE_AUTO_PLAY = `${CONF_LIVE}.auto_play` as const;
|
||||
@@ -228,9 +233,6 @@ export const CONF_LIVE_DISPLAY_GRID_MAX_COLUMNS =
|
||||
`${CONF_LIVE}.display.grid_max_columns` as const;
|
||||
export const CONF_LIVE_DISPLAY_GRID_SELECTED_WIDTH_FACTOR =
|
||||
`${CONF_LIVE}.display.grid_selected_width_factor` as const;
|
||||
export const CONF_LIVE_LAYOUT_FIT = `${CONF_LIVE}.layout.fit` as const;
|
||||
export const CONF_LIVE_LAYOUT_POSITION_X = `${CONF_LIVE}.layout.position.x` as const;
|
||||
export const CONF_LIVE_LAYOUT_POSITION_Y = `${CONF_LIVE}.layout.position.y` as const;
|
||||
export const CONF_LIVE_DRAGGABLE = `${CONF_LIVE}.draggable` as const;
|
||||
export const CONF_LIVE_LAZY_LOAD = `${CONF_LIVE}.lazy_load` as const;
|
||||
export const CONF_LIVE_LAZY_UNLOAD = `${CONF_LIVE}.lazy_unload` as const;
|
||||
@@ -247,9 +249,6 @@ export const CONF_LIVE_MICROPHONE_ALWAYS_CONNECTED =
|
||||
export const CONF_LIVE_ZOOMABLE = `${CONF_LIVE}.zoomable` as const;
|
||||
|
||||
const CONF_IMAGE = 'image' as const;
|
||||
export const CONF_IMAGE_LAYOUT_FIT = `${CONF_IMAGE}.layout.fit` as const;
|
||||
export const CONF_IMAGE_LAYOUT_POSITION_X = `${CONF_IMAGE}.layout.position.x` as const;
|
||||
export const CONF_IMAGE_LAYOUT_POSITION_Y = `${CONF_IMAGE}.layout.position.y` as const;
|
||||
export const CONF_IMAGE_MODE = `${CONF_IMAGE}.mode` as const;
|
||||
export const CONF_IMAGE_REFRESH_SECONDS = `${CONF_IMAGE}.refresh_seconds` as const;
|
||||
export const CONF_IMAGE_URL = `${CONF_IMAGE}.url` as const;
|
||||
|
||||
+39
-45
@@ -22,9 +22,9 @@ import {
|
||||
} from './config-mgmt.js';
|
||||
import {
|
||||
BUTTON_SIZE_MIN,
|
||||
FRIGATE_MENU_PRIORITY_MAX,
|
||||
FrigateCardConfig,
|
||||
frigateCardConfigDefaults,
|
||||
FRIGATE_MENU_PRIORITY_MAX,
|
||||
RawFrigateCardConfig,
|
||||
RawFrigateCardConfigArray,
|
||||
THUMBNAIL_WIDTH_MAX,
|
||||
@@ -38,6 +38,10 @@ import {
|
||||
CONF_CAMERAS_ARRAY_CAST_METHOD,
|
||||
CONF_CAMERAS_ARRAY_DEPENDENCIES_ALL_CAMERAS,
|
||||
CONF_CAMERAS_ARRAY_DEPENDENCIES_CAMERAS,
|
||||
CONF_CAMERAS_ARRAY_DIMENSIONS_ASPECT_RATIO,
|
||||
CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_FIT,
|
||||
CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_POSITION_X,
|
||||
CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_POSITION_Y,
|
||||
CONF_CAMERAS_ARRAY_FRIGATE_CAMERA_NAME,
|
||||
CONF_CAMERAS_ARRAY_FRIGATE_CLIENT_ID,
|
||||
CONF_CAMERAS_ARRAY_FRIGATE_LABELS,
|
||||
@@ -67,9 +71,6 @@ import {
|
||||
CONF_DIMENSIONS_ASPECT_RATIO_MODE,
|
||||
CONF_DIMENSIONS_MAX_HEIGHT,
|
||||
CONF_DIMENSIONS_MIN_HEIGHT,
|
||||
CONF_IMAGE_LAYOUT_FIT,
|
||||
CONF_IMAGE_LAYOUT_POSITION_X,
|
||||
CONF_IMAGE_LAYOUT_POSITION_Y,
|
||||
CONF_IMAGE_MODE,
|
||||
CONF_IMAGE_REFRESH_SECONDS,
|
||||
CONF_IMAGE_URL,
|
||||
@@ -108,9 +109,6 @@ import {
|
||||
CONF_LIVE_DISPLAY_GRID_SELECTED_WIDTH_FACTOR,
|
||||
CONF_LIVE_DISPLAY_MODE,
|
||||
CONF_LIVE_DRAGGABLE,
|
||||
CONF_LIVE_LAYOUT_FIT,
|
||||
CONF_LIVE_LAYOUT_POSITION_X,
|
||||
CONF_LIVE_LAYOUT_POSITION_Y,
|
||||
CONF_LIVE_LAZY_LOAD,
|
||||
CONF_LIVE_LAZY_UNLOAD,
|
||||
CONF_LIVE_MICROPHONE_ALWAYS_CONNECTED,
|
||||
@@ -152,16 +150,13 @@ import {
|
||||
CONF_MEDIA_VIEWER_DISPLAY_GRID_SELECTED_WIDTH_FACTOR,
|
||||
CONF_MEDIA_VIEWER_DISPLAY_MODE,
|
||||
CONF_MEDIA_VIEWER_DRAGGABLE,
|
||||
CONF_MEDIA_VIEWER_LAYOUT_FIT,
|
||||
CONF_MEDIA_VIEWER_LAYOUT_POSITION_X,
|
||||
CONF_MEDIA_VIEWER_LAYOUT_POSITION_Y,
|
||||
CONF_MEDIA_VIEWER_LAZY_LOAD,
|
||||
CONF_MEDIA_VIEWER_SNAPSHOT_CLICK_PLAYS_CLIP,
|
||||
CONF_MEDIA_VIEWER_TRANSITION_EFFECT,
|
||||
CONF_MEDIA_VIEWER_ZOOMABLE,
|
||||
CONF_MENU_ALIGNMENT,
|
||||
CONF_MENU_BUTTON_SIZE,
|
||||
CONF_MENU_BUTTONS,
|
||||
CONF_MENU_BUTTON_SIZE,
|
||||
CONF_MENU_POSITION,
|
||||
CONF_MENU_STYLE,
|
||||
CONF_PERFORMANCE_FEATURES_ANIMATED_PROGRESS_INDICATOR,
|
||||
@@ -213,6 +208,8 @@ const MENU_BUTTONS = 'buttons';
|
||||
const MENU_CAMERAS = 'cameras';
|
||||
const MENU_CAMERAS_CAST = 'cameras.cast';
|
||||
const MENU_CAMERAS_DEPENDENCIES = 'cameras.dependencies';
|
||||
const MENU_CAMERAS_DIMENSIONS = 'cameras.dimensions';
|
||||
const MENU_CAMERAS_DIMENSIONS_LAYOUT = 'cameras.dimensions.layout';
|
||||
const MENU_CAMERAS_ENGINE = 'cameras.engine';
|
||||
const MENU_CAMERAS_FRIGATE = 'cameras.frigate';
|
||||
const MENU_CAMERAS_GO2RTC = 'cameras.go2rtc';
|
||||
@@ -221,7 +218,6 @@ const MENU_CAMERAS_LIVE_PROVIDER = 'cameras.live_provider';
|
||||
const MENU_CAMERAS_MOTIONEYE = 'cameras.motioneye';
|
||||
const MENU_CAMERAS_TRIGGERS = 'cameras.triggers';
|
||||
const MENU_CAMERAS_WEBRTC_CARD = 'cameras.webrtc_card';
|
||||
const MENU_IMAGE_LAYOUT = 'image.layout';
|
||||
const MENU_LIVE_CONTROLS = 'live.controls';
|
||||
const MENU_LIVE_CONTROLS_NEXT_PREVIOUS = 'live.controls.next_previous';
|
||||
const MENU_LIVE_CONTROLS_PTZ = 'live.controls.ptz';
|
||||
@@ -229,7 +225,6 @@ const MENU_LIVE_CONTROLS_THUMBNAILS = 'live.controls.thumbnails';
|
||||
const MENU_LIVE_CONTROLS_TIMELINE = 'live.controls.timeline';
|
||||
const MENU_LIVE_CONTROLS_TITLE = 'live.controls.title';
|
||||
const MENU_LIVE_DISPLAY = 'live.display';
|
||||
const MENU_LIVE_LAYOUT = 'live.layout';
|
||||
const MENU_LIVE_MICROPHONE = 'live.microphone';
|
||||
const MENU_MEDIA_GALLERY_CONTROLS_FILTER = 'media_gallery.controls.filter';
|
||||
const MENU_MEDIA_GALLERY_CONTROLS_THUMBNAILS = 'media_gallery.controls.thumbnails';
|
||||
@@ -239,7 +234,6 @@ const MENU_MEDIA_VIEWER_CONTROLS_THUMBNAILS = 'media_viewer.controls.thumbnails'
|
||||
const MENU_MEDIA_VIEWER_CONTROLS_TIMELINE = 'media_viewer.controls.timeline';
|
||||
const MENU_MEDIA_VIEWER_CONTROLS_TITLE = 'media_viewer.controls.title';
|
||||
const MENU_MEDIA_VIEWER_DISPLAY = 'media_viewer.display';
|
||||
const MENU_MEDIA_VIEWER_LAYOUT = 'media_viewer.layout';
|
||||
const MENU_OPTIONS = 'options';
|
||||
const MENU_PERFORMANCE_FEATURES = 'performance.features';
|
||||
const MENU_PERFORMANCE_STYLE = 'performance.style';
|
||||
@@ -576,9 +570,12 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
||||
|
||||
protected _layoutFits: EditorSelectOption[] = [
|
||||
{ value: '', label: '' },
|
||||
{ value: 'contain', label: localize('config.common.layout.fits.contain') },
|
||||
{ value: 'cover', label: localize('config.common.layout.fits.cover') },
|
||||
{ value: 'fill', label: localize('config.common.layout.fits.fill') },
|
||||
{
|
||||
value: 'contain',
|
||||
label: localize('config.cameras.dimensions.layout.fits.contain'),
|
||||
},
|
||||
{ value: 'cover', label: localize('config.cameras.dimensions.layout.fits.cover') },
|
||||
{ value: 'fill', label: localize('config.cameras.dimensions.layout.fits.fill') },
|
||||
];
|
||||
|
||||
protected _miniTimelineModes: EditorSelectOption[] = [
|
||||
@@ -1167,17 +1164,17 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
||||
{ name: 'mdi:page-layout-body' },
|
||||
html`
|
||||
${this._renderOptionSelector(configPathFit, this._layoutFits, {
|
||||
label: localize('config.common.layout.fit'),
|
||||
label: localize('config.cameras.dimensions.layout.fit'),
|
||||
})}
|
||||
${this._renderNumberInput(configPathPositionX, {
|
||||
min: 0,
|
||||
max: 100,
|
||||
label: localize('config.common.layout.position.x'),
|
||||
label: localize('config.cameras.dimensions.layout.position.x'),
|
||||
})}
|
||||
${this._renderNumberInput(configPathPositionY, {
|
||||
min: 0,
|
||||
max: 100,
|
||||
label: localize('config.common.layout.position.y'),
|
||||
label: localize('config.cameras.dimensions.layout.position.y'),
|
||||
})}
|
||||
`,
|
||||
);
|
||||
@@ -1854,10 +1851,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
||||
},
|
||||
)}
|
||||
${this._renderOptionSelector(
|
||||
getArrayConfigPath(
|
||||
CONF_CAMERAS_ARRAY_TRIGGERS_EVENTS,
|
||||
cameraIndex,
|
||||
),
|
||||
getArrayConfigPath(CONF_CAMERAS_ARRAY_TRIGGERS_EVENTS, cameraIndex),
|
||||
this._triggersEvents,
|
||||
{
|
||||
multiple: true,
|
||||
@@ -1890,6 +1884,27 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
||||
)}
|
||||
`,
|
||||
)}
|
||||
${this._putInSubmenu(
|
||||
MENU_CAMERAS_DIMENSIONS,
|
||||
cameraIndex,
|
||||
'config.cameras.dimensions.editor_label',
|
||||
{ name: 'mdi:aspect-ratio' },
|
||||
html`
|
||||
${this._renderStringInput(
|
||||
getArrayConfigPath(
|
||||
CONF_CAMERAS_ARRAY_DIMENSIONS_ASPECT_RATIO,
|
||||
cameraIndex,
|
||||
),
|
||||
)}
|
||||
${this._renderMediaLayout(
|
||||
MENU_CAMERAS_DIMENSIONS_LAYOUT,
|
||||
'config.cameras.dimensions.layout.editor_label',
|
||||
CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_FIT,
|
||||
CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_POSITION_X,
|
||||
CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_POSITION_Y,
|
||||
)}
|
||||
`,
|
||||
)}
|
||||
</div>`
|
||||
: ``}
|
||||
</div>
|
||||
@@ -2237,13 +2252,6 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
||||
)}
|
||||
`,
|
||||
)}
|
||||
${this._renderMediaLayout(
|
||||
MENU_LIVE_LAYOUT,
|
||||
'config.live.layout',
|
||||
CONF_LIVE_LAYOUT_FIT,
|
||||
CONF_LIVE_LAYOUT_POSITION_X,
|
||||
CONF_LIVE_LAYOUT_POSITION_Y,
|
||||
)}
|
||||
${this._putInSubmenu(
|
||||
MENU_LIVE_MICROPHONE,
|
||||
true,
|
||||
@@ -2389,13 +2397,6 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
||||
)}
|
||||
`,
|
||||
)}
|
||||
${this._renderMediaLayout(
|
||||
MENU_MEDIA_VIEWER_LAYOUT,
|
||||
'config.media_viewer.layout',
|
||||
CONF_MEDIA_VIEWER_LAYOUT_FIT,
|
||||
CONF_MEDIA_VIEWER_LAYOUT_POSITION_X,
|
||||
CONF_MEDIA_VIEWER_LAYOUT_POSITION_Y,
|
||||
)}
|
||||
</div>`
|
||||
: ''}
|
||||
${this._renderOptionSetHeader('image')}
|
||||
@@ -2405,13 +2406,6 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
||||
${this._renderStringInput(CONF_IMAGE_URL)}
|
||||
${this._renderNumberInput(CONF_IMAGE_REFRESH_SECONDS)}
|
||||
${this._renderSwitch(CONF_IMAGE_ZOOMABLE, this._defaults.image.zoomable)}
|
||||
${this._renderMediaLayout(
|
||||
MENU_IMAGE_LAYOUT,
|
||||
'config.image.layout',
|
||||
CONF_IMAGE_LAYOUT_FIT,
|
||||
CONF_IMAGE_LAYOUT_POSITION_X,
|
||||
CONF_IMAGE_LAYOUT_POSITION_Y,
|
||||
)}
|
||||
</div>`
|
||||
: ''}
|
||||
${this._renderOptionSetHeader('timeline')}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"dashboard_path": "Dashboard path",
|
||||
"view_path": "View path"
|
||||
},
|
||||
"editor_label": "Cast Options",
|
||||
"editor_label": "Cast options",
|
||||
"method": "Cast method",
|
||||
"methods": {
|
||||
"dashboard": "Dashboard",
|
||||
@@ -25,7 +25,24 @@
|
||||
"dependencies": {
|
||||
"all_cameras": "Show events for all cameras with this camera",
|
||||
"cameras": "Show events for specific cameras with this camera",
|
||||
"editor_label": "Dependency Options"
|
||||
"editor_label": "Dependency options"
|
||||
},
|
||||
"dimensions": {
|
||||
"aspect_ratio": "Static aspect ratio",
|
||||
"editor_label": "Camera dimensions",
|
||||
"layout": {
|
||||
"editor_label": "Camera Layout",
|
||||
"fit": "Layout fit",
|
||||
"fits": {
|
||||
"contain": "Media is contained/letterboxed",
|
||||
"cover": "Media expands proportionally to cover the card",
|
||||
"fill": "Media is stretched to fill the card"
|
||||
},
|
||||
"position": {
|
||||
"x": "Horizontal placement percentage",
|
||||
"y": "Vertical placement percentage"
|
||||
}
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
"editor_label": "Camera engine options"
|
||||
@@ -83,7 +100,7 @@
|
||||
},
|
||||
"title": "Title for this camera (Autodetected from entity)",
|
||||
"triggers": {
|
||||
"editor_label": "Trigger Options",
|
||||
"editor_label": "Trigger options",
|
||||
"entities": "Trigger from other entities",
|
||||
"events": {
|
||||
"clips": "Events with new clips",
|
||||
@@ -178,18 +195,6 @@
|
||||
"grid_selected_width_factor": "Increase selected media width by this factor",
|
||||
"mode": "Mode"
|
||||
},
|
||||
"layout": {
|
||||
"fit": "Layout fit",
|
||||
"fits": {
|
||||
"contain": "Media is contained/letterboxed",
|
||||
"cover": "Media expands proportionally to cover the card",
|
||||
"fill": "Media is stretched to fill the card"
|
||||
},
|
||||
"position": {
|
||||
"x": "Horizontal placement percentage",
|
||||
"y": "Vertical placement percentage"
|
||||
}
|
||||
},
|
||||
"media_action_conditions": {
|
||||
"all": "All opportunities",
|
||||
"hidden": "On browser/tab hiding",
|
||||
@@ -229,7 +234,6 @@
|
||||
"min_height": "Minimum card height in CSS units (e.g. '100px')"
|
||||
},
|
||||
"image": {
|
||||
"layout": "Image Layout",
|
||||
"mode": "Image view mode",
|
||||
"modes": {
|
||||
"camera": "Home Assistant camera snapshot of camera entity",
|
||||
@@ -272,7 +276,6 @@
|
||||
}
|
||||
},
|
||||
"draggable": "Live cameras view can be dragged/swiped",
|
||||
"layout": "Live Layout",
|
||||
"lazy_load": "Live cameras are lazily loaded",
|
||||
"lazy_unload": "Live cameras are lazily unloaded",
|
||||
"microphone": {
|
||||
@@ -296,7 +299,6 @@
|
||||
"editor_label": "Media Viewer Controls"
|
||||
},
|
||||
"draggable": "Media Viewer can be dragged/swiped",
|
||||
"layout": "Media Viewer Layout",
|
||||
"lazy_load": "Media Viewer media is lazily loaded in carousel",
|
||||
"snapshot_click_plays_clip": "Clicking on a snapshot plays a related clip",
|
||||
"transition_effect": "Media Viewer transition effect",
|
||||
@@ -454,8 +456,8 @@
|
||||
"cameras": "Cameras",
|
||||
"cameras_secondary": "What cameras to render on this card",
|
||||
"delete": "Delete",
|
||||
"dimensions": "Dimensions",
|
||||
"dimensions_secondary": "Dimensions & shape options",
|
||||
"dimensions": "Card dimensions",
|
||||
"dimensions_secondary": "Card dimensions & shape options",
|
||||
"image": "Image",
|
||||
"image_secondary": "Static image view options",
|
||||
"live": "Live",
|
||||
|
||||
@@ -27,6 +27,22 @@
|
||||
"cameras": "Mostra eventi per telecamere specifiche con questa telecamera",
|
||||
"editor_label": "Opzioni di dipendenza"
|
||||
},
|
||||
"dimensions": {
|
||||
"editor_label": "",
|
||||
"aspect_ratio": "",
|
||||
"layout": {
|
||||
"fit": "Adatta al layout",
|
||||
"fits": {
|
||||
"contain": "Il supporto è contenuto/in cassetta delle lettere",
|
||||
"cover": "Il supporto si espande proporzionalmente per coprire la scheda",
|
||||
"fill": "Il supporto viene allungato per riempire la scheda"
|
||||
},
|
||||
"position": {
|
||||
"x": "Percentuale di posizionamento orizzontale",
|
||||
"y": "Percentuale di posizionamento verticale"
|
||||
}
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
"editor_label": "Opzioni del motore della fotocamera"
|
||||
},
|
||||
@@ -178,18 +194,6 @@
|
||||
"grid_selected_width_factor": "",
|
||||
"mode": ""
|
||||
},
|
||||
"layout": {
|
||||
"fit": "Adatta al layout",
|
||||
"fits": {
|
||||
"contain": "Il supporto è contenuto/in cassetta delle lettere",
|
||||
"cover": "Il supporto si espande proporzionalmente per coprire la scheda",
|
||||
"fill": "Il supporto viene allungato per riempire la scheda"
|
||||
},
|
||||
"position": {
|
||||
"x": "Percentuale di posizionamento orizzontale",
|
||||
"y": "Percentuale di posizionamento verticale"
|
||||
}
|
||||
},
|
||||
"media_action_conditions": {
|
||||
"all": "Tutte le opportunità",
|
||||
"hidden": "Sul browser/nascondere le schede",
|
||||
@@ -229,7 +233,6 @@
|
||||
"min_height": ""
|
||||
},
|
||||
"image": {
|
||||
"layout": "Disposizione dell'immagine",
|
||||
"mode": "Modalità Visualizza immagine",
|
||||
"modes": {
|
||||
"camera": "Istantanea della telecamera di Home Assistant dell'entità telecamera",
|
||||
@@ -272,7 +275,6 @@
|
||||
}
|
||||
},
|
||||
"draggable": "Il Visualizzatore eventi può essere trascinato oppure puoi scorrere",
|
||||
"layout": "Disposizione dal vivo",
|
||||
"lazy_load": "Le telecamere dal vivo sono pigramente cariche",
|
||||
"lazy_unload": "Le telecamere dal vivo sono pigramente non caricate",
|
||||
"microphone": {
|
||||
@@ -296,7 +298,6 @@
|
||||
"editor_label": "Controlli di visualizzatore multimediale"
|
||||
},
|
||||
"draggable": "Il visualizzatore multimediale può essere trascinato oppure può scorrere",
|
||||
"layout": "Layout del visualizzatore multimediale",
|
||||
"lazy_load": "Il media Viewer viene caricato pigramente nel carosello",
|
||||
"transition_effect": "Effetto di transizione del visualizzatore multimediale",
|
||||
"transition_effects": {
|
||||
@@ -448,8 +449,8 @@
|
||||
"cameras": "Telecamere",
|
||||
"cameras_secondary": "Quali telecamere visualizzare su questa card",
|
||||
"delete": "Elimina",
|
||||
"dimensions": "Dimensioni",
|
||||
"dimensions_secondary": "Dimensioni e opzioni di forma",
|
||||
"dimensions": "",
|
||||
"dimensions_secondary": "",
|
||||
"image": "Immagine",
|
||||
"image_secondary": "Opzioni di visualizzazione dell'immagine statica",
|
||||
"live": "Live",
|
||||
@@ -584,4 +585,4 @@
|
||||
},
|
||||
"select_date": "Scegli la data"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,22 @@
|
||||
"cameras": "Mostrar eventos para câmeras específicas nesta câmera",
|
||||
"editor_label": "Opções de dependência"
|
||||
},
|
||||
"dimensions": {
|
||||
"editor_label": "",
|
||||
"aspect_ratio": "",
|
||||
"layout": {
|
||||
"fit": "Ajuste de layout",
|
||||
"fits": {
|
||||
"contain": "A mídia é contida no cartão",
|
||||
"cover": "A mídia se expande proporcionalmente para cobrir o cartão",
|
||||
"fill": "A mídia é esticada para preencher o cartão"
|
||||
},
|
||||
"position": {
|
||||
"x": "Porcentagem do posicionamento horizontal",
|
||||
"y": "Porcentagem do posicionamento vertical"
|
||||
}
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
"editor_label": "Opções do motor da câmera"
|
||||
},
|
||||
@@ -178,18 +194,6 @@
|
||||
"grid_selected_width_factor": "",
|
||||
"mode": ""
|
||||
},
|
||||
"layout": {
|
||||
"fit": "Ajuste de layout",
|
||||
"fits": {
|
||||
"contain": "A mídia é contida no cartão",
|
||||
"cover": "A mídia se expande proporcionalmente para cobrir o cartão",
|
||||
"fill": "A mídia é esticada para preencher o cartão"
|
||||
},
|
||||
"position": {
|
||||
"x": "Porcentagem do posicionamento horizontal",
|
||||
"y": "Porcentagem do posicionamento vertical"
|
||||
}
|
||||
},
|
||||
"media_action_conditions": {
|
||||
"all": "Todas as oportunidades",
|
||||
"hidden": "Ao ocultar o navegador/aba",
|
||||
@@ -229,7 +233,6 @@
|
||||
"min_height": ""
|
||||
},
|
||||
"image": {
|
||||
"layout": "Layout da imagem",
|
||||
"mode": "Modo de visualização de imagem",
|
||||
"modes": {
|
||||
"camera": "Instantâneo da câmera do Home Assistant, da entidade de câmera",
|
||||
@@ -272,7 +275,6 @@
|
||||
}
|
||||
},
|
||||
"draggable": "A visualização ao vivo das câmeras pode ser arrastada/deslizada",
|
||||
"layout": "Layout dinâmico",
|
||||
"lazy_load": "As câmeras ao vivo são carregadas lentamente",
|
||||
"lazy_unload": "As câmeras ao vivo são descarregadas preguiçosamente",
|
||||
"microphone": {
|
||||
@@ -296,7 +298,6 @@
|
||||
"editor_label": "Controles do visualizador de mídia"
|
||||
},
|
||||
"draggable": "Visualizador de eventos pode ser arrastado/deslizado",
|
||||
"layout": "Layout do visualizador de mídia",
|
||||
"lazy_load": "A mídia do Visualizador de eventos é carregada lentamente no carrossel",
|
||||
"snapshot_click_plays_clip": "Clicar em um instantâneo reproduz um clipe relacionado",
|
||||
"transition_effect": "Efeito de transição do Visualizador de eventos",
|
||||
@@ -453,8 +454,8 @@
|
||||
"cameras": "Câmeras",
|
||||
"cameras_secondary": "Quais câmeras renderizar neste cartão",
|
||||
"delete": "Excluir",
|
||||
"dimensions": "Dimensões",
|
||||
"dimensions_secondary": "Dimensões e opções de forma",
|
||||
"dimensions": "",
|
||||
"dimensions_secondary": "",
|
||||
"image": "Imagem",
|
||||
"image_secondary": "Opções de visualização de imagem estática",
|
||||
"live": "Ao vivo",
|
||||
@@ -594,4 +595,4 @@
|
||||
},
|
||||
"select_date": "Escolha a data"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,22 @@
|
||||
"cameras": "Mostrar eventos para câmeras específicas nesta câmera",
|
||||
"editor_label": "Opções de dependência"
|
||||
},
|
||||
"dimensions": {
|
||||
"editor_label": "",
|
||||
"aspect_ratio": "",
|
||||
"layout": {
|
||||
"fit": "Fit",
|
||||
"fits": {
|
||||
"contain": "Conter",
|
||||
"cover": "Tapar",
|
||||
"fill": "Preencher"
|
||||
},
|
||||
"position": {
|
||||
"x": "Percentagem da localização horizontal",
|
||||
"y": "Percentagem da localização vertical"
|
||||
}
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
"editor_label": "Editor de etiquetas"
|
||||
},
|
||||
@@ -178,18 +194,6 @@
|
||||
"grid_selected_width_factor": "",
|
||||
"mode": ""
|
||||
},
|
||||
"layout": {
|
||||
"fit": "Fit",
|
||||
"fits": {
|
||||
"contain": "Conter",
|
||||
"cover": "Tapar",
|
||||
"fill": "Preencher"
|
||||
},
|
||||
"position": {
|
||||
"x": "Percentagem da localização horizontal",
|
||||
"y": "Percentagem da localização vertical"
|
||||
}
|
||||
},
|
||||
"media_action_conditions": {
|
||||
"all": "Todas as oportunidades",
|
||||
"hidden": "Ao ocultar o navegador/aba",
|
||||
@@ -222,7 +226,6 @@
|
||||
}
|
||||
},
|
||||
"image": {
|
||||
"layout": "Layout",
|
||||
"mode": "Modo de visualização de imagem",
|
||||
"modes": {
|
||||
"camera": "Instantâneo da câmera do Home Assistant, da entidade de câmera",
|
||||
@@ -265,7 +268,6 @@
|
||||
}
|
||||
},
|
||||
"draggable": "A visualização ao vivo das câmeras pode ser arrastada/deslizada",
|
||||
"layout": "layout",
|
||||
"lazy_load": "As câmeras ao vivo são carregadas lentamente",
|
||||
"lazy_unload": "As câmeras ao vivo são descarregadas preguiçosamente",
|
||||
"microphone": {
|
||||
@@ -289,7 +291,6 @@
|
||||
"editor_label": "Controles do visualizador de mídia"
|
||||
},
|
||||
"draggable": "Visualizador de eventos pode ser arrastado/deslizado",
|
||||
"layout": "Layout",
|
||||
"lazy_load": "A mídia do Visualizador de eventos é carregada lentamente no carrossel",
|
||||
"transition_effect": "Efeito de transição do Visualizador de eventos",
|
||||
"transition_effects": {
|
||||
@@ -441,8 +442,8 @@
|
||||
"cameras": "Câmeras",
|
||||
"cameras_secondary": "Câmeras para renderizar neste cartão",
|
||||
"delete": "Excluir",
|
||||
"dimensions": "Dimensões",
|
||||
"dimensions_secondary": "Dimensões e opções de forma",
|
||||
"dimensions": "",
|
||||
"dimensions_secondary": "",
|
||||
"image": "Imagem",
|
||||
"image_secondary": "Opções de visualização de imagem estática",
|
||||
"live": "Ao vivo",
|
||||
@@ -576,4 +577,4 @@
|
||||
},
|
||||
"select_date": "Selecionar a data"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
--video-max-height: none;
|
||||
}
|
||||
|
||||
// When the carousel is not part of a grid ensure its height matches its
|
||||
// container.
|
||||
:host(:not([grid-id])) {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
// If the carousel has an unselected attribute set on it, do not let the
|
||||
// pointer interact (e.g. hover, scroll) with underlying elements. This is used
|
||||
// when the carousel is part of a media-grid. Without this next/prev controls
|
||||
@@ -13,6 +19,11 @@
|
||||
}
|
||||
|
||||
.embla__slide {
|
||||
// Center the content horizontally (for cases where the configured aspect
|
||||
// ratio is a mismatch with the card).
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
height: 100%;
|
||||
flex: 0 0 100%;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
:host {
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 100;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
|
||||
@@ -2,6 +2,7 @@ import differenceInHours from 'date-fns/differenceInHours';
|
||||
import differenceInMinutes from 'date-fns/differenceInMinutes';
|
||||
import differenceInSeconds from 'date-fns/differenceInSeconds';
|
||||
import format from 'date-fns/format';
|
||||
import { StyleInfo } from 'lit/directives/style-map';
|
||||
import isEqual from 'lodash-es/isEqual';
|
||||
import mergeWith from 'lodash-es/mergeWith';
|
||||
import { FrigateCardError } from '../types';
|
||||
@@ -245,3 +246,25 @@ export const getChildrenFromElement = (parent: HTMLElement): HTMLElement[] => {
|
||||
export const recursivelyMergeObjectsNotArrays = <T>(src1: T, src2: T): T => {
|
||||
return mergeWith({}, src1, src2, (_a, b) => (Array.isArray(b) ? b : undefined));
|
||||
};
|
||||
|
||||
export const aspectRatioToString = (options?: {
|
||||
ratio?: number[];
|
||||
defaultStatic?: boolean;
|
||||
}): string => {
|
||||
if (options?.ratio && options.ratio.length === 2) {
|
||||
return `${options.ratio[0]} / ${options.ratio[1]}`;
|
||||
} else if (options?.defaultStatic) {
|
||||
return '16 / 9';
|
||||
} else {
|
||||
return 'auto';
|
||||
}
|
||||
};
|
||||
|
||||
export const aspectRatioToStyle = (options?: {
|
||||
ratio?: number[];
|
||||
defaultStatic?: boolean;
|
||||
}): StyleInfo => {
|
||||
return {
|
||||
'aspect-ratio': aspectRatioToString(options),
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user