mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-01 12:18:51 +00:00
AC0 задачи: пока референс лежит вложением в issue, ревью сравнивает продукт с макетом «на глаз», и ровно это дало выпущенный в 1.77.0-beta.2 ложный паритет — карточки снаружи, старая разметка внутри. Содержимое архива `houseplan-settings-design-2026-09-18.zip` (SHA-256 06f07fc212947ee9da1a39aaab2d14cbd41154cc9effe39bc48e1c2e1517255b, сверен побайтово с вложением #591) разложено по образцу #505: - `SPEC.md`, `IMPLEMENTATION-GUIDE.md`, `OPEN-POINTS.md`, карта полей Space — с этого коммита часть ТЗ: расхождение называется ссылкой на пункт документа; - `reference/` — свёрстанный прототип четырёх форм; - `screenshots/` — четыре формы целиком, 560 px, 2x; - `README.md` — происхождение, отпечаток, границы использования; - `ACCEPTANCE.md` — место для парных кадров «референс / продукт» по AC1. Автор — сотрудник владельца (подтверждено 20.09 в #600), внешний грант не нужен. Windows-лаунчеры `START.cmd` и `START.ps1` не переносились: `node serve.mjs` делает то же самое. `room-fill.test.mjs` перенесён как документ намерения, CI его не запускает — под `docs/**` не попадает ни один тестовый glob. В бандл отсюда не попадает ничего; `repo-hygiene` и полный набор зелёные (2793 pass). Issue: #600 User-Visible: no
49 lines
2.5 KiB
JavaScript
49 lines
2.5 KiB
JavaScript
/* House Plan roomFillStyle + Glow fallback, adapted for this isolated demo.
|
|
Source: c22c04d6476d0d387c237b427d0b83e7c1e11f70, src/logic.ts and
|
|
src/space-render.ts. See ROOM-FILL.md for palette and data limitations. */
|
|
export const DEFAULT_CUSTOM_FILL = {c:'#607d8b', a:.18};
|
|
export const DEFAULT_FILL_COLORS = {
|
|
light_on:{c:'#ffd45c',a:.18}, light_off:{c:'#9aa0a6',a:.14},
|
|
light_none:{c:'#6b7480',a:0},
|
|
temp_cold:{c:'#4fc3f7',a:.18}, temp_ok:{c:'#66d17a',a:.18},
|
|
temp_hot:{c:'#ffd45c',a:.18},
|
|
lqi_low:{c:'#f25a4a',a:.18}, lqi_high:{c:'#4bd28f',a:.18},
|
|
glow_base:{c:'#0d1b2a',a:.5},
|
|
};
|
|
const clamp = value => Math.min(1,Math.max(0,value));
|
|
function mixColor(a,b,t) {
|
|
return '#' + [1,3,5].map(i=>{
|
|
const start=parseInt(a.slice(i,i+2),16),end=parseInt(b.slice(i,i+2),16);
|
|
return Math.round(start+(end-start)*t).toString(16).padStart(2,'0');
|
|
}).join('');
|
|
}
|
|
export function roomFillStyle({mode,lqi,lights,temp,min,max,custom=DEFAULT_CUSTOM_FILL},colors=DEFAULT_FILL_COLORS) {
|
|
if(mode==='custom')return custom;
|
|
if(mode==='lqi') {
|
|
if(lqi==null)return null;
|
|
const t=clamp((lqi-40)/140);
|
|
return {c:mixColor(colors.lqi_low.c,colors.lqi_high.c,t),a:colors.lqi_low.a+(colors.lqi_high.a-colors.lqi_low.a)*t};
|
|
}
|
|
if(mode==='light')return lights==='none' ? (colors.light_none.a>0?colors.light_none:null) : colors[lights==='on'?'light_on':'light_off'];
|
|
if(mode==='temp') {
|
|
if(temp==null)return null;
|
|
return colors[temp<Math.min(min,max)?'temp_cold':temp>Math.max(min,max)?'temp_hot':'temp_ok'];
|
|
}
|
|
return null;
|
|
}
|
|
export function previewFill(settings,data,colors=DEFAULT_FILL_COLORS) {
|
|
const fill=roomFillStyle({mode:settings.fillMode,lqi:data.lqi,lights:data.totalLights===0?'none':data.onLights>0?'on':'off',temp:data.temp,min:settings.tempMin,max:settings.tempMax,
|
|
custom:settings.customFillSet?{c:settings.fillColor,a:clamp(Number(settings.fillOpacity)/100)}:DEFAULT_CUSTOM_FILL},colors);
|
|
return {fill,glowBase:settings.glowEnabled&&(!fill||fill.a<=0)?colors.glow_base:null};
|
|
}
|
|
const typical={temp:22.4,humidity:45,lqi:92,onLights:1,totalLights:3};
|
|
export const SAMPLE_SCENARIOS = {
|
|
typical:{label:'Typical room',...typical},
|
|
off:{label:'Lights off',...typical,onLights:0},
|
|
cold:{label:'Cold room',...typical,temp:16},
|
|
hot:{label:'Hot room',...typical,temp:30},
|
|
low:{label:'Weak Zigbee',...typical,lqi:30},
|
|
high:{label:'Strong Zigbee',...typical,lqi:200},
|
|
empty:{label:'No room data',temp:null,humidity:null,lqi:null,onLights:0,totalLights:0},
|
|
};
|