import { html, nothing, type TemplateResult } from 'lit'; import type { SummaryPanelConfig, SummaryPanelSource } from './types'; import { type SummaryDraftProblem, type SummaryPanelLocalPreferences, moveSummaryItem, newSummaryBlock, newSummaryValue, normalizeSummaryDraft, sameSummaryPanel, } from './summary-panel'; import type { SummaryPanelDialogState } from './summary-panel-runtime-loaded'; import type { SummaryPanelHost } from './summary-panel-host'; export type SummaryPanelEditorContext = { host: SummaryPanelHost; dialog: SummaryPanelDialogState; local: SummaryPanelLocalPreferences; storageUnavailable: boolean; problems: SummaryDraftProblem[]; setDialog(dialog: SummaryPanelDialogState | null): void; saveLocal(patch: Partial): void; mutate(mutate: (draft: SummaryPanelConfig) => void): void; deleteBlock(index: number): void; dragStart(event: DragEvent, token: string): void; drop(event: DragEvent, target: string): void; sourceToken(source: SummaryPanelSource): string; setSource(blockIndex: number, valueIndex: number, token: string): void; save(): void; reload(): void; close(): void; t(key: string): string; }; export type SummaryPanelEditorRenderer = ( context: SummaryPanelEditorContext, ) => TemplateResult | typeof nothing; /** Lazy settings surface for #437; imported only after the gear is pressed. */ export const renderSummaryPanelEditor: SummaryPanelEditorRenderer = (context) => { const { host, dialog, local, problems, t } = context; const firstError = problems.find((problem) => problem.kind === 'error'); const changed = dialog.localShow !== dialog.baseLocalShow || !dialog.localOnly && !sameSummaryPanel(normalizeSummaryDraft(dialog.draft), dialog.base); const canSave = changed && !dialog.busy && !firstError; const fieldProblem = (path: string) => problems.find((problem) => problem.path === path); const problemText = (problem: SummaryDraftProblem | undefined) => problem ? t(`summary.problem.${problem.code}`) : ''; const allEntities = Object.entries(host.hass?.states || {}).sort((a, b) => { const an = String(a[1]?.attributes?.friendly_name || a[0]); const bn = String(b[1]?.attributes?.friendly_name || b[0]); return an.localeCompare(bn); }); const query = dialog.entityFilter.trim().toLocaleLowerCase(); const entities = query ? allEntities.filter(([id, state]) => `${id} ${ state.attributes?.friendly_name || ''}`.toLocaleLowerCase().includes(query)) : allEntities; const close = () => context.close(); const showRow = html``; const sizeRows = html`

${t('summary.sizes_title')}

context.saveLocal({ icon_scale: Number((event.target as HTMLInputElement).value) / 100, })} /> ${Math.round(local.icon_scale * 100)}% context.saveLocal({ font_scale: Number((event.target as HTMLInputElement).value) / 100, })} /> ${Math.round(local.font_scale * 100)}%
${context.storageUnavailable ? html`
${t('summary.storage_unavailable')}
` : nothing}`; return html`
${dialog.localOnly ? html`

${t( dialog.localOnlyHint, )}

` : nothing} ${dialog.localOnly ? html`${showRow}${sizeRows}` : html` context.mutate((draft) => { draft.title = (event.target as HTMLInputElement).value; })} /> ${fieldProblem('title') ? html`
${problemText(fieldProblem('title'))}
` : nothing} ${showRow} ${sizeRows} context.setDialog({ ...dialog, entityFilter: (event.target as HTMLInputElement).value, })} /> ${entities.length ? nothing : html`
${t('summary.no_search_results')}
`}
${dialog.draft.blocks.map((block, bi) => { const bp = `blocks.${bi}`; const scopeProblem = fieldProblem(`${bp}.scope`); return html`
event.preventDefault()} @drop=${(event: DragEvent) => context.drop(event, `block:${bi}`)}>
context.dragStart(event, `block:${bi}`)}>⋮⋮ context.mutate((draft) => { draft.blocks[bi].title = (event.target as HTMLInputElement).value; })} />
${fieldProblem(`${bp}.title`) ? html`
${problemText(fieldProblem(`${bp}.title`))}
` : nothing}
${block.scope.type === 'space' ? html`` : nothing}
${scopeProblem ? html`
${problemText(scopeProblem)}
` : nothing}
${block.values.map((value, vi) => { const vp = `${bp}.values.${vi}`; const sourceProblem = fieldProblem(`${vp}.source`); const sourceToken = context.sourceToken(value.source); return html`
{ event.preventDefault(); event.stopPropagation(); }} @drop=${(event: DragEvent) => context.drop(event, `value:${bi}:${vi}`)}>
context.dragStart(event, `value:${bi}:${vi}`)}>⋮⋮ context.mutate((draft) => { draft.blocks[bi].values[vi].label = (event.target as HTMLInputElement).value; })} />
${fieldProblem(`${vp}.label`) ? html`
${problemText(fieldProblem(`${vp}.label`))}
` : nothing} ${sourceProblem ? html`
${problemText(sourceProblem)}
` : nothing}
`; })}
`; })}
${dialog.error ? html`` : nothing} ${dialog.conflict ? html`` : nothing} `}
`; };