1.8.3
Filter colours to match group Expand units tick box
This commit is contained in:
@@ -240,6 +240,48 @@
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* ── COLUMN TOGGLE - group colour tints ─────────────────────────────────
|
||||
Idle: light group tint bg + group text + group border.
|
||||
Hover: darker tint matching th hover palette.
|
||||
On: solid saturated group colour, white text.
|
||||
On-hover: slightly darker solid. */
|
||||
|
||||
.col-toggle.grp-felt { background: rgba(223,243,236,0.50); color: #075c3a; border-color: rgba(7,92,58,0.35); }
|
||||
.col-toggle.grp-surface { background: rgba(221,234,248,0.50); color: #0b3e72; border-color: rgba(11,62,114,0.30); }
|
||||
.col-toggle.grp-ambient { background: rgba(236,234,227,0.50); color: #3c3a35; border-color: rgba(60,58,53,0.30); }
|
||||
.col-toggle.grp-precip { background: rgba(247,228,238,0.50); color: #6b1e3a; border-color: rgba(107,30,58,0.30); }
|
||||
.col-toggle.grp-sky { background: rgba(234,232,252,0.50); color: #352e7a; border-color: rgba(53,46,122,0.30); }
|
||||
.col-toggle.grp-wind { background: rgba(250,230,224,0.50); color: #6a2210; border-color: rgba(106,34,16,0.30); }
|
||||
.col-toggle.grp-airqual { background: rgba(229,240,216,0.50); color: #244408; border-color: rgba(36,68,8,0.30); }
|
||||
.col-toggle.grp-solar { background: rgba(250,234,204,0.50); color: #5a3004; border-color: rgba(90,48,4,0.30); }
|
||||
|
||||
.col-toggle.grp-felt:hover { background: rgba(213,233,226,0.80); color: #075c3a; border-color: rgba(7,92,58,0.55); }
|
||||
.col-toggle.grp-surface:hover { background: rgba(211,224,238,0.80); color: #0b3e72; border-color: rgba(11,62,114,0.50); }
|
||||
.col-toggle.grp-ambient:hover { background: rgba(226,224,217,0.80); color: #3c3a35; border-color: rgba(60,58,53,0.50); }
|
||||
.col-toggle.grp-precip:hover { background: rgba(237,218,228,0.80); color: #6b1e3a; border-color: rgba(107,30,58,0.50); }
|
||||
.col-toggle.grp-sky:hover { background: rgba(224,222,242,0.80); color: #352e7a; border-color: rgba(53,46,122,0.50); }
|
||||
.col-toggle.grp-wind:hover { background: rgba(240,220,214,0.80); color: #6a2210; border-color: rgba(106,34,16,0.50); }
|
||||
.col-toggle.grp-airqual:hover { background: rgba(219,230,206,0.80); color: #244408; border-color: rgba(36,68,8,0.50); }
|
||||
.col-toggle.grp-solar:hover { background: rgba(240,224,194,0.80); color: #5a3004; border-color: rgba(90,48,4,0.50); }
|
||||
|
||||
.col-toggle.grp-felt.on { background: #0f9e63; border-color: #0f9e63; color: #fff; }
|
||||
.col-toggle.grp-surface.on { background: #2672c8; border-color: #2672c8; color: #fff; }
|
||||
.col-toggle.grp-ambient.on { background: #7a7870; border-color: #7a7870; color: #fff; }
|
||||
.col-toggle.grp-precip.on { background: #b03060; border-color: #b03060; color: #fff; }
|
||||
.col-toggle.grp-sky.on { background: #6058c8; border-color: #6058c8; color: #fff; }
|
||||
.col-toggle.grp-wind.on { background: #b04030; border-color: #b04030; color: #fff; }
|
||||
.col-toggle.grp-airqual.on { background: #4a8018; border-color: #4a8018; color: #fff; }
|
||||
.col-toggle.grp-solar.on { background: #b07820; border-color: #b07820; color: #fff; }
|
||||
|
||||
.col-toggle.grp-felt.on:hover { background: #0c7d4e; border-color: #0c7d4e; color: #fff; }
|
||||
.col-toggle.grp-surface.on:hover { background: #1e5aa0; border-color: #1e5aa0; color: #fff; }
|
||||
.col-toggle.grp-ambient.on:hover { background: #5e5c56; border-color: #5e5c56; color: #fff; }
|
||||
.col-toggle.grp-precip.on:hover { background: #8c264c; border-color: #8c264c; color: #fff; }
|
||||
.col-toggle.grp-sky.on:hover { background: #4c48a8; border-color: #4c48a8; color: #fff; }
|
||||
.col-toggle.grp-wind.on:hover { background: #8c3226; border-color: #8c3226; color: #fff; }
|
||||
.col-toggle.grp-airqual.on:hover { background: #3a6412; border-color: #3a6412; color: #fff; }
|
||||
.col-toggle.grp-solar.on:hover { background: #8c5e18; border-color: #8c5e18; color: #fff; }
|
||||
|
||||
/* ── Vehicle group: select + windows-open checkbox fused together ── */
|
||||
.col-toggle-group {
|
||||
display: inline-flex;
|
||||
@@ -426,6 +468,8 @@
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
/* col-unit header spans always visible - units toggle only affects body cells */
|
||||
|
||||
@media (max-width: 800px) {
|
||||
.utci-table th .col-unit {
|
||||
font-size: 9px;
|
||||
|
||||
@@ -364,6 +364,59 @@
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* ── CUSTOM SELECT BUTTON - group colour tints ──────────────────────────
|
||||
Mirrors the col-toggle group palette for dropdowns (Vehicle, Indoors,
|
||||
Burn, Pollen). Same idle - hover - on - on-hover pattern. */
|
||||
|
||||
.cs-btn.grp-felt { background: rgba(223,243,236,0.50); color: #075c3a; border-color: rgba(7,92,58,0.35); }
|
||||
.cs-btn.grp-surface { background: rgba(221,234,248,0.50); color: #0b3e72; border-color: rgba(11,62,114,0.30); }
|
||||
.cs-btn.grp-ambient { background: rgba(236,234,227,0.50); color: #3c3a35; border-color: rgba(60,58,53,0.30); }
|
||||
.cs-btn.grp-precip { background: rgba(247,228,238,0.50); color: #6b1e3a; border-color: rgba(107,30,58,0.30); }
|
||||
.cs-btn.grp-sky { background: rgba(234,232,252,0.50); color: #352e7a; border-color: rgba(53,46,122,0.30); }
|
||||
.cs-btn.grp-wind { background: rgba(250,230,224,0.50); color: #6a2210; border-color: rgba(106,34,16,0.30); }
|
||||
.cs-btn.grp-airqual { background: rgba(229,240,216,0.50); color: #244408; border-color: rgba(36,68,8,0.30); }
|
||||
.cs-btn.grp-solar { background: rgba(250,234,204,0.50); color: #5a3004; border-color: rgba(90,48,4,0.30); }
|
||||
|
||||
.cs-btn.grp-felt:hover { background: rgba(213,233,226,0.80); color: #075c3a; border-color: rgba(7,92,58,0.55); }
|
||||
.cs-btn.grp-surface:hover { background: rgba(211,224,238,0.80); color: #0b3e72; border-color: rgba(11,62,114,0.50); }
|
||||
.cs-btn.grp-ambient:hover { background: rgba(226,224,217,0.80); color: #3c3a35; border-color: rgba(60,58,53,0.50); }
|
||||
.cs-btn.grp-precip:hover { background: rgba(237,218,228,0.80); color: #6b1e3a; border-color: rgba(107,30,58,0.50); }
|
||||
.cs-btn.grp-sky:hover { background: rgba(224,222,242,0.80); color: #352e7a; border-color: rgba(53,46,122,0.50); }
|
||||
.cs-btn.grp-wind:hover { background: rgba(240,220,214,0.80); color: #6a2210; border-color: rgba(106,34,16,0.50); }
|
||||
.cs-btn.grp-airqual:hover { background: rgba(219,230,206,0.80); color: #244408; border-color: rgba(36,68,8,0.50); }
|
||||
.cs-btn.grp-solar:hover { background: rgba(240,224,194,0.80); color: #5a3004; border-color: rgba(90,48,4,0.50); }
|
||||
|
||||
.cs-btn.grp-felt.on { background: #0f9e63; border-color: #0f9e63; color: #fff; }
|
||||
.cs-btn.grp-surface.on { background: #2672c8; border-color: #2672c8; color: #fff; }
|
||||
.cs-btn.grp-ambient.on { background: #7a7870; border-color: #7a7870; color: #fff; }
|
||||
.cs-btn.grp-precip.on { background: #b03060; border-color: #b03060; color: #fff; }
|
||||
.cs-btn.grp-sky.on { background: #6058c8; border-color: #6058c8; color: #fff; }
|
||||
.cs-btn.grp-wind.on { background: #b04030; border-color: #b04030; color: #fff; }
|
||||
.cs-btn.grp-airqual.on { background: #4a8018; border-color: #4a8018; color: #fff; }
|
||||
.cs-btn.grp-solar.on { background: #b07820; border-color: #b07820; color: #fff; }
|
||||
|
||||
.cs-btn.grp-felt.on:hover { background: #0c7d4e; border-color: #0c7d4e; color: #fff; }
|
||||
.cs-btn.grp-surface.on:hover { background: #1e5aa0; border-color: #1e5aa0; color: #fff; }
|
||||
.cs-btn.grp-ambient.on:hover { background: #5e5c56; border-color: #5e5c56; color: #fff; }
|
||||
.cs-btn.grp-precip.on:hover { background: #8c264c; border-color: #8c264c; color: #fff; }
|
||||
.cs-btn.grp-sky.on:hover { background: #4c48a8; border-color: #4c48a8; color: #fff; }
|
||||
.cs-btn.grp-wind.on:hover { background: #8c3226; border-color: #8c3226; color: #fff; }
|
||||
.cs-btn.grp-airqual.on:hover { background: #3a6412; border-color: #3a6412; color: #fff; }
|
||||
.cs-btn.grp-solar.on:hover { background: #8c5e18; border-color: #8c5e18; color: #fff; }
|
||||
|
||||
/* ── VENT PILL - group colour tints ─────────────────────────────────────
|
||||
VentPill fuses with its sibling cs-btn so needs matching group tints.
|
||||
Only felt and surface groups currently use VentPills. */
|
||||
|
||||
.cs-vent.grp-felt { background: rgba(223,243,236,0.50); color: #075c3a; border-color: rgba(7,92,58,0.35); }
|
||||
.cs-vent.grp-surface { background: rgba(221,234,248,0.50); color: #0b3e72; border-color: rgba(11,62,114,0.30); }
|
||||
.cs-vent.grp-felt:hover { background: rgba(213,233,226,0.80); color: #075c3a; border-color: rgba(7,92,58,0.55); }
|
||||
.cs-vent.grp-surface:hover { background: rgba(211,224,238,0.80); color: #0b3e72; border-color: rgba(11,62,114,0.50); }
|
||||
.cs-vent.grp-felt.on { border-color: #0f9e63; color: #0f9e63; }
|
||||
.cs-vent.grp-surface.on { border-color: #2672c8; color: #2672c8; }
|
||||
.cs-vent.grp-felt.on:hover { background: rgba(213,233,226,0.80); color: #0c7d4e; border-color: #0c7d4e; }
|
||||
.cs-vent.grp-surface.on:hover { background: rgba(211,224,238,0.80); color: #1e5aa0; border-color: #1e5aa0; }
|
||||
|
||||
/* The chevron arrow inside the button */
|
||||
.cs-arrow {
|
||||
display: inline-block;
|
||||
|
||||
+64
-58
@@ -53,7 +53,7 @@ export function UTCIForecast() {
|
||||
activeProfile, setActiveProfile, activateProfile, activeCols,
|
||||
visibleCols, setVisibleCols, toggleCol,
|
||||
showDecimals, toggleShowDecimals,
|
||||
showDegree, toggleShowDegree,
|
||||
showUnits, toggleShowUnits,
|
||||
activityOptions, placeOptions,
|
||||
activityValue, activityLabel, placeValue, placeLabel,
|
||||
skinType, setSkinType,
|
||||
@@ -336,12 +336,13 @@ export function UTCIForecast() {
|
||||
<div class="col-toggles">
|
||||
<span class="col-toggles-label">Columns:</span>
|
||||
|
||||
${isPro && (activeProfile === 'custom' || activeCols['utciP']) && html`<button class=${`col-toggle${visibleCols.utciP ? ' on' : ''}`} onClick=${() => toggleCol('utciP')}>UTCI+P</button>`}
|
||||
${(isPro ? (activeProfile === 'custom' || activeCols['vehicleT']) : activeCols['vehicleT']) && html`
|
||||
${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['utciP']) && html`<button class=${`col-toggle grp-felt${visibleCols.utciP ? ' on' : ''}`} onClick=${() => toggleCol('utciP')}>UTCI+P</button>`}
|
||||
${(isPro ? (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['vehicleT']) : activeCols['vehicleT']) && html`
|
||||
<span class=${'col-toggle-group' + (visibleCols.vehicleT ? ' col-toggle-group--expanded' : '')}>
|
||||
<${CustomSelect}
|
||||
value=${vehicleType}
|
||||
isOn=${visibleCols.vehicleT}
|
||||
grpClass="grp-felt"
|
||||
hideLabel="Vehicle"
|
||||
hidingLabel="Hide Vehicle"
|
||||
groupedLeft=${true}
|
||||
@@ -364,15 +365,17 @@ ${isPro && (activeProfile === 'custom' || activeCols['utciP']) && html`<button c
|
||||
<${VentPill}
|
||||
checked=${vehicleVent}
|
||||
onChange=${() => setVehicleVent(v => !v)}
|
||||
grpClass="grp-felt"
|
||||
label="Ventilation"
|
||||
title="Ventilation — open windows significantly reduce cabin heat build-up"
|
||||
/>`}
|
||||
</span>`}
|
||||
${(isPro ? (activeProfile === 'custom' || activeCols['indoorT'] || activeCols['managedT']) : (activeCols['indoorT'] || activeCols['managedT'])) && html`
|
||||
${(isPro ? (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['indoorT'] || activeCols['managedT']) : (activeCols['indoorT'] || activeCols['managedT'])) && html`
|
||||
<span class=${'col-toggle-group' + (indoorMode === 'on' ? ' col-toggle-group--expanded' : '')}>
|
||||
<${CustomSelect}
|
||||
value=${buildingType}
|
||||
isOn=${indoorMode === 'on'}
|
||||
grpClass="grp-felt"
|
||||
hideLabel="Indoors"
|
||||
hidingLabel="Hide Indoors"
|
||||
groupedLeft=${true}
|
||||
@@ -395,14 +398,16 @@ ${isPro && (activeProfile === 'custom' || activeCols['utciP']) && html`<button c
|
||||
<${VentPill}
|
||||
checked=${indoorManaged}
|
||||
onChange=${() => setIndoorManaged(v => !v)}
|
||||
grpClass="grp-felt"
|
||||
label="Managed"
|
||||
title="Managed: curtains closed by day, windows open when cooler outside"
|
||||
/>`}
|
||||
</span>`}
|
||||
${(isPro ? (activeProfile === 'custom' || activeCols['burn']) : activeCols['burn']) && html`
|
||||
${(isPro ? (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['burn']) : activeCols['burn']) && html`
|
||||
<${CustomSelect}
|
||||
value=${skinType}
|
||||
isOn=${visibleCols.burn}
|
||||
grpClass="grp-felt"
|
||||
hideLabel="Burn"
|
||||
hidingLabel="Hide Burn"
|
||||
options=${Object.entries(SKIN_TYPES).map(([k, v]) => ({
|
||||
@@ -418,26 +423,27 @@ ${isPro && (activeProfile === 'custom' || activeCols['utciP']) && html`<button c
|
||||
}
|
||||
}}
|
||||
/>`}
|
||||
${isPro && (activeProfile === 'custom' || activeCols['utci']) && html`<button class=${`col-toggle${visibleCols.utci ? ' on' : ''}`} onClick=${() => toggleCol('utci')}>UTCI</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeCols['delta']) && html`<button class=${`col-toggle${visibleCols.delta ? ' on' : ''}`} onClick=${() => toggleCol('delta')}>Δ</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeCols['tmrt']) && html`<button class=${`col-toggle${visibleCols.tmrt ? ' on' : ''}`} onClick=${() => toggleCol('tmrt')}>Tmrt</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeCols['concreteT']) && html`<button class=${`col-toggle${visibleCols.concreteT ? ' on' : ''}`} onClick=${() => toggleCol('concreteT')}>Concrete</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeCols['soilT']) && html`<button class=${`col-toggle${visibleCols.soilT ? ' on' : ''}`} onClick=${() => toggleCol('soilT')}>Soil °C</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeCols['soilT6']) && html`<button class=${`col-toggle${visibleCols.soilT6 ? ' on' : ''}`} onClick=${() => toggleCol('soilT6')}>Soil 6cm</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeCols['soilM']) && html`<button class=${`col-toggle${visibleCols.soilM ? ' on' : ''}`} onClick=${() => toggleCol('soilM')}>Soil moist</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeCols['air']) && html`<button class=${`col-toggle${visibleCols.air ? ' on' : ''}`} onClick=${() => toggleCol('air')}>Air</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeCols['rh']) && html`<button class=${`col-toggle${visibleCols.rh ? ' on' : ''}`} onClick=${() => toggleCol('rh')}>RH</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeCols['dew']) && html`<button class=${`col-toggle${visibleCols.dew ? ' on' : ''}`} onClick=${() => toggleCol('dew')}>Dew</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeCols['precip']) && html`<button class=${`col-toggle${visibleCols.precip ? ' on' : ''}`} onClick=${() => toggleCol('precip')}>Precip</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeCols['precipProb']) && html`<button class=${`col-toggle${visibleCols.precipProb ? ' on' : ''}`} onClick=${() => toggleCol('precipProb')}>Rain%</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeCols['cloud']) && html`<button class=${`col-toggle${visibleCols.cloud ? ' on' : ''}`} onClick=${() => toggleCol('cloud')}>Cloud</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeCols['vis']) && html`<button class=${`col-toggle${visibleCols.vis ? ' on' : ''}`} onClick=${() => toggleCol('vis')}>Visibility</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeCols['wind']) && html`<button class=${`col-toggle${visibleCols.wind ? ' on' : ''}`} onClick=${() => toggleCol('wind')}>Wind</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeCols['dir']) && html`<button class=${`col-toggle${visibleCols.dir ? ' on' : ''}`} onClick=${() => toggleCol('dir')}>Dir</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeCols['aqi']) && html`<button class=${`col-toggle${visibleCols.aqi ? ' on' : ''}`} onClick=${() => toggleCol('aqi')}>Air Quality</button>`}
|
||||
${(isPro ? (activeProfile === 'custom' || activeCols['pollen']) : activeCols['pollen']) && html`<${CustomSelect}
|
||||
${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['utci']) && html`<button class=${`col-toggle grp-felt${visibleCols.utci ? ' on' : ''}`} onClick=${() => toggleCol('utci')}>UTCI</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['delta']) && html`<button class=${`col-toggle grp-felt${visibleCols.delta ? ' on' : ''}`} onClick=${() => toggleCol('delta')}>Δ</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['tmrt']) && html`<button class=${`col-toggle grp-felt${visibleCols.tmrt ? ' on' : ''}`} onClick=${() => toggleCol('tmrt')}>Tmrt</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['concreteT']) && html`<button class=${`col-toggle grp-surface${visibleCols.concreteT ? ' on' : ''}`} onClick=${() => toggleCol('concreteT')}>Concrete</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['soilT']) && html`<button class=${`col-toggle grp-surface${visibleCols.soilT ? ' on' : ''}`} onClick=${() => toggleCol('soilT')}>Soil °C</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['soilT6']) && html`<button class=${`col-toggle grp-surface${visibleCols.soilT6 ? ' on' : ''}`} onClick=${() => toggleCol('soilT6')}>Soil 6cm</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['soilM']) && html`<button class=${`col-toggle grp-surface${visibleCols.soilM ? ' on' : ''}`} onClick=${() => toggleCol('soilM')}>Soil moist</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['air']) && html`<button class=${`col-toggle grp-ambient${visibleCols.air ? ' on' : ''}`} onClick=${() => toggleCol('air')}>Air</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['rh']) && html`<button class=${`col-toggle grp-ambient${visibleCols.rh ? ' on' : ''}`} onClick=${() => toggleCol('rh')}>RH</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['dew']) && html`<button class=${`col-toggle grp-ambient${visibleCols.dew ? ' on' : ''}`} onClick=${() => toggleCol('dew')}>Dew</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['precip']) && html`<button class=${`col-toggle grp-precip${visibleCols.precip ? ' on' : ''}`} onClick=${() => toggleCol('precip')}>Precip</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['precipProb']) && html`<button class=${`col-toggle grp-precip${visibleCols.precipProb ? ' on' : ''}`} onClick=${() => toggleCol('precipProb')}>Rain%</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['cloud']) && html`<button class=${`col-toggle grp-sky${visibleCols.cloud ? ' on' : ''}`} onClick=${() => toggleCol('cloud')}>Cloud</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['vis']) && html`<button class=${`col-toggle grp-sky${visibleCols.vis ? ' on' : ''}`} onClick=${() => toggleCol('vis')}>Visibility</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['wind']) && html`<button class=${`col-toggle grp-wind${visibleCols.wind ? ' on' : ''}`} onClick=${() => toggleCol('wind')}>Wind</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['dir']) && html`<button class=${`col-toggle grp-wind${visibleCols.dir ? ' on' : ''}`} onClick=${() => toggleCol('dir')}>Dir</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['aqi']) && html`<button class=${`col-toggle grp-airqual${visibleCols.aqi ? ' on' : ''}`} onClick=${() => toggleCol('aqi')}>Air Quality</button>`}
|
||||
${(isPro ? (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['pollen']) : activeCols['pollen']) && html`<${CustomSelect}
|
||||
value=${pollenType}
|
||||
isOn=${visibleCols.pollen}
|
||||
grpClass="grp-airqual"
|
||||
hideLabel="Pollen"
|
||||
hidingLabel="Hide Pollen"
|
||||
options=${Object.entries(POLLEN_TYPES).flatMap(([k, v], i) => [
|
||||
@@ -453,11 +459,11 @@ ${isPro && (activeProfile === 'custom' || activeCols['utciP']) && html`<button c
|
||||
}
|
||||
}}
|
||||
/>`}
|
||||
${isPro && (activeProfile === 'custom' || activeCols['uvA']) && html`<button class=${`col-toggle${visibleCols.uvA ? ' on' : ''}`} onClick=${() => toggleCol('uvA')}>UV-A</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeCols['uvB']) && html`<button class=${`col-toggle${visibleCols.uvB ? ' on' : ''}`} onClick=${() => toggleCol('uvB')}>UV-B</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeCols['sun']) && html`<button class=${`col-toggle${visibleCols.sun ? ' on' : ''}`} onClick=${() => toggleCol('sun')}>Sun</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeCols['direct']) && html`<button class=${`col-toggle${visibleCols.direct ? ' on' : ''}`} onClick=${() => toggleCol('direct')}>Direct</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeCols['diffuse']) && html`<button class=${`col-toggle${visibleCols.diffuse ? ' on' : ''}`} onClick=${() => toggleCol('diffuse')}>Diffuse</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['uvA']) && html`<button class=${`col-toggle grp-solar${visibleCols.uvA ? ' on' : ''}`} onClick=${() => toggleCol('uvA')}>UV-A</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['uvB']) && html`<button class=${`col-toggle grp-solar${visibleCols.uvB ? ' on' : ''}`} onClick=${() => toggleCol('uvB')}>UV-B</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['sun']) && html`<button class=${`col-toggle grp-solar${visibleCols.sun ? ' on' : ''}`} onClick=${() => toggleCol('sun')}>Sun</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['direct']) && html`<button class=${`col-toggle grp-solar${visibleCols.direct ? ' on' : ''}`} onClick=${() => toggleCol('direct')}>Direct</button>`}
|
||||
${isPro && (activeProfile === 'custom' || activeProfile === 'showall' || activeCols['diffuse']) && html`<button class=${`col-toggle grp-solar${visibleCols.diffuse ? ' on' : ''}`} onClick=${() => toggleCol('diffuse')}>Diffuse</button>`}
|
||||
|
||||
</div>`}
|
||||
|
||||
@@ -467,12 +473,12 @@ ${isPro && (activeProfile === 'custom' || activeCols['utciP']) && html`<button c
|
||||
Decimals
|
||||
</label>
|
||||
<label class="display-opt">
|
||||
<input type="checkbox" checked=${showDegree} onChange=${toggleShowDegree} />
|
||||
° symbol
|
||||
<input type="checkbox" checked=${showUnits} onChange=${toggleShowUnits} />
|
||||
Units
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class=${`utci-table-wrap${tableCanScrollLeft ? ' scroll-fade-left' : ''}${tableCanScrollRight ? ' scroll-fade-right' : ''}`} ref=${tableWrapRef}>
|
||||
<div class=${`utci-table-wrap${tableCanScrollLeft ? ' scroll-fade-left' : ''}${tableCanScrollRight ? ' scroll-fade-right' : ''}${showUnits ? '' : ' no-units'}`} ref=${tableWrapRef}>
|
||||
<span class="utci-scroll-chevron left" aria-hidden="true">‹</span>
|
||||
<span class="utci-scroll-chevron right" aria-hidden="true">›</span>
|
||||
|
||||
@@ -536,7 +542,7 @@ ${isPro && (activeProfile === 'custom' || activeCols['utciP']) && html`<button c
|
||||
return `rgba(${r},${g},${b},${a})`;
|
||||
};
|
||||
const fmt = (v, dp = 1) => v == null ? '—' : (showDecimals ? v.toFixed(dp) : String(Math.round(v)));
|
||||
const deg = showDegree ? '°' : '';
|
||||
const u = (unit) => showUnits ? unit : '';
|
||||
// Returns a background tint based on temperature value - all share the same
|
||||
// Thermal Stress Bands - solid colours matching the legend exactly.
|
||||
// All band-coloured cells use the full bg/fg from UTCI_BANDS.
|
||||
@@ -607,19 +613,19 @@ ${isPro && (activeProfile === 'custom' || activeCols['utciP']) && html`<button c
|
||||
</td>
|
||||
${visibleCols.utciP && html`
|
||||
<td class=${groupStart('utciP')} style=${{ background: bandGradient(adjCat.bg, adjCat.darkenAmt), color: adjCat.fg, fontSize: '13px', ...bandExtras(r.utciAdj) }}>
|
||||
${fmt(r.utciAdj)}${deg}
|
||||
${fmt(r.utciAdj)}${u('°C')}
|
||||
</td>`}
|
||||
${visibleCols.vehicleT && html`
|
||||
<td class=${groupStart('vehicleT')} style=${{ color: tempFontColorStrong(r.vehicleT), background: tempBgStrong(r.vehicleT), ...bandExtras(r.vehicleT) }}>
|
||||
${fmt(r.vehicleT)}${deg}
|
||||
${fmt(r.vehicleT)}${u('°C')}
|
||||
</td>`}
|
||||
${indoorMode === 'on' && !indoorManaged && html`
|
||||
<td class=${groupStart('indoorT')} style=${{ color: tempFontColorStrong(r.indoorT), background: tempBgStrong(r.indoorT), ...bandExtras(r.indoorT) }}>
|
||||
${fmt(r.indoorT)}${deg}
|
||||
${fmt(r.indoorT)}${u('°C')}
|
||||
</td>`}
|
||||
${indoorMode === 'on' && indoorManaged && html`
|
||||
<td class=${groupStart('managedT')} style=${{ color: tempFontColorStrong(r.managedT), background: tempBgStrong(r.managedT), ...bandExtras(r.managedT) }}>
|
||||
${fmt(r.managedT)}${deg}
|
||||
${fmt(r.managedT)}${u('°C')}
|
||||
</td>`}
|
||||
${visibleCols.burn && html`
|
||||
<td class=${groupStart('burn')} style=${{ color: r.uv > 0 ? (burnMins < 30 ? '#c44a3a' : '#c8601a') : '#4a3218', background: burnBg(burnMins, r.uv) }}>
|
||||
@@ -627,48 +633,48 @@ ${isPro && (activeProfile === 'custom' || activeCols['utciP']) && html`<button c
|
||||
</td>`}
|
||||
${visibleCols.utci && html`
|
||||
<td class=${groupStart('utci')} style=${{ background: bandGradient(cat.bg, cat.darkenAmt), color: cat.fg, ...bandExtras(r.utci) }}>
|
||||
${fmt(r.utci)}${deg}
|
||||
${fmt(r.utci)}${u('°C')}
|
||||
</td>`}
|
||||
${visibleCols.delta && html`
|
||||
<td class=${groupStart('delta')} style=${{
|
||||
color: delta > 3 ? '#c8601a' : delta < -3 ? '#3f73c4' : '#4a3218',
|
||||
background: deltaBg(delta),
|
||||
}}>
|
||||
${delta > 0 ? '+' : ''}${fmt(delta)}
|
||||
${delta > 0 ? '+' : ''}${fmt(delta)}${u('°C')}
|
||||
</td>`}
|
||||
${visibleCols.tmrt && html`<td class=${groupStart('tmrt')} style=${{ background: tempBgStrong(r.Tmrt), color: tempFontColorStrong(r.Tmrt), ...bandExtras(r.Tmrt) }}>${fmt(r.Tmrt)}${deg}</td>`}
|
||||
${visibleCols.tmrt && html`<td class=${groupStart('tmrt')} style=${{ background: tempBgStrong(r.Tmrt), color: tempFontColorStrong(r.Tmrt), ...bandExtras(r.Tmrt) }}>${fmt(r.Tmrt)}${u('°C')}</td>`}
|
||||
${visibleCols.concreteT && html`
|
||||
<td class=${groupStart('concreteT')} style=${{ color: tempFontColorStrong(r.concreteT), background: tempBgStrong(r.concreteT), ...bandExtras(r.concreteT) }}>
|
||||
${fmt(r.concreteT)}${deg}
|
||||
${fmt(r.concreteT)}${u('°C')}
|
||||
</td>`}
|
||||
${visibleCols.soilT && html`
|
||||
<td class=${groupStart('soilT')} style=${{ color: tempFontColorStrong(r.soilT0), background: tempBgStrong(r.soilT0), ...bandExtras(r.soilT0) }}>${fmt(r.soilT0)}${deg}</td>`}
|
||||
<td class=${groupStart('soilT')} style=${{ color: tempFontColorStrong(r.soilT0), background: tempBgStrong(r.soilT0), ...bandExtras(r.soilT0) }}>${fmt(r.soilT0)}${u('°C')}</td>`}
|
||||
${visibleCols.soilT6 && html`
|
||||
<td class=${groupStart('soilT6')} style=${{ color: tempFontColorStrong(r.soilT6), background: tempBgStrong(r.soilT6), ...bandExtras(r.soilT6) }}>${fmt(r.soilT6)}${deg}</td>`}
|
||||
<td class=${groupStart('soilT6')} style=${{ color: tempFontColorStrong(r.soilT6), background: tempBgStrong(r.soilT6), ...bandExtras(r.soilT6) }}>${fmt(r.soilT6)}${u('°C')}</td>`}
|
||||
${visibleCols.soilM && html`
|
||||
<td class=${groupStart('soilM')} style=${{ color: '#2a6a90', background: scaleBg(r.soilM, 0.12, 0.45, '50,125,190') }}>${r.soilM != null ? fmt(r.soilM * 100, 1) + '%' : '—'}</td>`}
|
||||
${visibleCols.air && html`<td class=${groupStart('air')} style=${{ background: tempBg(r.Ta), color: tempFontColorStrong(r.Ta), ...bandExtras(r.Ta) }}>${fmt(r.Ta)}${deg}</td>`}
|
||||
${visibleCols.rh && html`<td class=${groupStart('rh')} style=${{ background: scaleBg(r.RH, 30, 100, '70,145,200') }}>${Math.round(r.RH)}</td>`}
|
||||
${visibleCols.dew && html`<td class=${groupStart('dew')} style=${{ background: tempBgStrong(r.dew), color: tempFontColorStrong(r.dew), ...bandExtras(r.dew) }}>${fmt(r.dew)}${deg}</td>`}
|
||||
<td class=${groupStart('soilM')} style=${{ color: '#2a6a90', background: scaleBg(r.soilM, 0.12, 0.45, '50,125,190') }}>${r.soilM != null ? fmt(r.soilM * 100, 1) + u('%') : '—'}</td>`}
|
||||
${visibleCols.air && html`<td class=${groupStart('air')} style=${{ background: tempBg(r.Ta), color: tempFontColorStrong(r.Ta), ...bandExtras(r.Ta) }}>${fmt(r.Ta)}${u('°C')}</td>`}
|
||||
${visibleCols.rh && html`<td class=${groupStart('rh')} style=${{ background: scaleBg(r.RH, 30, 100, '70,145,200') }}>${Math.round(r.RH)}${u('%')}</td>`}
|
||||
${visibleCols.dew && html`<td class=${groupStart('dew')} style=${{ background: tempBgStrong(r.dew), color: tempFontColorStrong(r.dew), ...bandExtras(r.dew) }}>${fmt(r.dew)}${u('°C')}</td>`}
|
||||
${visibleCols.precip && html`
|
||||
<td class=${groupStart('precip')} style=${{ background: r.snow > 0 ? scaleBg(r.snow, 0, 4, '90,140,210') : scaleBg(r.precip, 0, 8, '70,145,200') }}>
|
||||
<span style=${{ display: 'inline-flex', alignItems: 'center', gap: '5px', verticalAlign: 'middle' }}>
|
||||
<${PrecipIcon} precip=${r.precip} snow=${r.snow} size=${28} />
|
||||
<span style=${{ color: r.snow > 0 ? '#2a5fa8' : r.precip > 0 ? '#2a6a90' : '#7a5c30' }}>
|
||||
${r.snow > 0 ? fmt(r.snow) + 'cm' : r.precip > 0 ? fmt(r.precip) : '—'}
|
||||
${r.snow > 0 ? fmt(r.snow) + u('cm') : r.precip > 0 ? fmt(r.precip) + u('mm') : '—'}
|
||||
</span>
|
||||
</span>
|
||||
</td>`}
|
||||
${visibleCols.precipProb && html`
|
||||
<td class=${groupStart('precipProb')} style=${{ background: scaleBg(r.precipProb, 0, 100, '70,145,200'), color: r.precipProb >= 50 ? '#1a4a70' : r.precipProb > 0 ? '#2a6a90' : '#7a8a90' }}>
|
||||
${r.precipProb}%
|
||||
${r.precipProb}${u('%')}
|
||||
</td>`}
|
||||
${visibleCols.cloud && html`<td class=${groupStart('cloud')} style=${{ background: scaleBg(r.cc, 0, 100, '110,130,150', 0.07), verticalAlign: 'middle' }}>
|
||||
<span style=${{ display: 'inline-flex', alignItems: 'center', gap: '6px', verticalAlign: 'middle' }}>
|
||||
<span style=${{ position: 'relative', top: '6px' }}>
|
||||
<${CloudIcon} category=${r.cloudCat} elev=${r.elev} dt=${r.dt} size=${28} />
|
||||
</span>
|
||||
<span>${Math.round(r.cc)}</span>
|
||||
<span>${Math.round(r.cc)}${u('%')}</span>
|
||||
</span>
|
||||
</td>`}
|
||||
${visibleCols.vis && (() => {
|
||||
@@ -680,12 +686,12 @@ ${isPro && (activeProfile === 'custom' || activeCols['utciP']) && html`<button c
|
||||
: 'transparent';
|
||||
const color = v != null && v < 4 ? '#8a3a1a' : '#4a3218';
|
||||
return html`<td class=${groupStart('vis')} style=${{ background: bg, color }}>
|
||||
${v != null ? fmt(v) : '—'}
|
||||
${v != null ? fmt(v) + u('km') : '—'}
|
||||
</td>`;
|
||||
})()}
|
||||
${visibleCols.wind && html`<td class=${groupStart('wind')} style=${{ background: scaleBg((r.gust ?? r.va) * 2.237, 0, 40, '85,130,180') }}>
|
||||
${Math.round(r.va * 2.237)}${r.gust != null && r.gust > r.va + 0.5
|
||||
? (gm => html`<span style=${{ marginLeft: '4px', fontWeight: gm >= 25 ? 700 : 'normal', opacity: gm >= 25 ? 1 : 0.65, color: gm >= 55 ? '#b81010' : gm >= 40 ? '#d44010' : gm >= 25 ? '#c47a00' : 'inherit' }}>(${Math.round(gm)})</span>`)(r.gust * 2.237)
|
||||
${Math.round(r.va * 2.237)}${u('mph')}${r.gust != null && r.gust > r.va + 0.5
|
||||
? (gm => html`<span style=${{ marginLeft: '4px', fontWeight: gm >= 25 ? 700 : 'normal', opacity: gm >= 25 ? 1 : 0.65, color: gm >= 55 ? '#b81010' : gm >= 40 ? '#d44010' : gm >= 25 ? '#c47a00' : 'inherit' }}>(${Math.round(gm)}${u('mph')})</span>`)(r.gust * 2.237)
|
||||
: ''}
|
||||
</td>`}
|
||||
${visibleCols.dir && html`<td class=${`utci-dir-cell ${groupStart('dir')}`}>
|
||||
@@ -739,15 +745,15 @@ ${isPro && (activeProfile === 'custom' || activeCols['utciP']) && html`<button c
|
||||
})()}
|
||||
${visibleCols.uvA && html`
|
||||
<td class=${groupStart('uvA')} style=${{ color: r.uvA > 0 ? '#c8922a' : '#4a3218', background: scaleBg(r.uvA, 0, 8, '220,155,40') }}>
|
||||
${r.uvA > 0 ? fmt(r.uvA) : '—'}
|
||||
${r.uvA > 0 ? fmt(r.uvA) + u(' idx') : '—'}
|
||||
</td>`}
|
||||
${visibleCols.uvB && html`
|
||||
<td class=${groupStart('uvB')} style=${{ color: r.uvB > 0 ? '#c44a3a' : '#4a3218', background: scaleBg(r.uvB, 0, 1.2, '210,70,50') }}>
|
||||
${r.uvB > 0 ? fmt(r.uvB, 2) : '—'}
|
||||
${r.uvB > 0 ? fmt(r.uvB, 2) + u(' idx') : '—'}
|
||||
</td>`}
|
||||
${visibleCols.sun && html`<td class=${groupStart('sun')} style=${{ background: scaleBg(r.elev > 0 ? r.elev : null, 0, 70, '225,160,45') }}>${r.elev > 0 ? fmt(r.elev) + deg : '—'}</td>`}
|
||||
${visibleCols.direct && html`<td class=${groupStart('direct')} style=${{ background: scaleBg(r.dir, 0, 850, '230,155,35') }}>${Math.round(r.dir)}</td>`}
|
||||
${visibleCols.diffuse && html`<td class=${groupStart('diffuse')} style=${{ background: scaleBg(r.dif, 0, 450, '230,190,70') }}>${Math.round(r.dif)}</td>`}
|
||||
${visibleCols.sun && html`<td class=${groupStart('sun')} style=${{ background: scaleBg(r.elev > 0 ? r.elev : null, 0, 70, '225,160,45') }}>${r.elev > 0 ? fmt(r.elev) + u('°') : '—'}</td>`}
|
||||
${visibleCols.direct && html`<td class=${groupStart('direct')} style=${{ background: scaleBg(r.dir, 0, 850, '230,155,35') }}>${Math.round(r.dir)}${u('W/m²')}</td>`}
|
||||
${visibleCols.diffuse && html`<td class=${groupStart('diffuse')} style=${{ background: scaleBg(r.dif, 0, 450, '230,190,70') }}>${Math.round(r.dif)}${u('W/m²')}</td>`}
|
||||
</tr>`;
|
||||
})}
|
||||
</tbody>
|
||||
@@ -904,7 +910,7 @@ ${isPro && (activeProfile === 'custom' || activeCols['utciP']) && html`<button c
|
||||
</div>
|
||||
|
||||
<footer class="utci-site-footer">
|
||||
© 2026 <a href="https://fraxle.net" target="_blank" rel="noopener noreferrer">Fraxle.NET</a>
|
||||
© 2026 <a href="https://fraxle.net" target="_blank" rel="noopener noreferrer">Fraxle.NET</a>
|
||||
· <a href="./index.html">Forecast</a>
|
||||
· <a href="./about.html">About</a>
|
||||
· <a href="./faq.html">FAQ</a>
|
||||
|
||||
@@ -39,7 +39,7 @@ const html = htm.bind(h);
|
||||
// groupedLeft - bool - fuse right side with a VentPill
|
||||
// isLastChild - bool - restore right border-radius when no sibling follows
|
||||
// -------------------------------------------------------------------
|
||||
export function CustomSelect({ value, options, onChange, hideLabel, hidingLabel, buttonLabel, isOn, noHide, groupedLeft, isLastChild }) {
|
||||
export function CustomSelect({ value, options, onChange, hideLabel, hidingLabel, buttonLabel, isOn, noHide, groupedLeft, isLastChild, grpClass }) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const wrapRef = useRef(null);
|
||||
|
||||
@@ -68,6 +68,7 @@ export function CustomSelect({ value, options, onChange, hideLabel, hidingLabel,
|
||||
|
||||
const btnClass = [
|
||||
'cs-btn',
|
||||
grpClass || '',
|
||||
isOn ? 'on' : '',
|
||||
groupedLeft ? 'grouped-left' : '',
|
||||
(groupedLeft && isLastChild) ? 'last-child' : '',
|
||||
@@ -120,9 +121,9 @@ export function CustomSelect({ value, options, onChange, hideLabel, hidingLabel,
|
||||
// label - string
|
||||
// title - tooltip string
|
||||
// -------------------------------------------------------------------
|
||||
export function VentPill({ checked, onChange, label, title }) {
|
||||
export function VentPill({ checked, onChange, label, title, grpClass }) {
|
||||
return html`
|
||||
<label class=${`cs-vent${checked ? ' on' : ''}`} title=${title}>
|
||||
<label class=${[`cs-vent`, grpClass || '', checked ? 'on' : ''].filter(Boolean).join(' ')} title=${title}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked=${checked}
|
||||
|
||||
+10
-30
@@ -56,38 +56,18 @@ export const FILTER_PROFILES = {
|
||||
proOnly: true,
|
||||
cols: { hour: true, air: true, rh: false, dew: false, wind: false, dir: false, cloud: false, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: false, utciP: true, precip: false, precipProb: false, soilT: true, soilT6: false, soilM: false, concreteT: true, vehicleT: true, indoorT: true, managedT: true, vis: false, aqi: false, pollen: false },
|
||||
},
|
||||
custom: {
|
||||
label: 'Custom',
|
||||
showall: {
|
||||
label: 'Show All',
|
||||
icon: '⚙️',
|
||||
proOnly: true,
|
||||
cols: { hour: true, air: true, rh: true, dew: true, wind: true, dir: true, cloud: true, sun: true, direct: true, diffuse: true, tmrt: true, delta: true, utci: true, uvA: true, uvB: true, burn: true, utciP: true, precip: true, precipProb: true, soilT: true, soilT6: true, soilM: true, concreteT: true, vehicleT: true, indoorT: true, managedT: true, vis: true, aqi: true, pollen: true },
|
||||
// -- FUTURE FEATURE v2: Saved Custom Profiles (Pro) -----------------------
|
||||
// Expand 'Custom' into a fully user-owned profile system. Pro users can:
|
||||
//
|
||||
// - CREATE named profiles - give them a name and icon, choose any columns
|
||||
// - SAVE multiple profiles - stored in localStorage (or user account if we
|
||||
// add auth), each appearing as an extra pill in the profile button bar
|
||||
// - REORDER columns - drag-and-drop within the custom profile editor.
|
||||
// Column order is just an array of keys; shuffle the array, re-render.
|
||||
// The existing col visibility flags stay, reordering is a separate
|
||||
// 'colOrder: ['hour', 'air', 'wind', ...]' array on the profile object.
|
||||
// - DELETE / RENAME profiles in a small management modal
|
||||
//
|
||||
// The 'Custom' button becomes "- New Profile" when in profile-creation mode.
|
||||
// Existing preset profiles (Basic, Home, Vehicle-) remain read-only.
|
||||
//
|
||||
// Data shape per saved profile:
|
||||
// {
|
||||
// id: 'profile_abc123', // generated uuid
|
||||
// label: 'My Beach Days',
|
||||
// icon: '--', // user picks from a small emoji set
|
||||
// cols: { ...standard col flags },
|
||||
// colOrder: ['hour', 'air', 'burn', 'wind', ...], // user's preferred order
|
||||
// createdAt: ISO string,
|
||||
// }
|
||||
//
|
||||
// Storage: JSON.stringify array in localStorage under 'sunscope_custom_profiles'.
|
||||
// -----------------------------------------------------------------------------
|
||||
},
|
||||
custom: {
|
||||
label: 'Custom',
|
||||
icon: '✏️',
|
||||
proOnly: true,
|
||||
// Blank slate - only Hour is on. User enables whichever columns they want.
|
||||
cols: { hour: true, air: false, rh: false, dew: false, wind: false, dir: false, cloud: false, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: false, uvB: false, burn: false, utciP: false, precip: false, precipProb: false, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false, vis: false, aqi: false, pollen: false },
|
||||
},
|
||||
};
|
||||
|
||||
@@ -128,7 +108,7 @@ export const POLLEN_TYPES = {
|
||||
};
|
||||
|
||||
// Left-to-right order of the profile buttons in the top filter bar.
|
||||
export const profileButtonOrder = ['basic', 'home', 'vehicle', 'alltemps', 'custom'];
|
||||
export const profileButtonOrder = ['basic', 'home', 'vehicle', 'alltemps', 'showall', 'custom'];
|
||||
|
||||
// Emoji glyph per place/activity variant.
|
||||
export const variantIcons = {
|
||||
|
||||
@@ -134,7 +134,7 @@ export function useAppState() {
|
||||
?? FILTER_PROFILES.outdoors.cols;
|
||||
return { ...variantCols };
|
||||
}
|
||||
// For 'custom' profile, always use the configured custom cols (all 25 columns)
|
||||
// For custom profile, load from config - blank slate with only Hour on.
|
||||
if (saved === 'custom') {
|
||||
return { ...FILTER_PROFILES.custom?.cols ?? FILTER_PROFILES.basic.cols };
|
||||
}
|
||||
@@ -154,7 +154,7 @@ export function useAppState() {
|
||||
setIndoorMode(hasIndoor ? 'on' : 'off');
|
||||
setIndoorManaged(false);
|
||||
} else {
|
||||
// Custom profile ALWAYS initializes from config - with all 25 columns active
|
||||
// Custom profile initializes from config - blank slate, user picks columns.
|
||||
const customCols = FILTER_PROFILES.custom?.cols;
|
||||
if (customCols) {
|
||||
setVisibleCols({ ...customCols });
|
||||
@@ -217,16 +217,16 @@ export function useAppState() {
|
||||
return next;
|
||||
});
|
||||
|
||||
const [showDegree, setShowDegree] = useState(() => {
|
||||
const [showUnits, setShowUnits] = useState(() => {
|
||||
try {
|
||||
const s = localStorage.getItem('sunscope_show_degree');
|
||||
const s = localStorage.getItem('sunscope_show_units');
|
||||
if (s !== null) return s !== '0';
|
||||
return typeof window !== 'undefined' ? window.innerWidth >= 640 : true;
|
||||
} catch (e) { return true; }
|
||||
});
|
||||
const toggleShowDegree = () => setShowDegree(v => {
|
||||
const toggleShowUnits = () => setShowUnits(v => {
|
||||
const next = !v;
|
||||
try { localStorage.setItem('sunscope_show_degree', next ? '1' : '0'); } catch (e) { /* ignore */ }
|
||||
try { localStorage.setItem('sunscope_show_units', next ? '1' : '0'); } catch (e) { /* ignore */ }
|
||||
return next;
|
||||
});
|
||||
|
||||
@@ -452,7 +452,7 @@ export function useAppState() {
|
||||
indoorMode, setIndoorMode,
|
||||
pollenType, setPollenTypeAndSave,
|
||||
showDecimals, toggleShowDecimals,
|
||||
showDegree, toggleShowDegree,
|
||||
showUnits, toggleShowUnits,
|
||||
// table refs
|
||||
headStickyRef, headTrackRef, headTableRef,
|
||||
bodyScrollRef, bodyTableRef, tableWrapRef,
|
||||
|
||||
Reference in New Issue
Block a user