Add view header (#24237)
* Create basic section heading * Update badge position * Don't allow to move card * Remove view badges in section * Improve heading section UX * Add basic editor for heading section * Add badges position option * Add layout and badge position * Improve button * Use layout * Simplify edit mode * Fix CSS * Fix add heading button * Improve badges * Rename to extra space * Fix add top badge position * Add migration * Fix delete section confirmation * Add translations * Update comment * Add header config to view * Add edit card overlay * Remove badge support for sections * Remove section badges * Clean section * Fix header visibility * Update translations * Add view header editor * Use new markdown card option * Revert useless changes * Add options translations * Use edit dialog * Unify font * Update default text * Share default between editor and view * Update src/panels/lovelace/editor/view-header/hui-dialog-edit-view-header.ts Co-authored-by: Bram Kragten <mail@bramkragten.nl> * Update src/panels/lovelace/editor/view-header/hui-dialog-edit-view-header.ts Co-authored-by: Bram Kragten <mail@bramkragten.nl> * Fix comment * Use select box for view header editor * Remove extra space option * Update select box --------- Co-authored-by: Bram Kragten <mail@bramkragten.nl>
@ -0,0 +1,11 @@
|
||||
<svg width="94" height="56" viewBox="0 0 94 56" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="94" height="56" rx="8" fill="white"/>
|
||||
<rect x="0.5" y="0.5" width="93" height="55" rx="7.5" stroke="black" stroke-opacity="0.12" stroke-dasharray="4 4"/>
|
||||
<path d="M8 14C8 10.6863 10.6863 8 14 8H33C36.3137 8 39 10.6863 39 14C39 17.3137 36.3137 20 33 20H14C10.6863 20 8 17.3137 8 14Z" fill="black" fill-opacity="0.12"/>
|
||||
<path d="M8 27C8 25.3431 9.34315 24 11 24H83C84.6569 24 86 25.3431 86 27V29C86 30.6569 84.6569 32 83 32H11C9.34315 32 8 30.6569 8 29V27Z" fill="black" fill-opacity="0.12"/>
|
||||
<path d="M8 44C8 46.2091 9.79086 48 12 48H16C18.2091 48 20 46.2091 20 44C20 41.7909 18.2091 40 16 40H12C9.79086 40 8 41.7909 8 44Z" fill="black" fill-opacity="0.32"/>
|
||||
<path d="M24.5 44C24.5 46.2091 26.2909 48 28.5 48H32.5C34.7091 48 36.5 46.2091 36.5 44C36.5 41.7909 34.7091 40 32.5 40H28.5C26.2909 40 24.5 41.7909 24.5 44Z" fill="black" fill-opacity="0.32"/>
|
||||
<path d="M41 44C41 46.2091 42.7909 48 45 48H49C51.2091 48 53 46.2091 53 44C53 41.7909 51.2091 40 49 40H45C42.7909 40 41 41.7909 41 44Z" fill="black" fill-opacity="0.32"/>
|
||||
<path d="M57.5 44C57.5 46.2091 59.2909 48 61.5 48H65.5C67.7091 48 69.5 46.2091 69.5 44C69.5 41.7909 67.7091 40 65.5 40H61.5C59.2909 40 57.5 41.7909 57.5 44Z" fill="black" fill-opacity="0.32"/>
|
||||
<path d="M74 44C74 46.2091 75.7909 48 78 48H82C84.2091 48 86 46.2091 86 44C86 41.7909 84.2091 40 82 40H78C75.7909 40 74 41.7909 74 44Z" fill="black" fill-opacity="0.32"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
@ -0,0 +1,11 @@
|
||||
<svg width="94" height="56" viewBox="0 0 94 56" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 8C0 3.58172 3.58172 0 8 0H86C90.4183 0 94 3.58172 94 8V48C94 52.4183 90.4183 56 86 56H8C3.58172 56 0 52.4183 0 48V8Z" fill="black"/>
|
||||
<path d="M1.34748 52.4449C0.772837 51.5866 0.359906 50.6109 0.152272 49.5613L0.642766 49.4643C0.549158 48.9911 0.5 48.5015 0.5 48V46H0V42H0.5V38H0V34H0.5V30H0V26H0.5V22H0V18H0.5V14H0V10H0.5V8C0.5 7.49847 0.549158 7.00892 0.642766 6.53574L0.152272 6.4387C0.359906 5.38915 0.772837 4.41341 1.34748 3.55508L1.76296 3.83324C2.31067 3.01513 3.01513 2.31067 3.83323 1.76296L3.55507 1.34748C4.41341 0.772837 5.38915 0.359906 6.4387 0.152272L6.53574 0.642766C7.00892 0.549158 7.49847 0.5 8 0.5H9.94999V0H13.85V0.5H17.75V0H21.65V0.5H25.55V0H29.45V0.5H33.35V0H37.25V0.5H41.15V0H45.05V0.5H48.95V0H52.85V0.5H56.75V0H60.65V0.5H64.55V0H68.45V0.5H72.35V0H76.25V0.5H80.15V0H84.05V0.5H86C86.5015 0.5 86.9911 0.549158 87.4643 0.642766L87.5613 0.152273C88.6108 0.359907 89.5866 0.772837 90.4449 1.34747L90.1668 1.76296C90.9849 2.31067 91.6893 3.01513 92.237 3.83323L92.6525 3.55507C93.2272 4.41341 93.6401 5.38915 93.8477 6.4387L93.3572 6.53574C93.4508 7.00892 93.5 7.49847 93.5 8V10H94V14H93.5V18H94V22H93.5V26H94V30H93.5V34H94V38H93.5V42H94V46H93.5V48C93.5 48.5015 93.4508 48.9911 93.3572 49.4643L93.8477 49.5613C93.6401 50.6109 93.2272 51.5866 92.6525 52.4449L92.237 52.1668C91.6893 52.9849 90.9849 53.6893 90.1668 54.237L90.4449 54.6525C89.5866 55.2272 88.6108 55.6401 87.5613 55.8477L87.4643 55.3572C86.9911 55.4508 86.5015 55.5 86 55.5H84.05V56H80.15V55.5H76.25V56H72.35V55.5H68.45V56H64.55V55.5H60.65V56H56.75V55.5H52.85V56H48.95V55.5H45.05V56H41.15V55.5H37.25V56H33.35V55.5H29.45V56H25.55V55.5H21.65V56H17.75V55.5H13.85V56H9.95V55.5H8C7.49847 55.5 7.00892 55.4508 6.53574 55.3572L6.4387 55.8477C5.38915 55.6401 4.41341 55.2272 3.55508 54.6525L3.83323 54.237C3.01513 53.6893 2.31067 52.9849 1.76296 52.1668L1.34748 52.4449Z" stroke="white" stroke-opacity="0.24" stroke-dasharray="4 4"/>
|
||||
<path d="M8 14C8 10.6863 10.6863 8 14 8H33C36.3137 8 39 10.6863 39 14C39 17.3137 36.3137 20 33 20H14C10.6863 20 8 17.3137 8 14Z" fill="white" fill-opacity="0.24"/>
|
||||
<path d="M8 27C8 25.3431 9.34315 24 11 24H83C84.6569 24 86 25.3431 86 27V29C86 30.6569 84.6569 32 83 32H11C9.34315 32 8 30.6569 8 29V27Z" fill="white" fill-opacity="0.24"/>
|
||||
<path d="M8 44C8 46.2091 9.79086 48 12 48H16C18.2091 48 20 46.2091 20 44C20 41.7909 18.2091 40 16 40H12C9.79086 40 8 41.7909 8 44Z" fill="white" fill-opacity="0.48"/>
|
||||
<path d="M24.5 44C24.5 46.2091 26.2909 48 28.5 48H32.5C34.7091 48 36.5 46.2091 36.5 44C36.5 41.7909 34.7091 40 32.5 40H28.5C26.2909 40 24.5 41.7909 24.5 44Z" fill="white" fill-opacity="0.48"/>
|
||||
<path d="M41 44C41 46.2091 42.7909 48 45 48H49C51.2091 48 53 46.2091 53 44C53 41.7909 51.2091 40 49 40H45C42.7909 40 41 41.7909 41 44Z" fill="white" fill-opacity="0.48"/>
|
||||
<path d="M57.5 44C57.5 46.2091 59.2909 48 61.5 48H65.5C67.7091 48 69.5 46.2091 69.5 44C69.5 41.7909 67.7091 40 65.5 40H61.5C59.2909 40 57.5 41.7909 57.5 44Z" fill="white" fill-opacity="0.48"/>
|
||||
<path d="M74 44C74 46.2091 75.7909 48 78 48H82C84.2091 48 86 46.2091 86 44C86 41.7909 84.2091 40 82 40H78C75.7909 40 74 41.7909 74 44Z" fill="white" fill-opacity="0.48"/>
|
||||
</svg>
|
After Width: | Height: | Size: 3.2 KiB |
@ -0,0 +1,11 @@
|
||||
<svg width="94" height="56" viewBox="0 0 94 56" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="94" height="56" rx="8" fill="white"/>
|
||||
<rect x="0.5" y="0.5" width="93" height="55" rx="7.5" stroke="black" stroke-opacity="0.12" stroke-dasharray="4 4"/>
|
||||
<path d="M8 12C8 14.2091 9.79086 16 12 16H16C18.2091 16 20 14.2091 20 12C20 9.79086 18.2091 8 16 8H12C9.79086 8 8 9.79086 8 12Z" fill="black" fill-opacity="0.32"/>
|
||||
<path d="M24.5 12C24.5 14.2091 26.2909 16 28.5 16H32.5C34.7091 16 36.5 14.2091 36.5 12C36.5 9.79086 34.7091 8 32.5 8H28.5C26.2909 8 24.5 9.79086 24.5 12Z" fill="black" fill-opacity="0.32"/>
|
||||
<path d="M41 12C41 14.2091 42.7909 16 45 16H49C51.2091 16 53 14.2091 53 12C53 9.79086 51.2091 8 49 8H45C42.7909 8 41 9.79086 41 12Z" fill="black" fill-opacity="0.32"/>
|
||||
<path d="M57.5 12C57.5 14.2091 59.2909 16 61.5 16H65.5C67.7091 16 69.5 14.2091 69.5 12C69.5 9.79086 67.7091 8 65.5 8H61.5C59.2909 8 57.5 9.79086 57.5 12Z" fill="black" fill-opacity="0.32"/>
|
||||
<path d="M74 12C74 14.2091 75.7909 16 78 16H82C84.2091 16 86 14.2091 86 12C86 9.79086 84.2091 8 82 8H78C75.7909 8 74 9.79086 74 12Z" fill="black" fill-opacity="0.32"/>
|
||||
<path d="M8 30C8 26.6863 10.6863 24 14 24H33C36.3137 24 39 26.6863 39 30C39 33.3137 36.3137 36 33 36H14C10.6863 36 8 33.3137 8 30Z" fill="black" fill-opacity="0.12"/>
|
||||
<path d="M8 43C8 41.3431 9.34315 40 11 40H83C84.6569 40 86 41.3431 86 43V45C86 46.6569 84.6569 48 83 48H11C9.34315 48 8 46.6569 8 45V43Z" fill="black" fill-opacity="0.12"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
@ -0,0 +1,11 @@
|
||||
<svg width="94" height="56" viewBox="0 0 94 56" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 8C0 3.58172 3.58172 0 8 0H86C90.4183 0 94 3.58172 94 8V48C94 52.4183 90.4183 56 86 56H8C3.58172 56 0 52.4183 0 48V8Z" fill="black"/>
|
||||
<path d="M1.34748 52.4449C0.772837 51.5866 0.359906 50.6109 0.152272 49.5613L0.642766 49.4643C0.549158 48.9911 0.5 48.5015 0.5 48V46H0V42H0.5V38H0V34H0.5V30H0V26H0.5V22H0V18H0.5V14H0V10H0.5V8C0.5 7.49847 0.549158 7.00892 0.642766 6.53574L0.152272 6.4387C0.359906 5.38915 0.772837 4.41341 1.34748 3.55508L1.76296 3.83324C2.31067 3.01513 3.01513 2.31067 3.83323 1.76296L3.55507 1.34748C4.41341 0.772837 5.38915 0.359906 6.4387 0.152272L6.53574 0.642766C7.00892 0.549158 7.49847 0.5 8 0.5H9.94999V0H13.85V0.5H17.75V0H21.65V0.5H25.55V0H29.45V0.5H33.35V0H37.25V0.5H41.15V0H45.05V0.5H48.95V0H52.85V0.5H56.75V0H60.65V0.5H64.55V0H68.45V0.5H72.35V0H76.25V0.5H80.15V0H84.05V0.5H86C86.5015 0.5 86.9911 0.549158 87.4643 0.642766L87.5613 0.152273C88.6108 0.359907 89.5866 0.772837 90.4449 1.34747L90.1668 1.76296C90.9849 2.31067 91.6893 3.01513 92.237 3.83323L92.6525 3.55507C93.2272 4.41341 93.6401 5.38915 93.8477 6.4387L93.3572 6.53574C93.4508 7.00892 93.5 7.49847 93.5 8V10H94V14H93.5V18H94V22H93.5V26H94V30H93.5V34H94V38H93.5V42H94V46H93.5V48C93.5 48.5015 93.4508 48.9911 93.3572 49.4643L93.8477 49.5613C93.6401 50.6109 93.2272 51.5866 92.6525 52.4449L92.237 52.1668C91.6893 52.9849 90.9849 53.6893 90.1668 54.237L90.4449 54.6525C89.5866 55.2272 88.6108 55.6401 87.5613 55.8477L87.4643 55.3572C86.9911 55.4508 86.5015 55.5 86 55.5H84.05V56H80.15V55.5H76.25V56H72.35V55.5H68.45V56H64.55V55.5H60.65V56H56.75V55.5H52.85V56H48.95V55.5H45.05V56H41.15V55.5H37.25V56H33.35V55.5H29.45V56H25.55V55.5H21.65V56H17.75V55.5H13.85V56H9.95V55.5H8C7.49847 55.5 7.00892 55.4508 6.53574 55.3572L6.4387 55.8477C5.38915 55.6401 4.41341 55.2272 3.55508 54.6525L3.83323 54.237C3.01513 53.6893 2.31067 52.9849 1.76296 52.1668L1.34748 52.4449Z" stroke="white" stroke-opacity="0.24" stroke-dasharray="4 4"/>
|
||||
<path d="M8 12C8 14.2091 9.79086 16 12 16H16C18.2091 16 20 14.2091 20 12C20 9.79086 18.2091 8 16 8H12C9.79086 8 8 9.79086 8 12Z" fill="white" fill-opacity="0.48"/>
|
||||
<path d="M24.5 12C24.5 14.2091 26.2909 16 28.5 16H32.5C34.7091 16 36.5 14.2091 36.5 12C36.5 9.79086 34.7091 8 32.5 8H28.5C26.2909 8 24.5 9.79086 24.5 12Z" fill="white" fill-opacity="0.48"/>
|
||||
<path d="M41 12C41 14.2091 42.7909 16 45 16H49C51.2091 16 53 14.2091 53 12C53 9.79086 51.2091 8 49 8H45C42.7909 8 41 9.79086 41 12Z" fill="white" fill-opacity="0.48"/>
|
||||
<path d="M57.5 12C57.5 14.2091 59.2909 16 61.5 16H65.5C67.7091 16 69.5 14.2091 69.5 12C69.5 9.79086 67.7091 8 65.5 8H61.5C59.2909 8 57.5 9.79086 57.5 12Z" fill="white" fill-opacity="0.48"/>
|
||||
<path d="M74 12C74 14.2091 75.7909 16 78 16H82C84.2091 16 86 14.2091 86 12C86 9.79086 84.2091 8 82 8H78C75.7909 8 74 9.79086 74 12Z" fill="white" fill-opacity="0.48"/>
|
||||
<path d="M8 30C8 26.6863 10.6863 24 14 24H33C36.3137 24 39 26.6863 39 30C39 33.3137 36.3137 36 33 36H14C10.6863 36 8 33.3137 8 30Z" fill="white" fill-opacity="0.24"/>
|
||||
<path d="M8 43C8 41.3431 9.34315 40 11 40H83C84.6569 40 86 41.3431 86 43V45C86 46.6569 84.6569 48 83 48H11C9.34315 48 8 46.6569 8 45V43Z" fill="white" fill-opacity="0.24"/>
|
||||
</svg>
|
After Width: | Height: | Size: 3.2 KiB |
11
public/static/images/form/view_header_layout_center.svg
Normal file
@ -0,0 +1,11 @@
|
||||
<svg width="94" height="56" viewBox="0 0 94 56" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="94" height="56" rx="8" fill="white"/>
|
||||
<rect x="0.5" y="0.5" width="93" height="55" rx="7.5" stroke="black" stroke-opacity="0.12" stroke-dasharray="4 4"/>
|
||||
<path d="M31.5 14C31.5 10.6863 34.1863 8 37.5 8H56.5C59.8137 8 62.5 10.6863 62.5 14C62.5 17.3137 59.8137 20 56.5 20H37.5C34.1863 20 31.5 17.3137 31.5 14Z" fill="black" fill-opacity="0.32"/>
|
||||
<path d="M23 27C23 25.3431 24.3431 24 26 24H68C69.6569 24 71 25.3431 71 27V29C71 30.6569 69.6569 32 68 32H26C24.3431 32 23 30.6569 23 29V27Z" fill="black" fill-opacity="0.12"/>
|
||||
<path d="M9 44C9 41.7909 10.7909 40 13 40H17C19.2091 40 21 41.7909 21 44C21 46.2091 19.2091 48 17 48H13C10.7909 48 9 46.2091 9 44Z" fill="black" fill-opacity="0.32"/>
|
||||
<path d="M25 44C25 41.7909 26.7909 40 29 40H33C35.2091 40 37 41.7909 37 44C37 46.2091 35.2091 48 33 48H29C26.7909 48 25 46.2091 25 44Z" fill="black" fill-opacity="0.12"/>
|
||||
<path d="M41 44C41 41.7909 42.7909 40 45 40H49C51.2091 40 53 41.7909 53 44C53 46.2091 51.2091 48 49 48H45C42.7909 48 41 46.2091 41 44Z" fill="black" fill-opacity="0.12"/>
|
||||
<path d="M57 44C57 41.7909 58.7909 40 61 40H65C67.2091 40 69 41.7909 69 44C69 46.2091 67.2091 48 65 48H61C58.7909 48 57 46.2091 57 44Z" fill="black" fill-opacity="0.12"/>
|
||||
<path d="M73 44C73 41.7909 74.7909 40 77 40H81C83.2091 40 85 41.7909 85 44C85 46.2091 83.2091 48 81 48H77C74.7909 48 73 46.2091 73 44Z" fill="black" fill-opacity="0.12"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
11
public/static/images/form/view_header_layout_center_dark.svg
Normal file
@ -0,0 +1,11 @@
|
||||
<svg width="94" height="56" viewBox="0 0 94 56" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 8C0 3.58172 3.58172 0 8 0H86C90.4183 0 94 3.58172 94 8V48C94 52.4183 90.4183 56 86 56H8C3.58172 56 0 52.4183 0 48V8Z" fill="black"/>
|
||||
<path d="M1.34748 52.4449C0.772837 51.5866 0.359906 50.6109 0.152272 49.5613L0.642766 49.4643C0.549158 48.9911 0.5 48.5015 0.5 48V46H0V42H0.5V38H0V34H0.5V30H0V26H0.5V22H0V18H0.5V14H0V10H0.5V8C0.5 7.49847 0.549158 7.00892 0.642766 6.53574L0.152272 6.4387C0.359906 5.38915 0.772837 4.41341 1.34748 3.55508L1.76296 3.83324C2.31067 3.01513 3.01513 2.31067 3.83323 1.76296L3.55507 1.34748C4.41341 0.772837 5.38915 0.359906 6.4387 0.152272L6.53574 0.642766C7.00892 0.549158 7.49847 0.5 8 0.5H9.94999V0H13.85V0.5H17.75V0H21.65V0.5H25.55V0H29.45V0.5H33.35V0H37.25V0.5H41.15V0H45.05V0.5H48.95V0H52.85V0.5H56.75V0H60.65V0.5H64.55V0H68.45V0.5H72.35V0H76.25V0.5H80.15V0H84.05V0.5H86C86.5015 0.5 86.9911 0.549158 87.4643 0.642766L87.5613 0.152273C88.6108 0.359907 89.5866 0.772837 90.4449 1.34747L90.1668 1.76296C90.9849 2.31067 91.6893 3.01513 92.237 3.83323L92.6525 3.55507C93.2272 4.41341 93.6401 5.38915 93.8477 6.4387L93.3572 6.53574C93.4508 7.00892 93.5 7.49847 93.5 8V10H94V14H93.5V18H94V22H93.5V26H94V30H93.5V34H94V38H93.5V42H94V46H93.5V48C93.5 48.5015 93.4508 48.9911 93.3572 49.4643L93.8477 49.5613C93.6401 50.6109 93.2272 51.5866 92.6525 52.4449L92.237 52.1668C91.6893 52.9849 90.9849 53.6893 90.1668 54.237L90.4449 54.6525C89.5866 55.2272 88.6108 55.6401 87.5613 55.8477L87.4643 55.3572C86.9911 55.4508 86.5015 55.5 86 55.5H84.05V56H80.15V55.5H76.25V56H72.35V55.5H68.45V56H64.55V55.5H60.65V56H56.75V55.5H52.85V56H48.95V55.5H45.05V56H41.15V55.5H37.25V56H33.35V55.5H29.45V56H25.55V55.5H21.65V56H17.75V55.5H13.85V56H9.95V55.5H8C7.49847 55.5 7.00892 55.4508 6.53574 55.3572L6.4387 55.8477C5.38915 55.6401 4.41341 55.2272 3.55508 54.6525L3.83323 54.237C3.01513 53.6893 2.31067 52.9849 1.76296 52.1668L1.34748 52.4449Z" stroke="white" stroke-opacity="0.24" stroke-dasharray="4 4"/>
|
||||
<path d="M31.5 14C31.5 10.6863 34.1863 8 37.5 8H56.5C59.8137 8 62.5 10.6863 62.5 14C62.5 17.3137 59.8137 20 56.5 20H37.5C34.1863 20 31.5 17.3137 31.5 14Z" fill="white" fill-opacity="0.48"/>
|
||||
<path d="M23 27C23 25.3431 24.3431 24 26 24H68C69.6569 24 71 25.3431 71 27V29C71 30.6569 69.6569 32 68 32H26C24.3431 32 23 30.6569 23 29V27Z" fill="white" fill-opacity="0.24"/>
|
||||
<path d="M9 44C9 41.7909 10.7909 40 13 40H17C19.2091 40 21 41.7909 21 44C21 46.2091 19.2091 48 17 48H13C10.7909 48 9 46.2091 9 44Z" fill="white" fill-opacity="0.48"/>
|
||||
<rect x="25" y="40" width="12" height="8" rx="4" fill="white" fill-opacity="0.24"/>
|
||||
<rect x="41" y="40" width="12" height="8" rx="4" fill="white" fill-opacity="0.24"/>
|
||||
<rect x="57" y="40" width="12" height="8" rx="4" fill="white" fill-opacity="0.24"/>
|
||||
<rect x="73" y="40" width="12" height="8" rx="4" fill="white" fill-opacity="0.24"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
24
public/static/images/form/view_header_layout_responsive.svg
Normal file
@ -0,0 +1,24 @@
|
||||
<svg width="94" height="72" viewBox="0 0 94 72" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_887_2968)">
|
||||
<path d="M0 39H55V64C55 68.4183 51.4183 72 47 72H8C3.58172 72 0 68.4183 0 64V39Z" fill="white"/>
|
||||
<path d="M1.34748 68.4449C0.772837 67.5866 0.359906 66.6109 0.152272 65.5613L0.642766 65.4643C0.549158 64.9911 0.5 64.5015 0.5 64V61.9167H0V57.75H0.5V53.5833H0V49.4167H0.5V45.25H0V41.0833H0.5V39.5H1.96429V39H5.89286V39.5H9.82143V39H13.75V39.5H17.6786V39H21.6071V39.5H25.5357V39H29.4643V39.5H33.3929V39H37.3214V39.5H41.25V39H45.1786V39.5H49.1071V39H53.0357V39.5H54.5V41.0833H55V45.25H54.5V49.4167H55V53.5833H54.5V57.75H55V61.9167H54.5V64C54.5 64.5015 54.4508 64.9911 54.3572 65.4643L54.8477 65.5613C54.6401 66.6109 54.2272 67.5866 53.6525 68.4449L53.237 68.1668C52.6893 68.9849 51.9849 69.6893 51.1668 70.237L51.4449 70.6525C50.5866 71.2272 49.6109 71.6401 48.5613 71.8477L48.4643 71.3572C47.9911 71.4508 47.5015 71.5 47 71.5H45.05V72H41.15V71.5H37.25V72H33.35V71.5H29.45V72H25.55V71.5H21.65V72H17.75V71.5H13.85V72H9.95V71.5H8C7.49847 71.5 7.00892 71.4508 6.53574 71.3572L6.4387 71.8477C5.38915 71.6401 4.41341 71.2272 3.55507 70.6525L3.83323 70.237C3.01513 69.6893 2.31067 68.9849 1.76296 68.1668L1.34748 68.4449Z" stroke="black" stroke-opacity="0.12" stroke-dasharray="4 4"/>
|
||||
<rect x="8" y="47" width="12" height="8" rx="4" fill="black" fill-opacity="0.32"/>
|
||||
<rect x="24" y="47" width="12" height="8" rx="4" fill="black" fill-opacity="0.12"/>
|
||||
<rect x="8" y="59" width="12" height="8" rx="4" fill="black" fill-opacity="0.12"/>
|
||||
<path d="M54 0H86C90.4183 0 94 3.58172 94 8V32C94 36.4183 90.4183 40 86 40H54V0Z" fill="white"/>
|
||||
<path d="M84 39.5V40H80V39.5H76V40H72V39.5H68V40H64V39.5H60V40H56V39.5H54.5V38H54V34H54.5V30H54V26H54.5V22H54V18H54.5V14H54V10H54.5V6H54V2H54.5V0.5H56V0H60V0.5H64V0H68V0.5H72V0H76V0.5H80V0H84V0.5H86C86.5015 0.5 86.9911 0.549158 87.4643 0.642766L87.5613 0.152272C88.6109 0.359906 89.5866 0.772836 90.4449 1.34748L90.1668 1.76296C90.9849 2.31067 91.6893 3.01513 92.237 3.83323L92.6525 3.55507C93.2272 4.41341 93.6401 5.38915 93.8477 6.4387L93.3572 6.53574C93.4508 7.00892 93.5 7.49847 93.5 8V10H94V14H93.5V18H94V22H93.5V26H94V30H93.5V32C93.5 32.5015 93.4508 32.9911 93.3572 33.4643L93.8477 33.5613C93.6401 34.6109 93.2272 35.5866 92.6525 36.4449L92.237 36.1668C91.6893 36.9849 90.9849 37.6893 90.1668 38.237L90.4449 38.6525C89.5866 39.2272 88.6109 39.6401 87.5613 39.8477L87.4643 39.3572C86.9911 39.4508 86.5015 39.5 86 39.5H84Z" stroke="black" stroke-opacity="0.12" stroke-dasharray="4 4"/>
|
||||
<path d="M58 28C58 30.2091 59.7909 32 62 32H66C68.2091 32 70 30.2091 70 28C70 25.7909 68.2091 24 66 24H62C59.7909 24 58 25.7909 58 28Z" fill="black" fill-opacity="0.12"/>
|
||||
<path d="M74 28C74 30.2091 75.7909 32 78 32H82C84.2091 32 86 30.2091 86 28C86 25.7909 84.2091 24 82 24H78C75.7909 24 74 25.7909 74 28Z" fill="black" fill-opacity="0.32"/>
|
||||
<path d="M74 16C74 18.2091 75.7909 20 78 20H82C84.2091 20 86 18.2091 86 16C86 13.7909 84.2091 12 82 12H78C75.7909 12 74 13.7909 74 16Z" fill="black" fill-opacity="0.12"/>
|
||||
<path d="M0 8C0 3.58172 3.58172 0 8 0H55V40H0V8Z" fill="white"/>
|
||||
<path d="M3.55507 1.34748C4.41341 0.772837 5.38915 0.359906 6.4387 0.152272L6.53574 0.642766C7.00892 0.549158 7.49847 0.5 8 0.5H9.95833V0H13.875V0.5H17.7917V0H21.7083V0.5H25.625V0H29.5417V0.5H33.4583V0H37.375V0.5H41.2917V0H45.2083V0.5H49.125V0H53.0417V0.5H54.5V2H55V6H54.5V10H55V14H54.5V18H55V22H54.5V26H55V30H54.5V34H55V38H54.5V39.5H53.0357V40H49.1071V39.5H45.1786V40H41.25V39.5H37.3214V40H33.3929V39.5H29.4643V40H25.5357V39.5H21.6071V40H17.6786V39.5H13.75V40H9.82143V39.5H5.89286V40H1.96429V39.5H0.5V38H0V34H0.5V30H0V26H0.5V22H0V18H0.5V14H0V10H0.5V8C0.5 7.49847 0.549158 7.00892 0.642766 6.53574L0.152272 6.4387C0.359906 5.38915 0.772837 4.41341 1.34748 3.55508L1.76296 3.83324C2.31067 3.01513 3.01513 2.31067 3.83323 1.76296L3.55507 1.34748Z" stroke="black" stroke-opacity="0.12" stroke-dasharray="4 4"/>
|
||||
<path d="M8 14C8 10.6863 10.6863 8 14 8H33C36.3137 8 39 10.6863 39 14C39 17.3137 36.3137 20 33 20H14C10.6863 20 8 17.3137 8 14Z" fill="black" fill-opacity="0.32"/>
|
||||
<path d="M8 27C8 25.3431 9.34315 24 11 24H44C45.6569 24 47 25.3431 47 27V29C47 30.6569 45.6569 32 44 32H11C9.34315 32 8 30.6569 8 29V27Z" fill="black" fill-opacity="0.12"/>
|
||||
<path d="M79 48V54.5C79 58.09 76.09 61 72.5 61H66.83L69.92 64.09L68.5 65.5L63 60L68.5 54.5L69.91 55.91L66.83 59H72.5C75 59 77 57 77 54.5V48H79Z" fill="black" fill-opacity="0.32"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_887_2968">
|
||||
<rect width="94" height="72" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 4.5 KiB |
@ -0,0 +1,17 @@
|
||||
<svg width="94" height="72" viewBox="0 0 94 72" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 39H55V64C55 68.4183 51.4183 72 47 72H8C3.58172 72 0 68.4183 0 64V39Z" fill="black"/>
|
||||
<path d="M1.34748 68.4449C0.772837 67.5866 0.359906 66.6109 0.152272 65.5613L0.642766 65.4643C0.549158 64.9911 0.5 64.5015 0.5 64V61.9167H0V57.75H0.5V53.5833H0V49.4167H0.5V45.25H0V41.0833H0.5V39.5H1.96429V39H5.89286V39.5H9.82143V39H13.75V39.5H17.6786V39H21.6071V39.5H25.5357V39H29.4643V39.5H33.3929V39H37.3214V39.5H41.25V39H45.1786V39.5H49.1071V39H53.0357V39.5H54.5V41.0833H55V45.25H54.5V49.4167H55V53.5833H54.5V57.75H55V61.9167H54.5V64C54.5 64.5015 54.4508 64.9911 54.3572 65.4643L54.8477 65.5613C54.6401 66.6109 54.2272 67.5866 53.6525 68.4449L53.237 68.1668C52.6893 68.9849 51.9849 69.6893 51.1668 70.237L51.4449 70.6525C50.5866 71.2272 49.6109 71.6401 48.5613 71.8477L48.4643 71.3572C47.9911 71.4508 47.5015 71.5 47 71.5H45.05V72H41.15V71.5H37.25V72H33.35V71.5H29.45V72H25.55V71.5H21.65V72H17.75V71.5H13.85V72H9.95V71.5H8C7.49847 71.5 7.00892 71.4508 6.53574 71.3572L6.4387 71.8477C5.38915 71.6401 4.41341 71.2272 3.55507 70.6525L3.83323 70.237C3.01513 69.6893 2.31067 68.9849 1.76296 68.1668L1.34748 68.4449Z" stroke="white" stroke-opacity="0.24" stroke-dasharray="4 4"/>
|
||||
<path d="M8 51C8 48.7909 9.79086 47 12 47H16C18.2091 47 20 48.7909 20 51C20 53.2091 18.2091 55 16 55H12C9.79086 55 8 53.2091 8 51Z" fill="white" fill-opacity="0.48"/>
|
||||
<path d="M24 51C24 48.7909 25.7909 47 28 47H32C34.2091 47 36 48.7909 36 51C36 53.2091 34.2091 55 32 55H28C25.7909 55 24 53.2091 24 51Z" fill="white" fill-opacity="0.24"/>
|
||||
<path d="M8 63C8 60.7909 9.79086 59 12 59H16C18.2091 59 20 60.7909 20 63C20 65.2091 18.2091 67 16 67H12C9.79086 67 8 65.2091 8 63Z" fill="white" fill-opacity="0.24"/>
|
||||
<path d="M54 0H86C90.4183 0 94 3.58172 94 8V32C94 36.4183 90.4183 40 86 40H54V0Z" fill="black"/>
|
||||
<path d="M84 39.5V40H80V39.5H76V40H72V39.5H68V40H64V39.5H60V40H56V39.5H54.5V38H54V34H54.5V30H54V26H54.5V22H54V18H54.5V14H54V10H54.5V6H54V2H54.5V0.5H56V0H60V0.5H64V0H68V0.5H72V0H76V0.5H80V0H84V0.5H86C86.5015 0.5 86.9911 0.549158 87.4643 0.642766L87.5613 0.152272C88.6109 0.359906 89.5866 0.772836 90.4449 1.34748L90.1668 1.76296C90.9849 2.31067 91.6893 3.01513 92.237 3.83323L92.6525 3.55507C93.2272 4.41341 93.6401 5.38915 93.8477 6.4387L93.3572 6.53574C93.4508 7.00892 93.5 7.49847 93.5 8V10H94V14H93.5V18H94V22H93.5V26H94V30H93.5V32C93.5 32.5015 93.4508 32.9911 93.3572 33.4643L93.8477 33.5613C93.6401 34.6109 93.2272 35.5866 92.6525 36.4449L92.237 36.1668C91.6893 36.9849 90.9849 37.6893 90.1668 38.237L90.4449 38.6525C89.5866 39.2272 88.6109 39.6401 87.5613 39.8477L87.4643 39.3572C86.9911 39.4508 86.5015 39.5 86 39.5H84Z" stroke="white" stroke-opacity="0.24" stroke-dasharray="4 4"/>
|
||||
<path d="M58 28C58 30.2091 59.7909 32 62 32H66C68.2091 32 70 30.2091 70 28C70 25.7909 68.2091 24 66 24H62C59.7909 24 58 25.7909 58 28Z" fill="white" fill-opacity="0.24"/>
|
||||
<path d="M74 28C74 30.2091 75.7909 32 78 32H82C84.2091 32 86 30.2091 86 28C86 25.7909 84.2091 24 82 24H78C75.7909 24 74 25.7909 74 28Z" fill="white" fill-opacity="0.48"/>
|
||||
<path d="M74 16C74 18.2091 75.7909 20 78 20H82C84.2091 20 86 18.2091 86 16C86 13.7909 84.2091 12 82 12H78C75.7909 12 74 13.7909 74 16Z" fill="white" fill-opacity="0.24"/>
|
||||
<path d="M0 8C0 3.58172 3.58172 0 8 0H55V40H0V8Z" fill="black"/>
|
||||
<path d="M3.55507 1.34748C4.41341 0.772837 5.38915 0.359906 6.4387 0.152272L6.53574 0.642766C7.00892 0.549158 7.49847 0.5 8 0.5H9.95833V0H13.875V0.5H17.7917V0H21.7083V0.5H25.625V0H29.5417V0.5H33.4583V0H37.375V0.5H41.2917V0H45.2083V0.5H49.125V0H53.0417V0.5H54.5V2H55V6H54.5V10H55V14H54.5V18H55V22H54.5V26H55V30H54.5V34H55V38H54.5V39.5H53.0357V40H49.1071V39.5H45.1786V40H41.25V39.5H37.3214V40H33.3929V39.5H29.4643V40H25.5357V39.5H21.6071V40H17.6786V39.5H13.75V40H9.82143V39.5H5.89286V40H1.96429V39.5H0.5V38H0V34H0.5V30H0V26H0.5V22H0V18H0.5V14H0V10H0.5V8C0.5 7.49847 0.549158 7.00892 0.642766 6.53574L0.152272 6.4387C0.359906 5.38915 0.772837 4.41341 1.34748 3.55508L1.76296 3.83324C2.31067 3.01513 3.01513 2.31067 3.83323 1.76296L3.55507 1.34748Z" stroke="white" stroke-opacity="0.24" stroke-dasharray="4 4"/>
|
||||
<path d="M8 14C8 10.6863 10.6863 8 14 8H33C36.3137 8 39 10.6863 39 14C39 17.3137 36.3137 20 33 20H14C10.6863 20 8 17.3137 8 14Z" fill="white" fill-opacity="0.48"/>
|
||||
<path d="M8 27C8 25.3431 9.34315 24 11 24H44C45.6569 24 47 25.3431 47 27V29C47 30.6569 45.6569 32 44 32H11C9.34315 32 8 30.6569 8 29V27Z" fill="white" fill-opacity="0.24"/>
|
||||
<path d="M79 48V54.5C79 58.09 76.09 61 72.5 61H66.83L69.92 64.09L68.5 65.5L63 60L68.5 54.5L69.91 55.91L66.83 59H72.5C75 59 77 57 77 54.5V48H79Z" fill="white" fill-opacity="0.48"/>
|
||||
</svg>
|
After Width: | Height: | Size: 4.6 KiB |
9
public/static/images/form/view_header_layout_start.svg
Normal file
@ -0,0 +1,9 @@
|
||||
<svg width="94" height="56" viewBox="0 0 94 56" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="94" height="56" rx="8" fill="white"/>
|
||||
<rect x="0.5" y="0.5" width="93" height="55" rx="7.5" stroke="black" stroke-opacity="0.12" stroke-dasharray="4 4"/>
|
||||
<path d="M8 14C8 10.6863 10.6863 8 14 8H33C36.3137 8 39 10.6863 39 14C39 17.3137 36.3137 20 33 20H14C10.6863 20 8 17.3137 8 14Z" fill="black" fill-opacity="0.32"/>
|
||||
<path d="M8 27C8 25.3431 9.34315 24 11 24H53C54.6569 24 56 25.3431 56 27V29C56 30.6569 54.6569 32 53 32H11C9.34315 32 8 30.6569 8 29V27Z" fill="black" fill-opacity="0.12"/>
|
||||
<path d="M8 44C8 41.7909 9.79086 40 12 40H16C18.2091 40 20 41.7909 20 44C20 46.2091 18.2091 48 16 48H12C9.79086 48 8 46.2091 8 44Z" fill="black" fill-opacity="0.32"/>
|
||||
<path d="M24 44C24 41.7909 25.7909 40 28 40H32C34.2091 40 36 41.7909 36 44C36 46.2091 34.2091 48 32 48H28C25.7909 48 24 46.2091 24 44Z" fill="black" fill-opacity="0.12"/>
|
||||
<path d="M40 44C40 41.7909 41.7909 40 44 40H48C50.2091 40 52 41.7909 52 44C52 46.2091 50.2091 48 48 48H44C41.7909 48 40 46.2091 40 44Z" fill="black" fill-opacity="0.12"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
11
public/static/images/form/view_header_layout_start_dark.svg
Normal file
@ -0,0 +1,11 @@
|
||||
<svg width="94" height="56" viewBox="0 0 94 56" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 8C0 3.58172 3.58172 0 8 0H86C90.4183 0 94 3.58172 94 8V48C94 52.4183 90.4183 56 86 56H8C3.58172 56 0 52.4183 0 48V8Z" fill="black"/>
|
||||
<path d="M1.34748 52.4449C0.772837 51.5866 0.359906 50.6109 0.152272 49.5613L0.642766 49.4643C0.549158 48.9911 0.5 48.5015 0.5 48V46H0V42H0.5V38H0V34H0.5V30H0V26H0.5V22H0V18H0.5V14H0V10H0.5V8C0.5 7.49847 0.549158 7.00892 0.642766 6.53574L0.152272 6.4387C0.359906 5.38915 0.772837 4.41341 1.34748 3.55508L1.76296 3.83324C2.31067 3.01513 3.01513 2.31067 3.83323 1.76296L3.55507 1.34748C4.41341 0.772837 5.38915 0.359906 6.4387 0.152272L6.53574 0.642766C7.00892 0.549158 7.49847 0.5 8 0.5H9.94999V0H13.85V0.5H17.75V0H21.65V0.5H25.55V0H29.45V0.5H33.35V0H37.25V0.5H41.15V0H45.05V0.5H48.95V0H52.85V0.5H56.75V0H60.65V0.5H64.55V0H68.45V0.5H72.35V0H76.25V0.5H80.15V0H84.05V0.5H86C86.5015 0.5 86.9911 0.549158 87.4643 0.642766L87.5613 0.152273C88.6108 0.359907 89.5866 0.772837 90.4449 1.34747L90.1668 1.76296C90.9849 2.31067 91.6893 3.01513 92.237 3.83323L92.6525 3.55507C93.2272 4.41341 93.6401 5.38915 93.8477 6.4387L93.3572 6.53574C93.4508 7.00892 93.5 7.49847 93.5 8V10H94V14H93.5V18H94V22H93.5V26H94V30H93.5V34H94V38H93.5V42H94V46H93.5V48C93.5 48.5015 93.4508 48.9911 93.3572 49.4643L93.8477 49.5613C93.6401 50.6109 93.2272 51.5866 92.6525 52.4449L92.237 52.1668C91.6893 52.9849 90.9849 53.6893 90.1668 54.237L90.4449 54.6525C89.5866 55.2272 88.6108 55.6401 87.5613 55.8477L87.4643 55.3572C86.9911 55.4508 86.5015 55.5 86 55.5H84.05V56H80.15V55.5H76.25V56H72.35V55.5H68.45V56H64.55V55.5H60.65V56H56.75V55.5H52.85V56H48.95V55.5H45.05V56H41.15V55.5H37.25V56H33.35V55.5H29.45V56H25.55V55.5H21.65V56H17.75V55.5H13.85V56H9.95V55.5H8C7.49847 55.5 7.00892 55.4508 6.53574 55.3572L6.4387 55.8477C5.38915 55.6401 4.41341 55.2272 3.55508 54.6525L3.83323 54.237C3.01513 53.6893 2.31067 52.9849 1.76296 52.1668L1.34748 52.4449Z" stroke="white" stroke-opacity="0.24" stroke-dasharray="4 4"/>
|
||||
<path d="M8 14C8 10.6863 10.6863 8 14 8H33C36.3137 8 39 10.6863 39 14C39 17.3137 36.3137 20 33 20H14C10.6863 20 8 17.3137 8 14Z" fill="white" fill-opacity="0.48"/>
|
||||
<path d="M8 27C8 25.3431 9.34315 24 11 24H53C54.6569 24 56 25.3431 56 27V29C56 30.6569 54.6569 32 53 32H11C9.34315 32 8 30.6569 8 29V27Z" fill="white" fill-opacity="0.24"/>
|
||||
<path d="M8 44C8 41.7909 9.79086 40 12 40H16C18.2091 40 20 41.7909 20 44C20 46.2091 18.2091 48 16 48H12C9.79086 48 8 46.2091 8 44Z" fill="white" fill-opacity="0.48"/>
|
||||
<rect x="24" y="40" width="12" height="8" rx="4" fill="white" fill-opacity="0.24"/>
|
||||
<rect x="40" y="40" width="12" height="8" rx="4" fill="white" fill-opacity="0.24"/>
|
||||
<rect x="56" y="40" width="12" height="8" rx="4" fill="white" fill-opacity="0.24"/>
|
||||
<rect x="72" y="40" width="12" height="8" rx="4" fill="white" fill-opacity="0.24"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
@ -25,6 +25,12 @@ export interface LovelaceViewBackgroundConfig {
|
||||
attachment?: "scroll" | "fixed";
|
||||
}
|
||||
|
||||
export interface LovelaceViewHeaderConfig {
|
||||
card?: LovelaceCardConfig;
|
||||
layout?: "start" | "center" | "responsive";
|
||||
badges_position?: "bottom" | "top";
|
||||
}
|
||||
|
||||
export interface LovelaceBaseViewConfig {
|
||||
index?: number;
|
||||
title?: string;
|
||||
@ -46,6 +52,7 @@ export interface LovelaceViewConfig extends LovelaceBaseViewConfig {
|
||||
badges?: (string | Partial<LovelaceBadgeConfig>)[]; // Badge can be just an entity_id or without type
|
||||
cards?: LovelaceCardConfig[];
|
||||
sections?: LovelaceSectionRawConfig[];
|
||||
header?: LovelaceViewHeaderConfig;
|
||||
}
|
||||
|
||||
export interface LovelaceStrategyViewConfig extends LovelaceBaseViewConfig {
|
||||
|
@ -12,6 +12,7 @@ import "../../../components/ha-svg-icon";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import "../components/hui-badge-edit-mode";
|
||||
import { moveBadge } from "../editor/config-util";
|
||||
import type { LovelaceCardPath } from "../editor/lovelace-path";
|
||||
import type { Lovelace } from "../types";
|
||||
import type { HuiBadge } from "./hui-badge";
|
||||
|
||||
@ -89,6 +90,20 @@ export class HuiViewBadges extends LitElement {
|
||||
this.lovelace!.saveConfig(newConfig);
|
||||
}
|
||||
|
||||
private _badgeAdded(ev) {
|
||||
ev.stopPropagation();
|
||||
const { index, data } = ev.detail;
|
||||
const oldPath = data as LovelaceCardPath;
|
||||
const newPath = [this.viewIndex!, index] as LovelaceCardPath;
|
||||
const newConfig = moveBadge(this.lovelace!.config, oldPath, newPath);
|
||||
this.lovelace!.saveConfig(newConfig);
|
||||
}
|
||||
|
||||
private _badgeRemoved(ev) {
|
||||
ev.stopPropagation();
|
||||
// Do nothing, it's handled by the "item-added" event from the new parent.
|
||||
}
|
||||
|
||||
private _dragStart() {
|
||||
this._dragging = true;
|
||||
}
|
||||
@ -114,6 +129,8 @@ export class HuiViewBadges extends LitElement {
|
||||
<ha-sortable
|
||||
.disabled=${!editMode}
|
||||
@item-moved=${this._badgeMoved}
|
||||
@item-added=${this._badgeAdded}
|
||||
@item-removed=${this._badgeRemoved}
|
||||
@drag-start=${this._dragStart}
|
||||
@drag-end=${this._dragEnd}
|
||||
group="badge"
|
||||
@ -126,21 +143,25 @@ export class HuiViewBadges extends LitElement {
|
||||
${repeat(
|
||||
badges,
|
||||
(badge) => this._getBadgeKey(badge),
|
||||
(badge, idx) => html`
|
||||
(badge, idx) => {
|
||||
const badgePath = [this.viewIndex, idx] as LovelaceCardPath;
|
||||
return html`
|
||||
${editMode
|
||||
? html`
|
||||
<hui-badge-edit-mode
|
||||
data-sortable
|
||||
.hass=${this.hass}
|
||||
.lovelace=${this.lovelace}
|
||||
.path=${[this.viewIndex, idx]}
|
||||
.path=${badgePath}
|
||||
.hiddenOverlay=${this._dragging}
|
||||
.sortableData=${badgePath}
|
||||
>
|
||||
${badge}
|
||||
</hui-badge-edit-mode>
|
||||
`
|
||||
: badge}
|
||||
`
|
||||
`;
|
||||
}
|
||||
)}
|
||||
${editMode
|
||||
? html`
|
||||
@ -179,8 +200,8 @@ export class HuiViewBadges extends LitElement {
|
||||
.badges {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
flex-wrap: var(--badges-wrap, wrap);
|
||||
justify-content: var(--badges-aligmnent, center);
|
||||
gap: 8px;
|
||||
margin: 0;
|
||||
}
|
||||
@ -197,6 +218,7 @@ export class HuiViewBadges extends LitElement {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
outline: none;
|
||||
gap: 8px;
|
||||
height: 36px;
|
||||
padding: 6px 20px 6px 20px;
|
||||
|
@ -50,6 +50,9 @@ export class HuiCardEditMode extends LitElement {
|
||||
@property({ type: Boolean, attribute: "no-duplicate" })
|
||||
public noDuplicate = false;
|
||||
|
||||
@property({ type: Boolean, attribute: "no-move" })
|
||||
public noMove = false;
|
||||
|
||||
@state()
|
||||
public _menuOpened = false;
|
||||
|
||||
@ -179,23 +182,39 @@ export class HuiCardEditMode extends LitElement {
|
||||
)}
|
||||
</ha-list-item>
|
||||
`}
|
||||
${this.noMove
|
||||
? nothing
|
||||
: html`
|
||||
<ha-list-item
|
||||
graphic="icon"
|
||||
@click=${this._handleAction}
|
||||
.action=${"copy"}
|
||||
>
|
||||
<ha-svg-icon slot="graphic" .path=${mdiContentCopy}></ha-svg-icon>
|
||||
${this.hass.localize("ui.panel.lovelace.editor.edit_card.copy")}
|
||||
<ha-svg-icon
|
||||
slot="graphic"
|
||||
.path=${mdiContentCopy}
|
||||
></ha-svg-icon>
|
||||
${this.hass.localize(
|
||||
"ui.panel.lovelace.editor.edit_card.copy"
|
||||
)}
|
||||
</ha-list-item>
|
||||
<ha-list-item
|
||||
graphic="icon"
|
||||
@click=${this._handleAction}
|
||||
.action=${"cut"}
|
||||
>
|
||||
<ha-svg-icon slot="graphic" .path=${mdiContentCut}></ha-svg-icon>
|
||||
${this.hass.localize("ui.panel.lovelace.editor.edit_card.cut")}
|
||||
<ha-svg-icon
|
||||
slot="graphic"
|
||||
.path=${mdiContentCut}
|
||||
></ha-svg-icon>
|
||||
${this.hass.localize(
|
||||
"ui.panel.lovelace.editor.edit_card.cut"
|
||||
)}
|
||||
</ha-list-item>
|
||||
<li divider role="separator"></li>
|
||||
`}
|
||||
${this.noDuplicate && this.noEdit && this.noMove
|
||||
? nothing
|
||||
: html`<li divider role="separator"></li>`}
|
||||
<ha-list-item
|
||||
graphic="icon"
|
||||
class="warning"
|
||||
|
@ -0,0 +1,245 @@
|
||||
import type { ActionDetail } from "@material/mwc-list";
|
||||
import { mdiClose, mdiDotsVertical, mdiPlaylistEdit } from "@mdi/js";
|
||||
import type { CSSResultGroup, PropertyValues } from "lit";
|
||||
import { LitElement, css, html, nothing } from "lit";
|
||||
import { customElement, property, query, state } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import { stopPropagation } from "../../../../common/dom/stop_propagation";
|
||||
import { deepEqual } from "../../../../common/util/deep-equal";
|
||||
import "../../../../components/ha-button";
|
||||
import "../../../../components/ha-circular-progress";
|
||||
import "../../../../components/ha-dialog";
|
||||
import "../../../../components/ha-dialog-header";
|
||||
import "../../../../components/ha-yaml-editor";
|
||||
import type { HaYamlEditor } from "../../../../components/ha-yaml-editor";
|
||||
import type { LovelaceViewHeaderConfig } from "../../../../data/lovelace/config/view";
|
||||
import { showAlertDialog } from "../../../../dialogs/generic/show-dialog-box";
|
||||
import { haStyleDialog } from "../../../../resources/styles";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import "./hui-view-header-settings-editor";
|
||||
import type { EditViewHeaderDialogParams } from "./show-edit-view-header-dialog";
|
||||
|
||||
@customElement("hui-dialog-edit-view-header")
|
||||
export class HuiDialogEditViewHeader extends LitElement {
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
|
||||
@state() private _params?: EditViewHeaderDialogParams;
|
||||
|
||||
@state() private _config?: LovelaceViewHeaderConfig;
|
||||
|
||||
@state() private _saving = false;
|
||||
|
||||
@state() private _dirty = false;
|
||||
|
||||
@state() private _yamlMode = false;
|
||||
|
||||
@query("ha-yaml-editor") private _editor?: HaYamlEditor;
|
||||
|
||||
protected updated(changedProperties: PropertyValues) {
|
||||
if (this._yamlMode && changedProperties.has("_yamlMode")) {
|
||||
const config = {
|
||||
...this._config,
|
||||
};
|
||||
this._editor?.setValue(config);
|
||||
}
|
||||
}
|
||||
|
||||
public showDialog(params: EditViewHeaderDialogParams): void {
|
||||
this._params = params;
|
||||
|
||||
this._dirty = false;
|
||||
this._config = this._params.config;
|
||||
}
|
||||
|
||||
public closeDialog(): void {
|
||||
this._params = undefined;
|
||||
this._config = undefined;
|
||||
this._yamlMode = false;
|
||||
this._dirty = false;
|
||||
this._saving = false;
|
||||
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||
}
|
||||
|
||||
protected render() {
|
||||
if (!this._params || !this.hass) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
let content;
|
||||
|
||||
if (this._yamlMode) {
|
||||
content = html`
|
||||
<ha-yaml-editor
|
||||
.hass=${this.hass}
|
||||
dialogInitialFocus
|
||||
@value-changed=${this._viewYamlChanged}
|
||||
></ha-yaml-editor>
|
||||
`;
|
||||
} else {
|
||||
content = html`
|
||||
<hui-view-header-settings-editor
|
||||
.hass=${this.hass}
|
||||
.config=${this._config}
|
||||
@config-changed=${this._configChanged}
|
||||
></hui-view-header-settings-editor>
|
||||
`;
|
||||
}
|
||||
|
||||
const title = this.hass.localize(
|
||||
"ui.panel.lovelace.editor.edit_view_header.header"
|
||||
);
|
||||
|
||||
return html`
|
||||
<ha-dialog
|
||||
open
|
||||
scrimClickAction
|
||||
escapeKeyAction
|
||||
@closed=${this.closeDialog}
|
||||
.heading=${title}
|
||||
class=${classMap({
|
||||
"yaml-mode": this._yamlMode,
|
||||
})}
|
||||
>
|
||||
<ha-dialog-header show-border slot="heading">
|
||||
<ha-icon-button
|
||||
slot="navigationIcon"
|
||||
dialogAction="cancel"
|
||||
.label=${this.hass!.localize("ui.common.close")}
|
||||
.path=${mdiClose}
|
||||
></ha-icon-button>
|
||||
<h2 slot="title">${title}</h2>
|
||||
<ha-button-menu
|
||||
slot="actionItems"
|
||||
fixed
|
||||
corner="BOTTOM_END"
|
||||
menu-corner="END"
|
||||
@action=${this._handleAction}
|
||||
@closed=${stopPropagation}
|
||||
>
|
||||
<ha-icon-button
|
||||
slot="trigger"
|
||||
.label=${this.hass!.localize("ui.common.menu")}
|
||||
.path=${mdiDotsVertical}
|
||||
></ha-icon-button>
|
||||
<ha-list-item graphic="icon">
|
||||
${this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.edit_view_header.edit_${!this._yamlMode ? "yaml" : "ui"}`
|
||||
)}
|
||||
<ha-svg-icon
|
||||
slot="graphic"
|
||||
.path=${mdiPlaylistEdit}
|
||||
></ha-svg-icon>
|
||||
</ha-list-item>
|
||||
</ha-button-menu>
|
||||
</ha-dialog-header>
|
||||
${content}
|
||||
<ha-button
|
||||
slot="primaryAction"
|
||||
.disabled=${!this._config || this._saving || !this._dirty}
|
||||
@click=${this._save}
|
||||
>
|
||||
${this._saving
|
||||
? html`<ha-circular-progress
|
||||
indeterminate
|
||||
size="small"
|
||||
aria-label="Saving"
|
||||
></ha-circular-progress>`
|
||||
: nothing}
|
||||
${this.hass!.localize("ui.common.save")}</ha-button
|
||||
>
|
||||
</ha-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
private async _handleAction(ev: CustomEvent<ActionDetail>) {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
switch (ev.detail.index) {
|
||||
case 0:
|
||||
this._yamlMode = !this._yamlMode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private _configChanged(ev: CustomEvent): void {
|
||||
if (
|
||||
ev.detail &&
|
||||
ev.detail.config &&
|
||||
!deepEqual(this._config, ev.detail.config)
|
||||
) {
|
||||
this._config = ev.detail.config;
|
||||
this._dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
private _viewYamlChanged(ev: CustomEvent) {
|
||||
ev.stopPropagation();
|
||||
if (!ev.detail.isValid) {
|
||||
return;
|
||||
}
|
||||
this._config = ev.detail.value;
|
||||
this._dirty = true;
|
||||
}
|
||||
|
||||
private async _save(): Promise<void> {
|
||||
if (!this._params || !this._config) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._saving = true;
|
||||
|
||||
try {
|
||||
await this._params.saveConfig(this._config);
|
||||
this.closeDialog();
|
||||
} catch (err: any) {
|
||||
showAlertDialog(this, {
|
||||
text: `${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.edit_view_header.saving_failed"
|
||||
)}: ${err.message}`,
|
||||
});
|
||||
} finally {
|
||||
this._saving = false;
|
||||
}
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [
|
||||
haStyleDialog,
|
||||
css`
|
||||
ha-dialog {
|
||||
/* Set the top top of the dialog to a fixed position, so it doesnt jump when the content changes size */
|
||||
--vertical-align-dialog: flex-start;
|
||||
--dialog-surface-margin-top: 40px;
|
||||
}
|
||||
|
||||
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||
/* When in fullscreen dialog should be attached to top */
|
||||
ha-dialog {
|
||||
--dialog-surface-margin-top: 0px;
|
||||
}
|
||||
}
|
||||
ha-dialog.yaml-mode {
|
||||
--dialog-content-padding: 0;
|
||||
}
|
||||
h2 {
|
||||
margin: 0;
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
@media all and (min-width: 600px) {
|
||||
ha-dialog {
|
||||
--mdc-dialog-min-width: 600px;
|
||||
}
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"hui-dialog-edit-view-header": HuiDialogEditViewHeader;
|
||||
}
|
||||
}
|
@ -0,0 +1,155 @@
|
||||
import { html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import type { LocalizeFunc } from "../../../../common/translations/localize";
|
||||
import { computeRTL } from "../../../../common/util/compute_rtl";
|
||||
import "../../../../components/ha-form/ha-form";
|
||||
import type {
|
||||
HaFormSchema,
|
||||
SchemaUnion,
|
||||
} from "../../../../components/ha-form/types";
|
||||
import type {
|
||||
LovelaceViewConfig,
|
||||
LovelaceViewHeaderConfig,
|
||||
} from "../../../../data/lovelace/config/view";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import {
|
||||
DEFAULT_VIEW_HEADER_BADGES_POSITION,
|
||||
DEFAULT_VIEW_HEADER_LAYOUT,
|
||||
} from "../../views/hui-view-header";
|
||||
import { listenMediaQuery } from "../../../../common/dom/media_query";
|
||||
|
||||
@customElement("hui-view-header-settings-editor")
|
||||
export class HuiViewHeaderSettingsEditor extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public config?: LovelaceViewHeaderConfig;
|
||||
|
||||
@state({ attribute: false }) private narrow = false;
|
||||
|
||||
private _unsubMql?: () => void;
|
||||
|
||||
connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
this._unsubMql = listenMediaQuery("(max-width: 600px)", (matches) => {
|
||||
this.narrow = matches;
|
||||
});
|
||||
}
|
||||
|
||||
public disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
this._unsubMql?.();
|
||||
this._unsubMql = undefined;
|
||||
}
|
||||
|
||||
private _schema = memoizeOne(
|
||||
(localize: LocalizeFunc, isRTL: boolean, narrow: boolean) =>
|
||||
[
|
||||
{
|
||||
name: "layout",
|
||||
selector: {
|
||||
select: {
|
||||
mode: "box",
|
||||
box_max_columns: narrow ? 1 : 3,
|
||||
options: ["responsive", "start", "center"].map((value) => {
|
||||
const labelKey =
|
||||
value === "start" && isRTL ? `${value}_rtl` : value;
|
||||
return {
|
||||
value,
|
||||
label: localize(
|
||||
`ui.panel.lovelace.editor.edit_view_header.settings.layout_options.${labelKey}`
|
||||
),
|
||||
description: localize(
|
||||
`ui.panel.lovelace.editor.edit_view_header.settings.layout_options.${value}_description`
|
||||
),
|
||||
image: {
|
||||
src: `/static/images/form/view_header_layout_${value}.svg`,
|
||||
src_dark: `/static/images/form/view_header_layout_${value}_dark.svg`,
|
||||
flip_rtl: true,
|
||||
},
|
||||
};
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "badges_position",
|
||||
selector: {
|
||||
select: {
|
||||
mode: "box",
|
||||
options: ["bottom", "top"].map((value) => ({
|
||||
value,
|
||||
label: localize(
|
||||
`ui.panel.lovelace.editor.edit_view_header.settings.badges_position_options.${value}`
|
||||
),
|
||||
image: {
|
||||
src: `/static/images/form/view_header_badges_position_${value}.svg`,
|
||||
src_dark: `/static/images/form/view_header_badges_position_${value}_dark.svg`,
|
||||
flip_rtl: true,
|
||||
},
|
||||
})),
|
||||
},
|
||||
},
|
||||
},
|
||||
] as const satisfies HaFormSchema[]
|
||||
);
|
||||
|
||||
protected render() {
|
||||
if (!this.hass) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
const data = {
|
||||
layout: this.config?.layout || DEFAULT_VIEW_HEADER_LAYOUT,
|
||||
badges_position:
|
||||
this.config?.badges_position || DEFAULT_VIEW_HEADER_BADGES_POSITION,
|
||||
};
|
||||
|
||||
const narrow = this.narrow;
|
||||
const isRTL = computeRTL(this.hass);
|
||||
const schema = this._schema(this.hass.localize, isRTL, narrow);
|
||||
|
||||
return html`
|
||||
<ha-form
|
||||
.hass=${this.hass}
|
||||
.data=${data}
|
||||
.schema=${schema}
|
||||
.computeLabel=${this._computeLabel}
|
||||
@value-changed=${this._valueChanged}
|
||||
></ha-form>
|
||||
`;
|
||||
}
|
||||
|
||||
private _valueChanged(ev: CustomEvent): void {
|
||||
ev.stopPropagation();
|
||||
const newData = ev.detail.value as LovelaceViewConfig;
|
||||
|
||||
const config: LovelaceViewHeaderConfig = {
|
||||
...this.config,
|
||||
...newData,
|
||||
};
|
||||
|
||||
fireEvent(this, "config-changed", { config });
|
||||
}
|
||||
|
||||
private _computeLabel = (
|
||||
schema: SchemaUnion<ReturnType<typeof this._schema>>
|
||||
) => {
|
||||
switch (schema.name) {
|
||||
case "layout":
|
||||
case "badges_position":
|
||||
return this.hass.localize(
|
||||
`ui.panel.lovelace.editor.edit_view_header.settings.${schema.name}`
|
||||
);
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"hui-view-header-settings-editor": HuiViewHeaderSettingsEditor;
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import type { LovelaceViewHeaderConfig } from "../../../../data/lovelace/config/view";
|
||||
|
||||
export interface EditViewHeaderDialogParams {
|
||||
saveConfig: (config: LovelaceViewHeaderConfig) => void;
|
||||
config: LovelaceViewHeaderConfig;
|
||||
}
|
||||
|
||||
export const showEditViewHeaderDialog = (
|
||||
element: HTMLElement,
|
||||
dialogParams: EditViewHeaderDialogParams
|
||||
): void => {
|
||||
fireEvent(element, "show-dialog", {
|
||||
dialogTag: "hui-dialog-edit-view-header",
|
||||
dialogImport: () => import("./hui-dialog-edit-view-header"),
|
||||
dialogParams: dialogParams,
|
||||
});
|
||||
};
|
@ -193,7 +193,7 @@ export class GridSection extends LitElement implements LovelaceSectionElement {
|
||||
|
||||
private _cardRemoved(ev) {
|
||||
ev.stopPropagation();
|
||||
// Do nothing, it's handle by the "card-added" event from the new parent.
|
||||
// Do nothing, it's handled by the "item-added" event from the new parent.
|
||||
}
|
||||
|
||||
private _dragStart() {
|
||||
|
@ -25,7 +25,7 @@ import type { LovelaceViewConfig } from "../../../data/lovelace/config/view";
|
||||
import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import type { HuiBadge } from "../badges/hui-badge";
|
||||
import "../badges/hui-view-badges";
|
||||
import "./hui-view-header";
|
||||
import type { HuiCard } from "../cards/hui-card";
|
||||
import "../components/hui-badge-edit-mode";
|
||||
import {
|
||||
@ -61,10 +61,10 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
||||
|
||||
@property({ attribute: false }) public sections: HuiSection[] = [];
|
||||
|
||||
@property({ attribute: false }) public badges: HuiBadge[] = [];
|
||||
|
||||
@property({ attribute: false }) public cards: HuiCard[] = [];
|
||||
|
||||
@property({ attribute: false }) public badges: HuiBadge[] = [];
|
||||
|
||||
@state() private _config?: LovelaceViewConfig;
|
||||
|
||||
@state() private _sectionColumnCount = 0;
|
||||
@ -154,15 +154,16 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
||||
const maxColumnCount = this._columnsController.value ?? 1;
|
||||
|
||||
return html`
|
||||
<hui-view-badges
|
||||
<hui-view-header
|
||||
.hass=${this.hass}
|
||||
.badges=${this.badges}
|
||||
.lovelace=${this.lovelace}
|
||||
.viewIndex=${this.index}
|
||||
.config=${this._config?.header}
|
||||
style=${styleMap({
|
||||
"--max-column-count": maxColumnCount,
|
||||
})}
|
||||
></hui-view-badges>
|
||||
></hui-view-header>
|
||||
<ha-sortable
|
||||
.disabled=${!editMode}
|
||||
@item-moved=${this._sectionMoved}
|
||||
@ -184,13 +185,11 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
||||
sections,
|
||||
(section) => this._getSectionKey(section),
|
||||
(section, idx) => {
|
||||
const sectionConfig = this._config?.sections?.[idx];
|
||||
const columnSpan = Math.min(
|
||||
sectionConfig?.column_span || 1,
|
||||
section.config.column_span || 1,
|
||||
maxColumnCount
|
||||
);
|
||||
|
||||
const rowSpan = sectionConfig?.row_span || 1;
|
||||
const rowSpan = section.config.row_span || 1;
|
||||
|
||||
return html`
|
||||
<div
|
||||
@ -551,7 +550,7 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
||||
border-radius: var(--ha-card-border-radius, 12px);
|
||||
}
|
||||
|
||||
hui-view-badges {
|
||||
hui-view-header {
|
||||
display: block;
|
||||
text-align: center;
|
||||
padding: 0 var(--column-gap);
|
||||
|
440
src/panels/lovelace/views/hui-view-header.ts
Normal file
@ -0,0 +1,440 @@
|
||||
import { mdiPencil, mdiPlus } from "@mdi/js";
|
||||
import type { PropertyValues } from "lit";
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import "../../../components/ha-ripple";
|
||||
import "../../../components/ha-sortable";
|
||||
import "../../../components/ha-svg-icon";
|
||||
import type { LovelaceCardConfig } from "../../../data/lovelace/config/card";
|
||||
import type {
|
||||
LovelaceViewConfig,
|
||||
LovelaceViewHeaderConfig,
|
||||
} from "../../../data/lovelace/config/view";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import type { HuiBadge } from "../badges/hui-badge";
|
||||
import "../badges/hui-view-badges";
|
||||
import type { HuiCard } from "../cards/hui-card";
|
||||
import "../components/hui-badge-edit-mode";
|
||||
import { replaceView } from "../editor/config-util";
|
||||
import { showEditViewHeaderDialog } from "../editor/view-header/show-edit-view-header-dialog";
|
||||
import type { Lovelace } from "../types";
|
||||
import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog";
|
||||
|
||||
export const DEFAULT_VIEW_HEADER_LAYOUT = "center";
|
||||
export const DEFAULT_VIEW_HEADER_BADGES_POSITION = "bottom";
|
||||
|
||||
@customElement("hui-view-header")
|
||||
export class HuiViewHeader extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public lovelace!: Lovelace;
|
||||
|
||||
@property({ attribute: false }) public card?: HuiCard;
|
||||
|
||||
@property({ attribute: false }) public badges: HuiBadge[] = [];
|
||||
|
||||
@property({ attribute: false }) public config?: LovelaceViewHeaderConfig;
|
||||
|
||||
@property({ attribute: false }) public viewIndex!: number;
|
||||
|
||||
private _checkHidden() {
|
||||
const allHidden =
|
||||
!this.card &&
|
||||
!this.lovelace.editMode &&
|
||||
this.badges.every((badges) => badges.hidden);
|
||||
this.toggleAttribute("hidden", allHidden);
|
||||
}
|
||||
|
||||
private _badgeVisibilityChanged = () => {
|
||||
this._checkHidden();
|
||||
};
|
||||
|
||||
connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
this.addEventListener(
|
||||
"badge-visibility-changed",
|
||||
this._badgeVisibilityChanged
|
||||
);
|
||||
}
|
||||
|
||||
disconnectedCallback(): void {
|
||||
super.disconnectedCallback();
|
||||
this.removeEventListener(
|
||||
"badge-visibility-changed",
|
||||
this._badgeVisibilityChanged
|
||||
);
|
||||
}
|
||||
|
||||
willUpdate(changedProperties: PropertyValues<typeof this>): void {
|
||||
if (
|
||||
changedProperties.has("badges") ||
|
||||
changedProperties.has("lovelace") ||
|
||||
changedProperties.has("card")
|
||||
) {
|
||||
this._checkHidden();
|
||||
}
|
||||
|
||||
if (changedProperties.has("config")) {
|
||||
if (this.config?.card) {
|
||||
this.card = this._createCardElement(this.config.card);
|
||||
} else {
|
||||
this.card = undefined;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.card) {
|
||||
if (changedProperties.has("hass")) {
|
||||
this.card.hass = this.hass;
|
||||
}
|
||||
if (changedProperties.has("lovelace")) {
|
||||
this.card.preview = this.lovelace.editMode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _createCardElement(cardConfig: LovelaceCardConfig) {
|
||||
const element = document.createElement("hui-card");
|
||||
element.hass = this.hass;
|
||||
element.preview = this.lovelace.editMode;
|
||||
element.config = cardConfig;
|
||||
element.load();
|
||||
return element;
|
||||
}
|
||||
|
||||
private _addCard() {
|
||||
const cardConfig: LovelaceCardConfig = {
|
||||
type: "markdown",
|
||||
text_only: true,
|
||||
content: this.hass.localize(
|
||||
"ui.panel.lovelace.editor.edit_view_header.default_title",
|
||||
{ user: "{{ user }}" }
|
||||
),
|
||||
};
|
||||
|
||||
showEditCardDialog(this, {
|
||||
cardConfig,
|
||||
lovelaceConfig: this.lovelace.config,
|
||||
saveCardConfig: (newCardConfig: LovelaceCardConfig) => {
|
||||
const newConfig = { ...this.config };
|
||||
newConfig.card = newCardConfig;
|
||||
this._saveHeaderConfig(newConfig);
|
||||
},
|
||||
isNew: true,
|
||||
});
|
||||
}
|
||||
|
||||
private _deleteCard(ev) {
|
||||
ev.stopPropagation();
|
||||
const newConfig = { ...this.config };
|
||||
delete newConfig.card;
|
||||
this._saveHeaderConfig(newConfig);
|
||||
}
|
||||
|
||||
private _editCard(ev) {
|
||||
ev.stopPropagation();
|
||||
const cardConfig = this.config!.card;
|
||||
|
||||
if (!cardConfig) {
|
||||
return;
|
||||
}
|
||||
|
||||
showEditCardDialog(this, {
|
||||
cardConfig,
|
||||
lovelaceConfig: this.lovelace.config,
|
||||
saveCardConfig: (newCardConfig: LovelaceCardConfig) => {
|
||||
const newConfig = { ...this.config };
|
||||
newConfig.card = newCardConfig;
|
||||
this._saveHeaderConfig(newConfig);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private _saveHeaderConfig(headerConfig: LovelaceViewHeaderConfig) {
|
||||
const viewConfig = this.lovelace.config.views[
|
||||
this.viewIndex
|
||||
] as LovelaceViewConfig;
|
||||
|
||||
const config = { ...viewConfig };
|
||||
config.header = headerConfig;
|
||||
|
||||
const updatedConfig = replaceView(
|
||||
this.hass,
|
||||
this.lovelace.config,
|
||||
this.viewIndex,
|
||||
config
|
||||
);
|
||||
this.lovelace.saveConfig(updatedConfig);
|
||||
}
|
||||
|
||||
private _configure = () => {
|
||||
showEditViewHeaderDialog(this, {
|
||||
config: this.config!,
|
||||
saveConfig: (config: LovelaceViewHeaderConfig) => {
|
||||
this._saveHeaderConfig(config);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
if (!this.lovelace) return nothing;
|
||||
|
||||
const editMode = Boolean(this.lovelace?.editMode);
|
||||
|
||||
const card = this.card;
|
||||
|
||||
const layout = this.config?.layout ?? DEFAULT_VIEW_HEADER_LAYOUT;
|
||||
const badgesPosition =
|
||||
this.config?.badges_position ?? DEFAULT_VIEW_HEADER_BADGES_POSITION;
|
||||
|
||||
const hasHeading = card !== undefined;
|
||||
const hasBadges = this.badges.length > 0;
|
||||
|
||||
return html`
|
||||
${editMode
|
||||
? html`
|
||||
<div class="actions-container">
|
||||
<div class="actions">
|
||||
<ha-icon-button
|
||||
.label=${this.hass.localize("ui.common.edit")}
|
||||
@click=${this._configure}
|
||||
.path=${mdiPencil}
|
||||
></ha-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
: nothing}
|
||||
<div class="container ${editMode ? "edit-mode" : ""}">
|
||||
<div
|
||||
class="layout ${classMap({
|
||||
[layout]: true,
|
||||
[`badges-${badgesPosition}`]: true,
|
||||
"has-heading": hasHeading,
|
||||
"has-badges": hasBadges,
|
||||
})}"
|
||||
>
|
||||
${card || editMode
|
||||
? html`
|
||||
<div class="heading">
|
||||
${editMode
|
||||
? card
|
||||
? html`
|
||||
<hui-card-edit-mode
|
||||
@ll-edit-card=${this._editCard}
|
||||
@ll-delete-card=${this._deleteCard}
|
||||
.hass=${this.hass}
|
||||
.lovelace=${this.lovelace!}
|
||||
.path=${[0]}
|
||||
no-duplicate
|
||||
no-move
|
||||
>
|
||||
${card}
|
||||
</hui-card-edit-mode>
|
||||
`
|
||||
: html`
|
||||
<button class="add" @click=${this._addCard}>
|
||||
<ha-ripple></ha-ripple>
|
||||
<ha-svg-icon .path=${mdiPlus}></ha-svg-icon>
|
||||
${this.hass.localize(
|
||||
"ui.panel.lovelace.editor.edit_view_header.add_title"
|
||||
)}
|
||||
</button>
|
||||
`
|
||||
: card}
|
||||
</div>
|
||||
`
|
||||
: nothing}
|
||||
${this.lovelace && (editMode || this.badges.length > 0)
|
||||
? html`
|
||||
<div class="badges ${badgesPosition}">
|
||||
<hui-view-badges
|
||||
.badges=${this.badges}
|
||||
.hass=${this.hass}
|
||||
.lovelace=${this.lovelace!}
|
||||
.viewIndex=${this.viewIndex!}
|
||||
.showAddLabel=${this.badges.length === 0}
|
||||
></hui-view-badges>
|
||||
</div>
|
||||
`
|
||||
: nothing}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host([hidden]) {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.actions-container {
|
||||
position: relative;
|
||||
height: 34px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.actions {
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
height: 36px;
|
||||
bottom: -2px;
|
||||
right: 0;
|
||||
inset-inline-end: 0;
|
||||
inset-inline-start: initial;
|
||||
opacity: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: opacity 0.2s ease-in-out;
|
||||
border-radius: var(--ha-card-border-radius, 12px);
|
||||
border-bottom-left-radius: 0px;
|
||||
border-bottom-right-radius: 0px;
|
||||
background: var(--secondary-background-color);
|
||||
--mdc-icon-button-size: 36px;
|
||||
--mdc-icon-size: 20px;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
|
||||
.layout {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px 8px;
|
||||
--spacing: 24px;
|
||||
}
|
||||
|
||||
.layout.has-heading {
|
||||
margin-top: var(--spacing);
|
||||
}
|
||||
|
||||
.heading {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
max-width: 700px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.heading > * {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.badges {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
hui-view-badges {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
--badges-aligmnent: flex-start;
|
||||
}
|
||||
|
||||
/* Layout */
|
||||
.layout {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.layout.center {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.layout .heading {
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
.layout.center .heading {
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.layout.center hui-view-badges {
|
||||
--badges-aligmnent: center;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.layout.responsive.has-heading {
|
||||
flex-direction: row;
|
||||
align-items: flex-end;
|
||||
}
|
||||
.layout.responsive.has-heading hui-view-badges {
|
||||
--badges-aligmnent: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.layout.badges-top {
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
.layout.badges-top.has-badges {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.layout.responsive.badges-top.has-heading {
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
margin-top: var(--spacing);
|
||||
}
|
||||
}
|
||||
|
||||
.container.edit-mode {
|
||||
padding: 8px;
|
||||
border-radius: var(--ha-card-border-radius, 12px);
|
||||
border: 2px dashed var(--divider-color);
|
||||
border-start-end-radius: 0;
|
||||
}
|
||||
|
||||
.container.edit-mode .content {
|
||||
min-height: 36px;
|
||||
}
|
||||
|
||||
.add {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
outline: none;
|
||||
gap: 8px;
|
||||
height: 36px;
|
||||
padding: 6px 20px 6px 20px;
|
||||
box-sizing: border-box;
|
||||
width: auto;
|
||||
border-radius: var(--ha-card-border-radius, 12px);
|
||||
background-color: transparent;
|
||||
border-width: 2px;
|
||||
border-style: dashed;
|
||||
border-color: var(--primary-color);
|
||||
--mdc-icon-size: 18px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
color: var(--primary-text-color);
|
||||
--ha-ripple-color: var(--primary-color);
|
||||
--ha-ripple-hover-opacity: 0.04;
|
||||
--ha-ripple-pressed-opacity: 0.12;
|
||||
}
|
||||
|
||||
.add:focus {
|
||||
border-style: solid;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"hui-view-header": HuiViewHeader;
|
||||
}
|
||||
}
|
@ -6575,6 +6575,31 @@
|
||||
"error_same_url": "You cannot save a view with the same URL as a different existing view.",
|
||||
"move_to_dashboard": "Move to dashboard"
|
||||
},
|
||||
"edit_view_header": {
|
||||
"add_title": "Add title",
|
||||
"header": "Header settings",
|
||||
"edit_ui": "[%key:ui::panel::lovelace::editor::edit_view::edit_ui%]",
|
||||
"edit_yaml": "[%key:ui::panel::lovelace::editor::edit_view::edit_yaml%]",
|
||||
"saving_failed": "[%key:ui::panel::lovelace::editor::edit_view::saving_failed%]",
|
||||
"default_title": "# Hello {user}\nAdd your text here, template variables are supported ✨",
|
||||
"settings": {
|
||||
"layout": "Layout",
|
||||
"layout_options": {
|
||||
"responsive": "Responsive",
|
||||
"responsive_description": "Stacked on mobile",
|
||||
"start": "Left aligned",
|
||||
"start_description": "Always stacked",
|
||||
"start_rtl": "Right aligned",
|
||||
"center": "Centered",
|
||||
"center_description": "Always stacked"
|
||||
},
|
||||
"badges_position": "Badges position",
|
||||
"badges_position_options": {
|
||||
"top": "Top",
|
||||
"bottom": "Bottom"
|
||||
}
|
||||
}
|
||||
},
|
||||
"edit_badges": {
|
||||
"view_no_badges": "Badges are not be supported by the current view type."
|
||||
},
|
||||
@ -6694,8 +6719,6 @@
|
||||
"edit_ui": "[%key:ui::panel::lovelace::editor::edit_view::edit_ui%]",
|
||||
"edit_yaml": "[%key:ui::panel::lovelace::editor::edit_view::edit_yaml%]",
|
||||
"settings": {
|
||||
"title": "Title",
|
||||
"title_helper": "The title will appear at the top of section. Leave empty to hide the title.",
|
||||
"column_span": "Width",
|
||||
"column_span_helper": "Larger sections will be made smaller to fit the display. (e.g. on mobile devices)"
|
||||
},
|
||||
|