mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-01 20:29:00 +00:00
feat: add critical settings help content
Add the agreed Party 1 help controls to general, space, marker and device-catalog settings in all four locales, including cold onboarding parity and regression coverage. Issue: #86 User-Visible: yes
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"schema": 1,
|
||||
<<<<<<< HEAD
|
||||
"fingerprint": "88a6e19b99c65848b1132de49a50a7d9214b7d4c077dbd83e9cbda0c21b27d3b",
|
||||
"entry": "houseplan-card.js",
|
||||
"initialViewFiles": [
|
||||
@@ -41,19 +42,70 @@
|
||||
"isEntry": false,
|
||||
"imports": [
|
||||
"houseplan-assets/houseplan-card-DR7nMAa_.js"
|
||||
=======
|
||||
"fingerprint": "ef677d5cdeb6a192fb365bc296170e7d5ffab5fddb8a5d91e7fd0e42403f6f47",
|
||||
"entry": "houseplan-card.js",
|
||||
"initialViewFiles": [
|
||||
"houseplan-assets/houseplan-card-BNqrY9Pv.js",
|
||||
"houseplan-card.js"
|
||||
],
|
||||
"initialViewGzipBytes": 280311,
|
||||
"lazyFiles": [
|
||||
"houseplan-assets/backdrop-pick-CuKzg7Xb.js",
|
||||
"houseplan-assets/de-aSw1c0jr.js",
|
||||
"houseplan-assets/editor-BZmLvR26.js",
|
||||
"houseplan-assets/fr-B0cHXK43.js",
|
||||
"houseplan-assets/houseplan-editor-runtime-DTu6GIyL.js",
|
||||
"houseplan-assets/houseplan-onboarding-runtime-D_gZwBXA.js"
|
||||
],
|
||||
"lazyGzipBytes": 195871,
|
||||
"lazyEditorFiles": [
|
||||
"houseplan-assets/backdrop-pick-CuKzg7Xb.js",
|
||||
"houseplan-assets/editor-BZmLvR26.js",
|
||||
"houseplan-assets/houseplan-editor-runtime-DTu6GIyL.js"
|
||||
],
|
||||
"lazyEditorGzipBytes": 142546,
|
||||
"lazyOnboardingFiles": [
|
||||
"houseplan-assets/backdrop-pick-CuKzg7Xb.js",
|
||||
"houseplan-assets/houseplan-onboarding-runtime-D_gZwBXA.js"
|
||||
],
|
||||
"lazyOnboardingGzipBytes": 13789,
|
||||
"lazyLocaleFiles": [
|
||||
"houseplan-assets/de-aSw1c0jr.js",
|
||||
"houseplan-assets/fr-B0cHXK43.js"
|
||||
],
|
||||
"lazyLocaleGzipBytes": 46606,
|
||||
"files": [
|
||||
{
|
||||
"path": "houseplan-assets/backdrop-pick-CuKzg7Xb.js",
|
||||
"sha256": "f206cb26949def5617aca34876eb118ead1dd73096f6448e2952112e4a8b2322",
|
||||
"rawBytes": 20636,
|
||||
"gzipBytes": 7070,
|
||||
"isEntry": false,
|
||||
"imports": [
|
||||
"houseplan-assets/houseplan-card-BNqrY9Pv.js"
|
||||
>>>>>>> 30df567d (feat: add critical settings help content)
|
||||
],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
"path": "houseplan-assets/de-B-stL9mL.js",
|
||||
"sha256": "16bd18e83158ca3d35ea4132a9300039d1c8d6bc7642a95115ddf1dba6265ede",
|
||||
"rawBytes": 76237,
|
||||
"gzipBytes": 23178,
|
||||
=======
|
||||
"path": "houseplan-assets/de-aSw1c0jr.js",
|
||||
"sha256": "950bae213e009cbe3616ce860a00a38dca38b6668a5267c341ff2aa9521e0a82",
|
||||
"rawBytes": 77607,
|
||||
"gzipBytes": 23535,
|
||||
>>>>>>> 30df567d (feat: add critical settings help content)
|
||||
"isEntry": false,
|
||||
"imports": [],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
"path": "houseplan-assets/editor-Cm8lkf2a.js",
|
||||
"sha256": "d38328e9559875eb4ba650e7f939cb81e4d9e93b70eafcc4b2348693344afdc7",
|
||||
"rawBytes": 3831,
|
||||
@@ -61,19 +113,36 @@
|
||||
"isEntry": false,
|
||||
"imports": [
|
||||
"houseplan-assets/houseplan-card-DR7nMAa_.js"
|
||||
=======
|
||||
"path": "houseplan-assets/editor-BZmLvR26.js",
|
||||
"sha256": "da07c62693624372584aae3142bdde710687b98571d97bfeb7dfb88a224fa9df",
|
||||
"rawBytes": 3826,
|
||||
"gzipBytes": 1581,
|
||||
"isEntry": false,
|
||||
"imports": [
|
||||
"houseplan-assets/houseplan-card-BNqrY9Pv.js"
|
||||
>>>>>>> 30df567d (feat: add critical settings help content)
|
||||
],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
"path": "houseplan-assets/fr-DosWl8Ak.js",
|
||||
"sha256": "b795363b2ada632fd7f79798152b9b4586f3310641ab7de7789dfac8d31eab70",
|
||||
"rawBytes": 78415,
|
||||
"gzipBytes": 22713,
|
||||
=======
|
||||
"path": "houseplan-assets/fr-B0cHXK43.js",
|
||||
"sha256": "552c4dea67f2d56303eb0643bc7702c9733c1ea00187f837ff3ad88c101574ad",
|
||||
"rawBytes": 79750,
|
||||
"gzipBytes": 23071,
|
||||
>>>>>>> 30df567d (feat: add critical settings help content)
|
||||
"isEntry": false,
|
||||
"imports": [],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
"path": "houseplan-assets/houseplan-card-DR7nMAa_.js",
|
||||
"sha256": "73bb53ca51571acec2596bee21c05698d86455b05ab351767f0b76f19ccb76ab",
|
||||
"rawBytes": 985833,
|
||||
@@ -97,10 +166,36 @@
|
||||
"imports": [
|
||||
"houseplan-assets/backdrop-pick-CY3bq28R.js",
|
||||
"houseplan-assets/houseplan-card-DR7nMAa_.js"
|
||||
=======
|
||||
"path": "houseplan-assets/houseplan-card-BNqrY9Pv.js",
|
||||
"sha256": "62fda34044e8a75ba084411949dbc47094e0767e75e8d1cd93a197c8e719fb23",
|
||||
"rawBytes": 988826,
|
||||
"gzipBytes": 279515,
|
||||
"isEntry": false,
|
||||
"imports": [],
|
||||
"dynamicImports": [
|
||||
"houseplan-assets/de-aSw1c0jr.js",
|
||||
"houseplan-assets/editor-BZmLvR26.js",
|
||||
"houseplan-assets/fr-B0cHXK43.js",
|
||||
"houseplan-assets/houseplan-editor-runtime-DTu6GIyL.js",
|
||||
"houseplan-assets/houseplan-onboarding-runtime-D_gZwBXA.js"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "houseplan-assets/houseplan-editor-runtime-DTu6GIyL.js",
|
||||
"sha256": "2247306357d692f09bb8f24d8cb1079625ff24a6b3daa105c628f954b6fe40f9",
|
||||
"rawBytes": 517847,
|
||||
"gzipBytes": 133895,
|
||||
"isEntry": false,
|
||||
"imports": [
|
||||
"houseplan-assets/backdrop-pick-CuKzg7Xb.js",
|
||||
"houseplan-assets/houseplan-card-BNqrY9Pv.js"
|
||||
>>>>>>> 30df567d (feat: add critical settings help content)
|
||||
],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
"path": "houseplan-assets/houseplan-onboarding-runtime-CWRuFlaF.js",
|
||||
"sha256": "8df13ba33ec7e1e83eb054ea8b66a25456e384d4a5e0be57f470241fb6f55fbc",
|
||||
"rawBytes": 26195,
|
||||
@@ -109,17 +204,35 @@
|
||||
"imports": [
|
||||
"houseplan-assets/backdrop-pick-CY3bq28R.js",
|
||||
"houseplan-assets/houseplan-card-DR7nMAa_.js"
|
||||
=======
|
||||
"path": "houseplan-assets/houseplan-onboarding-runtime-D_gZwBXA.js",
|
||||
"sha256": "831bb3e83b75a8c424a45910a87647981ec0b9061078ba33ccd074ad2cb8ce89",
|
||||
"rawBytes": 27120,
|
||||
"gzipBytes": 6719,
|
||||
"isEntry": false,
|
||||
"imports": [
|
||||
"houseplan-assets/backdrop-pick-CuKzg7Xb.js",
|
||||
"houseplan-assets/houseplan-card-BNqrY9Pv.js"
|
||||
>>>>>>> 30df567d (feat: add critical settings help content)
|
||||
],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
"path": "houseplan-card.js",
|
||||
<<<<<<< HEAD
|
||||
"sha256": "12e0e5704282fe9af4546c9f3b6a8ee697b87747ad8425d6e8e4b8340cb3df9a",
|
||||
=======
|
||||
"sha256": "3b84719bd1f458e24e2deb0dbfd74ea3ee41afaf134f3b077f3e53b1cbeee982",
|
||||
>>>>>>> 30df567d (feat: add critical settings help content)
|
||||
"rawBytes": 1183,
|
||||
"gzipBytes": 795,
|
||||
"gzipBytes": 796,
|
||||
"isEntry": true,
|
||||
"imports": [
|
||||
<<<<<<< HEAD
|
||||
"houseplan-assets/houseplan-card-DR7nMAa_.js"
|
||||
=======
|
||||
"houseplan-assets/houseplan-card-BNqrY9Pv.js"
|
||||
>>>>>>> 30df567d (feat: add critical settings help content)
|
||||
],
|
||||
"dynamicImports": []
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,14 @@
|
||||
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="ef677d5cdeb6a192fb365bc296170e7d5ffab5fddb8a5d91e7fd0e42403f6f47";import{b as e,l as o,t,d3 as s,A as a,d4 as i,d5 as l,d6 as n,E as r,c}from"./houseplan-card-BNqrY9Pv.js";class f extends e{constructor(){super(...arguments),this._spaces=null,this._spacesLoading=!1,this._spacesAuthoritative=!1}setConfig(e){this._config=e}async _loadSpaces(){if(!this._spaces&&!this._spacesLoading&&this.hass){this._spacesLoading=!0;try{const e=await this.hass.callWS({type:"houseplan/config/get"});this._spaces=(e?.config?.spaces||[]).map(e=>({value:e.id,label:e.title||e.id})),this._spacesAuthoritative=!0}catch{this._spaces=[],this._spacesAuthoritative=!1}finally{this._spacesLoading=!1}}}get _lang(){return o(this.hass,this._config?.language)}get _floorToken(){const e=this._config?.floor;return"number"==typeof e?`__houseplan_yaml_floor_index__:${String(e)}`:null}get _formData(){const e={...this._config},o=this._floorToken;return o?e.floor=o:Object.prototype.hasOwnProperty.call(e,"floor")||(e.floor=""),e}get _schema(){const e=this._spaces||[],o=this._lang,a=[{value:"",label:t(o,"editor.floor_none")}],i=this._floorToken;i&&a.push({value:i,label:t(o,"editor.floor_index",{index:String(this._config?.floor)})});const l="string"==typeof this._config?.floor?this._config.floor:"";l&&!e.some(e=>e.value===l)&&a.push({value:l,label:l}),a.push(...e);const n="string"==typeof this._config?.default_floor?this._config.default_floor:"",r=[...e];return n&&!e.some(e=>e.value===n)&&r.unshift({value:n,label:n}),[{name:"title",selector:{text:{}}},{name:"floor",selector:{select:{mode:"dropdown",options:a}}},e.length?{name:"default_floor",selector:{select:{mode:"dropdown",options:r}}}:{name:"default_floor",selector:{text:{}}},{name:"language",selector:{select:{mode:"dropdown",options:s(t(o,"editor.lang_auto"),this._config?.language)}}},{name:"icon_size",selector:{number:{min:1,max:6,step:.1,mode:"box"}}},{name:"show_temperature",selector:{boolean:{}}},{name:"live_states",selector:{boolean:{}}},{name:"show_signal",selector:{boolean:{}}},{name:"kiosk",selector:{boolean:{}}},{name:"cycle",selector:{number:{min:0,max:3600,step:5,mode:"box"}}}]}render(){if(!this.hass||!this._config)return a;const e=i(this,l,o(this.hass,this._config.language));if("cold"===e)return n();if("warm"===e)return r;this._loadSpaces();const s=this._lang,f={title:t(s,"editor.title"),floor:t(s,"editor.floor"),default_floor:t(s,"editor.default_floor"),language:t(s,"editor.language"),icon_size:t(s,"editor.icon_size"),show_temperature:t(s,"editor.show_temperature"),live_states:t(s,"editor.live_states"),show_signal:t(s,"editor.show_signal"),kiosk:t(s,"editor.kiosk"),cycle:t(s,"editor.cycle")},h=this._schema,_=function(e,o,t){if(!t||null===o)return null;const s="string"==typeof e?.default_floor?e.default_floor:"";return!s||o.some(e=>e.value===s)?null:s}(this._config,this._spaces,this._spacesAuthoritative),d=e=>c`<ha-form
|
||||
.hass=${this.hass}
|
||||
.data=${this._formData}
|
||||
.schema=${e}
|
||||
.computeLabel=${e=>f[e.name]||e.name}
|
||||
@value-changed=${this._valueChanged}
|
||||
></ha-form>`;return c`
|
||||
${d(h.slice(0,3))}
|
||||
${_?c`<div class="default-floor-error" role="alert"
|
||||
style="color:var(--error-color,#db4437);margin:-4px 0 12px;overflow-wrap:anywhere">
|
||||
${t(s,"editor.default_floor_missing",{id:_})}
|
||||
</div>`:a}
|
||||
${d(h.slice(3))}
|
||||
`}_valueChanged(e){const o={...this._config,...e.detail.value};""===o.floor?delete o.floor:o.floor===this._floorToken&&(o.floor=this._config?.floor);const t=new Event("config-changed",{bubbles:!0,composed:!0});t.detail={config:o},this.dispatchEvent(t)}}f.properties={hass:{attribute:!1},_config:{state:!0},_spaces:{state:!0}},customElements.get("houseplan-card-editor")||customElements.define("houseplan-card-editor",f);
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+658
-402
File diff suppressed because one or more lines are too long
+2938
File diff suppressed because one or more lines are too long
+78
-54
File diff suppressed because one or more lines are too long
+241
File diff suppressed because one or more lines are too long
@@ -1 +1,5 @@
|
||||
<<<<<<< HEAD
|
||||
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="88a6e19b99c65848b1132de49a50a7d9214b7d4c077dbd83e9cbda0c21b27d3b";try{await import("./houseplan-assets/houseplan-card-DR7nMAa_.js")}catch(e){if(!customElements.get("houseplan-card")){const l=String(navigator.language||"en").toLowerCase();const m=l.startsWith("ru")?"House Plan обновился — перезагрузите страницу (Ctrl+F5).":l.startsWith("de")?"House Plan wurde aktualisiert — bitte laden Sie die Seite neu (Strg+F5).":l.startsWith("fr")?"House Plan a été mis à jour — veuillez recharger la page (Ctrl+F5).":"House Plan was updated — please reload the page (Ctrl+F5).";customElements.define("houseplan-card",class extends HTMLElement{setConfig(){}getCardSize(){return 1}connectedCallback(){this.style.cssText="display:block;box-sizing:border-box;padding:16px;border:1px solid var(--divider-color,#e0e0e0);border-radius:var(--ha-card-border-radius,12px);background:var(--card-background-color,#fff);color:var(--primary-text-color,#212121);font:14px/1.4 var(--paper-font-body1_-_font-family,sans-serif)";this.textContent=m}})}console.error("[houseplan] stale entry: the main chunk is unavailable",e)}
|
||||
=======
|
||||
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="ef677d5cdeb6a192fb365bc296170e7d5ffab5fddb8a5d91e7fd0e42403f6f47";try{await import("./houseplan-assets/houseplan-card-BNqrY9Pv.js")}catch(e){if(!customElements.get("houseplan-card")){const l=String(navigator.language||"en").toLowerCase();const m=l.startsWith("ru")?"House Plan обновился — перезагрузите страницу (Ctrl+F5).":l.startsWith("de")?"House Plan wurde aktualisiert — bitte laden Sie die Seite neu (Strg+F5).":l.startsWith("fr")?"House Plan a été mis à jour — veuillez recharger la page (Ctrl+F5).":"House Plan was updated — please reload the page (Ctrl+F5).";customElements.define("houseplan-card",class extends HTMLElement{setConfig(){}getCardSize(){return 1}connectedCallback(){this.style.cssText="display:block;box-sizing:border-box;padding:16px;border:1px solid var(--divider-color,#e0e0e0);border-radius:var(--ha-card-border-radius,12px);background:var(--card-background-color,#fff);color:var(--primary-text-color,#212121);font:14px/1.4 var(--paper-font-body1_-_font-family,sans-serif)";this.textContent=m}})}console.error("[houseplan] stale entry: the main chunk is unavailable",e)}
|
||||
>>>>>>> 30df567d (feat: add critical settings help content)
|
||||
|
||||
@@ -252,6 +252,74 @@ const res = await page.evaluate(async () => {
|
||||
await card.updateComplete;
|
||||
out.secondEscapeClosesDialog = !card._markerDialog;
|
||||
|
||||
// #86 Party 1: all general-settings placements are real help controls and
|
||||
// opening one of them cannot mutate its associated setting.
|
||||
card._openSettingsDialog();
|
||||
await card.updateComplete;
|
||||
const generalKeys = ['gs.glow_radius.help', 'gs.bg_mode.help', 'gs.north.help'];
|
||||
out.party1GeneralInventory = generalKeys.every((key) => !!helpButton(key));
|
||||
const generalBefore = JSON.stringify({
|
||||
glowRadius: card._settingsDialog?.glowRadius,
|
||||
bgMode: card._settingsDialog?.bgMode,
|
||||
northDeg: card._settingsDialog?.northDeg,
|
||||
});
|
||||
helpButton('gs.bg_mode.help')?.click();
|
||||
await frame();
|
||||
out.party1GeneralHelpIsReadOnly = generalBefore === JSON.stringify({
|
||||
glowRadius: card._settingsDialog?.glowRadius,
|
||||
bgMode: card._settingsDialog?.bgMode,
|
||||
northDeg: card._settingsDialog?.northDeg,
|
||||
});
|
||||
card._settingsDialog = null;
|
||||
card.requestUpdate();
|
||||
await card.updateComplete;
|
||||
|
||||
// The regular editor and cold-install onboarding render separate space
|
||||
// dialog templates; this smoke covers the editor copy while the source/i18n
|
||||
// contract covers both implementations.
|
||||
card._openSpaceDialog('edit', card._space);
|
||||
await card.updateComplete;
|
||||
const spaceKeys = [
|
||||
'space.cell_cm.help', 'space.zero_wall_style.help', 'space.bg_mode.help',
|
||||
'space.north.help', 'space.fill_mode.help',
|
||||
];
|
||||
out.party1SpaceInventory = spaceKeys.every((key) => !!helpButton(key));
|
||||
const spaceBefore = JSON.stringify({
|
||||
cellCm: card._spaceDialog?.cellCm,
|
||||
zeroWallStyle: card._spaceDialog?.zeroWallStyle,
|
||||
bgMode: card._spaceDialog?.bgMode,
|
||||
northDeg: card._spaceDialog?.northDeg,
|
||||
fillMode: card._spaceDialog?.fillMode,
|
||||
});
|
||||
helpButton('space.zero_wall_style.help')?.click();
|
||||
await frame();
|
||||
out.party1SpaceHelpIsReadOnly = spaceBefore === JSON.stringify({
|
||||
cellCm: card._spaceDialog?.cellCm,
|
||||
zeroWallStyle: card._spaceDialog?.zeroWallStyle,
|
||||
bgMode: card._spaceDialog?.bgMode,
|
||||
northDeg: card._spaceDialog?.northDeg,
|
||||
fillMode: card._spaceDialog?.fillMode,
|
||||
});
|
||||
card._spaceDialog = null;
|
||||
card.requestUpdate();
|
||||
await card.updateComplete;
|
||||
|
||||
card._openDeviceInbox();
|
||||
await card.updateComplete;
|
||||
const hiddenBefore = card._showHidden;
|
||||
const hiddenHelpButton = helpButton('device_inbox.show_hidden.help');
|
||||
hiddenHelpButton?.click();
|
||||
await frame();
|
||||
const hiddenSurface = helpSurface('device_inbox.show_hidden.help');
|
||||
const hiddenBox = hiddenSurface?.getBoundingClientRect();
|
||||
out.party1ShowHiddenHelpIsReadOnly = !!hiddenHelpButton
|
||||
&& card._showHidden === hiddenBefore;
|
||||
out.party1ShowHiddenHelpInsideNarrowViewport = !!hiddenBox
|
||||
&& hiddenBox.left >= (visualViewport?.offsetLeft || 0)
|
||||
&& hiddenBox.top >= (visualViewport?.offsetTop || 0)
|
||||
&& hiddenBox.right <= (visualViewport?.offsetLeft || 0) + (visualViewport?.width || innerWidth)
|
||||
&& hiddenBox.bottom <= (visualViewport?.offsetTop || 0) + (visualViewport?.height || innerHeight);
|
||||
|
||||
return out;
|
||||
});
|
||||
|
||||
|
||||
Vendored
+114
-1
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"schema": 1,
|
||||
<<<<<<< HEAD
|
||||
"fingerprint": "88a6e19b99c65848b1132de49a50a7d9214b7d4c077dbd83e9cbda0c21b27d3b",
|
||||
"entry": "houseplan-card.js",
|
||||
"initialViewFiles": [
|
||||
@@ -41,19 +42,70 @@
|
||||
"isEntry": false,
|
||||
"imports": [
|
||||
"houseplan-assets/houseplan-card-DR7nMAa_.js"
|
||||
=======
|
||||
"fingerprint": "ef677d5cdeb6a192fb365bc296170e7d5ffab5fddb8a5d91e7fd0e42403f6f47",
|
||||
"entry": "houseplan-card.js",
|
||||
"initialViewFiles": [
|
||||
"houseplan-assets/houseplan-card-BNqrY9Pv.js",
|
||||
"houseplan-card.js"
|
||||
],
|
||||
"initialViewGzipBytes": 280311,
|
||||
"lazyFiles": [
|
||||
"houseplan-assets/backdrop-pick-CuKzg7Xb.js",
|
||||
"houseplan-assets/de-aSw1c0jr.js",
|
||||
"houseplan-assets/editor-BZmLvR26.js",
|
||||
"houseplan-assets/fr-B0cHXK43.js",
|
||||
"houseplan-assets/houseplan-editor-runtime-DTu6GIyL.js",
|
||||
"houseplan-assets/houseplan-onboarding-runtime-D_gZwBXA.js"
|
||||
],
|
||||
"lazyGzipBytes": 195871,
|
||||
"lazyEditorFiles": [
|
||||
"houseplan-assets/backdrop-pick-CuKzg7Xb.js",
|
||||
"houseplan-assets/editor-BZmLvR26.js",
|
||||
"houseplan-assets/houseplan-editor-runtime-DTu6GIyL.js"
|
||||
],
|
||||
"lazyEditorGzipBytes": 142546,
|
||||
"lazyOnboardingFiles": [
|
||||
"houseplan-assets/backdrop-pick-CuKzg7Xb.js",
|
||||
"houseplan-assets/houseplan-onboarding-runtime-D_gZwBXA.js"
|
||||
],
|
||||
"lazyOnboardingGzipBytes": 13789,
|
||||
"lazyLocaleFiles": [
|
||||
"houseplan-assets/de-aSw1c0jr.js",
|
||||
"houseplan-assets/fr-B0cHXK43.js"
|
||||
],
|
||||
"lazyLocaleGzipBytes": 46606,
|
||||
"files": [
|
||||
{
|
||||
"path": "houseplan-assets/backdrop-pick-CuKzg7Xb.js",
|
||||
"sha256": "f206cb26949def5617aca34876eb118ead1dd73096f6448e2952112e4a8b2322",
|
||||
"rawBytes": 20636,
|
||||
"gzipBytes": 7070,
|
||||
"isEntry": false,
|
||||
"imports": [
|
||||
"houseplan-assets/houseplan-card-BNqrY9Pv.js"
|
||||
>>>>>>> 30df567d (feat: add critical settings help content)
|
||||
],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
"path": "houseplan-assets/de-B-stL9mL.js",
|
||||
"sha256": "16bd18e83158ca3d35ea4132a9300039d1c8d6bc7642a95115ddf1dba6265ede",
|
||||
"rawBytes": 76237,
|
||||
"gzipBytes": 23178,
|
||||
=======
|
||||
"path": "houseplan-assets/de-aSw1c0jr.js",
|
||||
"sha256": "950bae213e009cbe3616ce860a00a38dca38b6668a5267c341ff2aa9521e0a82",
|
||||
"rawBytes": 77607,
|
||||
"gzipBytes": 23535,
|
||||
>>>>>>> 30df567d (feat: add critical settings help content)
|
||||
"isEntry": false,
|
||||
"imports": [],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
"path": "houseplan-assets/editor-Cm8lkf2a.js",
|
||||
"sha256": "d38328e9559875eb4ba650e7f939cb81e4d9e93b70eafcc4b2348693344afdc7",
|
||||
"rawBytes": 3831,
|
||||
@@ -61,19 +113,36 @@
|
||||
"isEntry": false,
|
||||
"imports": [
|
||||
"houseplan-assets/houseplan-card-DR7nMAa_.js"
|
||||
=======
|
||||
"path": "houseplan-assets/editor-BZmLvR26.js",
|
||||
"sha256": "da07c62693624372584aae3142bdde710687b98571d97bfeb7dfb88a224fa9df",
|
||||
"rawBytes": 3826,
|
||||
"gzipBytes": 1581,
|
||||
"isEntry": false,
|
||||
"imports": [
|
||||
"houseplan-assets/houseplan-card-BNqrY9Pv.js"
|
||||
>>>>>>> 30df567d (feat: add critical settings help content)
|
||||
],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
"path": "houseplan-assets/fr-DosWl8Ak.js",
|
||||
"sha256": "b795363b2ada632fd7f79798152b9b4586f3310641ab7de7789dfac8d31eab70",
|
||||
"rawBytes": 78415,
|
||||
"gzipBytes": 22713,
|
||||
=======
|
||||
"path": "houseplan-assets/fr-B0cHXK43.js",
|
||||
"sha256": "552c4dea67f2d56303eb0643bc7702c9733c1ea00187f837ff3ad88c101574ad",
|
||||
"rawBytes": 79750,
|
||||
"gzipBytes": 23071,
|
||||
>>>>>>> 30df567d (feat: add critical settings help content)
|
||||
"isEntry": false,
|
||||
"imports": [],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
"path": "houseplan-assets/houseplan-card-DR7nMAa_.js",
|
||||
"sha256": "73bb53ca51571acec2596bee21c05698d86455b05ab351767f0b76f19ccb76ab",
|
||||
"rawBytes": 985833,
|
||||
@@ -97,10 +166,36 @@
|
||||
"imports": [
|
||||
"houseplan-assets/backdrop-pick-CY3bq28R.js",
|
||||
"houseplan-assets/houseplan-card-DR7nMAa_.js"
|
||||
=======
|
||||
"path": "houseplan-assets/houseplan-card-BNqrY9Pv.js",
|
||||
"sha256": "62fda34044e8a75ba084411949dbc47094e0767e75e8d1cd93a197c8e719fb23",
|
||||
"rawBytes": 988826,
|
||||
"gzipBytes": 279515,
|
||||
"isEntry": false,
|
||||
"imports": [],
|
||||
"dynamicImports": [
|
||||
"houseplan-assets/de-aSw1c0jr.js",
|
||||
"houseplan-assets/editor-BZmLvR26.js",
|
||||
"houseplan-assets/fr-B0cHXK43.js",
|
||||
"houseplan-assets/houseplan-editor-runtime-DTu6GIyL.js",
|
||||
"houseplan-assets/houseplan-onboarding-runtime-D_gZwBXA.js"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "houseplan-assets/houseplan-editor-runtime-DTu6GIyL.js",
|
||||
"sha256": "2247306357d692f09bb8f24d8cb1079625ff24a6b3daa105c628f954b6fe40f9",
|
||||
"rawBytes": 517847,
|
||||
"gzipBytes": 133895,
|
||||
"isEntry": false,
|
||||
"imports": [
|
||||
"houseplan-assets/backdrop-pick-CuKzg7Xb.js",
|
||||
"houseplan-assets/houseplan-card-BNqrY9Pv.js"
|
||||
>>>>>>> 30df567d (feat: add critical settings help content)
|
||||
],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
"path": "houseplan-assets/houseplan-onboarding-runtime-CWRuFlaF.js",
|
||||
"sha256": "8df13ba33ec7e1e83eb054ea8b66a25456e384d4a5e0be57f470241fb6f55fbc",
|
||||
"rawBytes": 26195,
|
||||
@@ -109,17 +204,35 @@
|
||||
"imports": [
|
||||
"houseplan-assets/backdrop-pick-CY3bq28R.js",
|
||||
"houseplan-assets/houseplan-card-DR7nMAa_.js"
|
||||
=======
|
||||
"path": "houseplan-assets/houseplan-onboarding-runtime-D_gZwBXA.js",
|
||||
"sha256": "831bb3e83b75a8c424a45910a87647981ec0b9061078ba33ccd074ad2cb8ce89",
|
||||
"rawBytes": 27120,
|
||||
"gzipBytes": 6719,
|
||||
"isEntry": false,
|
||||
"imports": [
|
||||
"houseplan-assets/backdrop-pick-CuKzg7Xb.js",
|
||||
"houseplan-assets/houseplan-card-BNqrY9Pv.js"
|
||||
>>>>>>> 30df567d (feat: add critical settings help content)
|
||||
],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
"path": "houseplan-card.js",
|
||||
<<<<<<< HEAD
|
||||
"sha256": "12e0e5704282fe9af4546c9f3b6a8ee697b87747ad8425d6e8e4b8340cb3df9a",
|
||||
=======
|
||||
"sha256": "3b84719bd1f458e24e2deb0dbfd74ea3ee41afaf134f3b077f3e53b1cbeee982",
|
||||
>>>>>>> 30df567d (feat: add critical settings help content)
|
||||
"rawBytes": 1183,
|
||||
"gzipBytes": 795,
|
||||
"gzipBytes": 796,
|
||||
"isEntry": true,
|
||||
"imports": [
|
||||
<<<<<<< HEAD
|
||||
"houseplan-assets/houseplan-card-DR7nMAa_.js"
|
||||
=======
|
||||
"houseplan-assets/houseplan-card-BNqrY9Pv.js"
|
||||
>>>>>>> 30df567d (feat: add critical settings help content)
|
||||
],
|
||||
"dynamicImports": []
|
||||
}
|
||||
|
||||
+155
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
+14
@@ -0,0 +1,14 @@
|
||||
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="ef677d5cdeb6a192fb365bc296170e7d5ffab5fddb8a5d91e7fd0e42403f6f47";import{b as e,l as o,t,d3 as s,A as a,d4 as i,d5 as l,d6 as n,E as r,c}from"./houseplan-card-BNqrY9Pv.js";class f extends e{constructor(){super(...arguments),this._spaces=null,this._spacesLoading=!1,this._spacesAuthoritative=!1}setConfig(e){this._config=e}async _loadSpaces(){if(!this._spaces&&!this._spacesLoading&&this.hass){this._spacesLoading=!0;try{const e=await this.hass.callWS({type:"houseplan/config/get"});this._spaces=(e?.config?.spaces||[]).map(e=>({value:e.id,label:e.title||e.id})),this._spacesAuthoritative=!0}catch{this._spaces=[],this._spacesAuthoritative=!1}finally{this._spacesLoading=!1}}}get _lang(){return o(this.hass,this._config?.language)}get _floorToken(){const e=this._config?.floor;return"number"==typeof e?`__houseplan_yaml_floor_index__:${String(e)}`:null}get _formData(){const e={...this._config},o=this._floorToken;return o?e.floor=o:Object.prototype.hasOwnProperty.call(e,"floor")||(e.floor=""),e}get _schema(){const e=this._spaces||[],o=this._lang,a=[{value:"",label:t(o,"editor.floor_none")}],i=this._floorToken;i&&a.push({value:i,label:t(o,"editor.floor_index",{index:String(this._config?.floor)})});const l="string"==typeof this._config?.floor?this._config.floor:"";l&&!e.some(e=>e.value===l)&&a.push({value:l,label:l}),a.push(...e);const n="string"==typeof this._config?.default_floor?this._config.default_floor:"",r=[...e];return n&&!e.some(e=>e.value===n)&&r.unshift({value:n,label:n}),[{name:"title",selector:{text:{}}},{name:"floor",selector:{select:{mode:"dropdown",options:a}}},e.length?{name:"default_floor",selector:{select:{mode:"dropdown",options:r}}}:{name:"default_floor",selector:{text:{}}},{name:"language",selector:{select:{mode:"dropdown",options:s(t(o,"editor.lang_auto"),this._config?.language)}}},{name:"icon_size",selector:{number:{min:1,max:6,step:.1,mode:"box"}}},{name:"show_temperature",selector:{boolean:{}}},{name:"live_states",selector:{boolean:{}}},{name:"show_signal",selector:{boolean:{}}},{name:"kiosk",selector:{boolean:{}}},{name:"cycle",selector:{number:{min:0,max:3600,step:5,mode:"box"}}}]}render(){if(!this.hass||!this._config)return a;const e=i(this,l,o(this.hass,this._config.language));if("cold"===e)return n();if("warm"===e)return r;this._loadSpaces();const s=this._lang,f={title:t(s,"editor.title"),floor:t(s,"editor.floor"),default_floor:t(s,"editor.default_floor"),language:t(s,"editor.language"),icon_size:t(s,"editor.icon_size"),show_temperature:t(s,"editor.show_temperature"),live_states:t(s,"editor.live_states"),show_signal:t(s,"editor.show_signal"),kiosk:t(s,"editor.kiosk"),cycle:t(s,"editor.cycle")},h=this._schema,_=function(e,o,t){if(!t||null===o)return null;const s="string"==typeof e?.default_floor?e.default_floor:"";return!s||o.some(e=>e.value===s)?null:s}(this._config,this._spaces,this._spacesAuthoritative),d=e=>c`<ha-form
|
||||
.hass=${this.hass}
|
||||
.data=${this._formData}
|
||||
.schema=${e}
|
||||
.computeLabel=${e=>f[e.name]||e.name}
|
||||
@value-changed=${this._valueChanged}
|
||||
></ha-form>`;return c`
|
||||
${d(h.slice(0,3))}
|
||||
${_?c`<div class="default-floor-error" role="alert"
|
||||
style="color:var(--error-color,#db4437);margin:-4px 0 12px;overflow-wrap:anywhere">
|
||||
${t(s,"editor.default_floor_missing",{id:_})}
|
||||
</div>`:a}
|
||||
${d(h.slice(3))}
|
||||
`}_valueChanged(e){const o={...this._config,...e.detail.value};""===o.floor?delete o.floor:o.floor===this._floorToken&&(o.floor=this._config?.floor);const t=new Event("config-changed",{bubbles:!0,composed:!0});t.detail={config:o},this.dispatchEvent(t)}}f.properties={hass:{attribute:!1},_config:{state:!0},_spaces:{state:!0}},customElements.get("houseplan-card-editor")||customElements.define("houseplan-card-editor",f);
|
||||
Vendored
+1
File diff suppressed because one or more lines are too long
+5369
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+658
-402
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+78
-54
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
+4
@@ -1 +1,5 @@
|
||||
<<<<<<< HEAD
|
||||
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="88a6e19b99c65848b1132de49a50a7d9214b7d4c077dbd83e9cbda0c21b27d3b";try{await import("./houseplan-assets/houseplan-card-DR7nMAa_.js")}catch(e){if(!customElements.get("houseplan-card")){const l=String(navigator.language||"en").toLowerCase();const m=l.startsWith("ru")?"House Plan обновился — перезагрузите страницу (Ctrl+F5).":l.startsWith("de")?"House Plan wurde aktualisiert — bitte laden Sie die Seite neu (Strg+F5).":l.startsWith("fr")?"House Plan a été mis à jour — veuillez recharger la page (Ctrl+F5).":"House Plan was updated — please reload the page (Ctrl+F5).";customElements.define("houseplan-card",class extends HTMLElement{setConfig(){}getCardSize(){return 1}connectedCallback(){this.style.cssText="display:block;box-sizing:border-box;padding:16px;border:1px solid var(--divider-color,#e0e0e0);border-radius:var(--ha-card-border-radius,12px);background:var(--card-background-color,#fff);color:var(--primary-text-color,#212121);font:14px/1.4 var(--paper-font-body1_-_font-family,sans-serif)";this.textContent=m}})}console.error("[houseplan] stale entry: the main chunk is unavailable",e)}
|
||||
=======
|
||||
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="ef677d5cdeb6a192fb365bc296170e7d5ffab5fddb8a5d91e7fd0e42403f6f47";try{await import("./houseplan-assets/houseplan-card-BNqrY9Pv.js")}catch(e){if(!customElements.get("houseplan-card")){const l=String(navigator.language||"en").toLowerCase();const m=l.startsWith("ru")?"House Plan обновился — перезагрузите страницу (Ctrl+F5).":l.startsWith("de")?"House Plan wurde aktualisiert — bitte laden Sie die Seite neu (Strg+F5).":l.startsWith("fr")?"House Plan a été mis à jour — veuillez recharger la page (Ctrl+F5).":"House Plan was updated — please reload the page (Ctrl+F5).";customElements.define("houseplan-card",class extends HTMLElement{setConfig(){}getCardSize(){return 1}connectedCallback(){this.style.cssText="display:block;box-sizing:border-box;padding:16px;border:1px solid var(--divider-color,#e0e0e0);border-radius:var(--ha-card-border-radius,12px);background:var(--card-background-color,#fff);color:var(--primary-text-color,#212121);font:14px/1.4 var(--paper-font-body1_-_font-family,sans-serif)";this.textContent=m}})}console.error("[houseplan] stale entry: the main chunk is unavailable",e)}
|
||||
>>>>>>> 30df567d (feat: add critical settings help content)
|
||||
|
||||
@@ -16,6 +16,11 @@
|
||||
config from the oldest supported era — or one from the future — loads
|
||||
without silent loss ([#33](https://github.com/Matysh/houseplan-card/issues/33)).
|
||||
|
||||
- Critical plan, light, background and device-catalog settings now have concise
|
||||
contextual help in all four interface languages, without changing the
|
||||
setting when the help is opened
|
||||
([#86](https://github.com/Matysh/houseplan-card/issues/86)).
|
||||
|
||||
- Clicking the already-selected binding in the marker dialog no longer silently
|
||||
resets the configured value source and badge to automatic — the reset now
|
||||
happens only on an actual change of binding
|
||||
|
||||
@@ -22,6 +22,11 @@
|
||||
старейшей поддерживаемой эпохи — или из будущего — загружается без тихих
|
||||
потерь ([#33](https://github.com/Matysh/houseplan-card/issues/33)).
|
||||
|
||||
- У критичных настроек плана, света, фона и каталога устройств появились
|
||||
короткие контекстные подсказки на всех четырёх языках интерфейса; открытие
|
||||
подсказки не меняет саму настройку
|
||||
([#86](https://github.com/Matysh/houseplan-card/issues/86)).
|
||||
|
||||
- Клик по уже выбранной привязке в диалоге маркера больше не сбрасывает молча
|
||||
настроенный источник значения и бейдж на «авто» — сброс происходит только
|
||||
при реальной смене привязки
|
||||
|
||||
+13
-2
@@ -3363,9 +3363,9 @@ require hands on real hardware — they remain for the human pass.
|
||||
config/space/source changes [auto: editor/preloader smokes; performance
|
||||
profile for a dense plan].
|
||||
|
||||
## Contextual help (issue #68, v1.62)
|
||||
## Contextual help (issues #68 and #86)
|
||||
|
||||
- [ ] A setting with complete RU/EN help body and ARIA copy shows one 32 px
|
||||
- [ ] A setting with complete EN/RU/DE/FR help body and ARIA copy shows one 32 px
|
||||
desktop / 40 px coarse-pointer button with the outlined circled-question
|
||||
icon. Mouse hover, keyboard focus and tap open the same text surface
|
||||
[auto: `smoke_help_affordance`].
|
||||
@@ -3379,6 +3379,17 @@ require hands on real hardware — they remain for the human pass.
|
||||
`scrollHeight` nor `scrollTop` of the owning dialog body. The native
|
||||
Popover and forced portal fallback have the same no-layout-shift contract
|
||||
[auto: `smoke_help_affordance`].
|
||||
- [ ] Party 1 contains exactly the 11 agreed logical settings: space scale,
|
||||
general and device Glow radius, room fill, source role and controlled
|
||||
sources, general/space north, general/space background, zero-thickness
|
||||
wall style and the show-hidden catalog filter. The regular and onboarding
|
||||
space dialogs expose the same five space-help controls; opening help does
|
||||
not change a draft setting or the session-only filter
|
||||
[unit: `i18n.test`; auto: `smoke_help_affordance`;
|
||||
mutation: `settings-help-party1-placement-removed`].
|
||||
- [ ] `marker.controls_hint`, `gs.bg_daynight_hint`, `gs.north_hint` and
|
||||
`space.zero_wall_help` are absent from all four dictionaries and production
|
||||
templates; state-specific sun/Glow notes remain visible [unit: `i18n.test`].
|
||||
|
||||
## Large backdrops (#39, docs/specs/039-large-backdrops.md)
|
||||
|
||||
|
||||
@@ -228,6 +228,18 @@ title: План дома
|
||||
**«Наследовать»** остаются рядом с образцом фона и не сохраняют показанное
|
||||
значение по умолчанию, пока пользователь не изменит цвет.
|
||||
|
||||
### Контекстные подсказки настроек
|
||||
|
||||
Значок вопроса в кружке рядом с названием сложной настройки открывает короткое
|
||||
объяснение, не меняя её значение. Подсказка работает мышью, клавиатурой и тапом,
|
||||
закрывается по `Escape` раньше самого диалога и не добавляет ему прокрутку.
|
||||
|
||||
Такие подсказки есть у масштаба пространства, общего и локального фона и севера,
|
||||
режима заливки комнат, общего и персонального радиуса Glow, вида стен нулевой
|
||||
толщины, роли и связей источника света, а также фильтра **Показывать скрытые на
|
||||
плане**. Для стен нулевой толщины подсказка дополнительно напоминает: пунктир
|
||||
пропускает Glow и солнечные лучи, сплошная линия блокирует их.
|
||||
|
||||
<!-- docs-section: input -->
|
||||
|
||||
## 6. Навигация, масштаб и жесты
|
||||
|
||||
@@ -103,6 +103,9 @@ issue после проверки механики и текстов перво
|
||||
не вложен в `<label>` и не переключает checkbox при открытии подсказки.
|
||||
- General/space north and background получают отдельные keys, потому что
|
||||
inheritance/override semantics различаются.
|
||||
- Пять space-подсказок присутствуют и в обычном editor runtime, и в отдельном
|
||||
onboarding runtime создания первого пространства; их текст и поведение
|
||||
идентичны.
|
||||
|
||||
Help-trigger не должен менять ширину canvas, stage zoom или доступность основного
|
||||
action. При 200% zoom label и trigger могут переноситься вместе.
|
||||
@@ -215,7 +218,8 @@ must fail; без этого source contract не доказан.
|
||||
|
||||
## 15. Затронутые поверхности
|
||||
|
||||
- relevant templates in `src/houseplan-editor-runtime.ts`;
|
||||
- relevant templates in `src/houseplan-editor-runtime.ts` and
|
||||
`src/houseplan-onboarding-runtime.ts`;
|
||||
- `src/i18n/en.json`, `src/i18n/ru.json`, `src/i18n/de.json`, `src/i18n/fr.json`;
|
||||
- existing #68 i18n/source tests and targeted browser/golden fixtures;
|
||||
- `docs/USER-GUIDE.ru.md`, `docs/TESTING.md`.
|
||||
|
||||
@@ -105,6 +105,17 @@ function relocateEditorPatch(patch, cardSource, editorSource) {
|
||||
// `find` обязан встречаться в файле ровно один раз: патч, который ложится «куда
|
||||
// попало», проверяет не то, что объявлен проверять. Это контролирует --check.
|
||||
const MUTANT_DEFINITIONS = [
|
||||
{
|
||||
id: 'settings-help-party1-placement-removed',
|
||||
guard: 'npx tsc -p tsconfig.test.json && node scripts/fix-test-build.mjs '
|
||||
+ '&& node --test --test-name-pattern="issue 86 Party 1" test/i18n.test.mjs',
|
||||
because: 'the critical-settings help inventory must fail when one agreed trigger disappears (#86)',
|
||||
patches: [{
|
||||
file: 'src/houseplan-editor-runtime.ts',
|
||||
find: "this._help('device_inbox.show_hidden.help')",
|
||||
replace: 'nothing',
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'room-climate-ignores-marker-placement',
|
||||
guard: 'node demo/smoke_room_climate_placement.mjs',
|
||||
|
||||
@@ -9940,8 +9940,9 @@ public _renderSettingsDialog(): TemplateResult {
|
||||
${this._renderColorRow('glow_base', 'gs.glow_base')}
|
||||
${this._renderColorRow('glow_light', 'gs.glow_light')}
|
||||
<div class="colorrow gsrow">
|
||||
<span class="gsl">${this.host._t('gs.glow_radius')}</span>
|
||||
<input type="number" class="tempin" min="0.5" step="0.5"
|
||||
<span class="gsl help-inline-label"><label for="gs-glow-radius">${this.host._t('gs.glow_radius')}</label>
|
||||
${this._help('gs.glow_radius.help')}</span>
|
||||
<input id="gs-glow-radius" type="number" class="tempin" min="0.5" step="0.5"
|
||||
.value=${String(this.host._settingsDialog!.glowRadius)}
|
||||
@input=${(e: Event) => {
|
||||
const v = strictNumber((e.target as HTMLInputElement).value);
|
||||
@@ -9954,8 +9955,9 @@ public _renderSettingsDialog(): TemplateResult {
|
||||
${this._renderColorRow('wall_fill', 'gs.wall_fill')}
|
||||
<label class="dispsection">${this.host._t('gs.bg_group')}</label>
|
||||
<div class="colorrow gsrow">
|
||||
<span class="gsl">${this.host._t('gs.bg_mode')}</span>
|
||||
<select class="areasel"
|
||||
<span class="gsl help-inline-label"><label for="gs-bg-mode">${this.host._t('gs.bg_mode')}</label>
|
||||
${this._help('gs.bg_mode.help')}</span>
|
||||
<select id="gs-bg-mode" class="areasel"
|
||||
@change=${(e: Event) =>
|
||||
(this.host._settingsDialog = { ...this.host._settingsDialog!, bgMode: (e.target as HTMLSelectElement).value === 'daynight' ? 'daynight' : 'static' })}>
|
||||
<option value="static" ?selected=${this.host._settingsDialog!.bgMode === 'static'}>${this.host._t('gs.bg_static')}</option>
|
||||
@@ -9976,7 +9978,7 @@ public _renderSettingsDialog(): TemplateResult {
|
||||
(this.host._settingsDialog = { ...this.host._settingsDialog!, bgColor: null })}>${this.host._t('gs.bg_default')}</button>`
|
||||
: html`<span class="opl">${this.host._t('gs.bg_theme')}</span>`}
|
||||
</div>`
|
||||
: html`<div class="rhint">${this.host._t('gs.bg_daynight_hint')}</div>`}
|
||||
: nothing}
|
||||
<label class="dispsection">${this.host._t('gs.sun_group')}</label>
|
||||
${!sunStateOf(this.host.hass)
|
||||
? html`<div class="rhint">${this.host._t('gs.sun_missing')}</div>`
|
||||
@@ -9984,9 +9986,12 @@ public _renderSettingsDialog(): TemplateResult {
|
||||
<div class="sunrow">
|
||||
${this.host._renderCompass()}
|
||||
<div class="suncol">
|
||||
<span class="gsl">${this.host._t('gs.north')}</span>
|
||||
<div class="helpfieldlabel compact">
|
||||
<label for="gs-north">${this.host._t('gs.north')}</label>
|
||||
${this._help('gs.north.help')}
|
||||
</div>
|
||||
<div class="colorrow">
|
||||
<input class="namein tempin" type="number" min="0" max="359" step="1"
|
||||
<input id="gs-north" class="namein tempin" type="number" min="0" max="359" step="1"
|
||||
placeholder=${this.host._t('gs.north_ph')}
|
||||
.value=${this.host._settingsDialog!.northDeg === null ? '' : String(this.host._settingsDialog!.northDeg)}
|
||||
@input=${(e: Event) => {
|
||||
@@ -10002,9 +10007,6 @@ public _renderSettingsDialog(): TemplateResult {
|
||||
(this.host._settingsDialog = { ...this.host._settingsDialog!, northDeg: null })}>${this.host._t('gs.north_clear')}</button>`
|
||||
: nothing}
|
||||
</div>
|
||||
${this.host._settingsDialog!.northDeg === null
|
||||
? html`<div class="rhint">${this.host._t('gs.north_hint')}</div>`
|
||||
: nothing}
|
||||
</div>
|
||||
</div>
|
||||
<label class="srcrow">
|
||||
@@ -11982,14 +11984,17 @@ public _renderDeviceInbox(): TemplateResult {
|
||||
};
|
||||
}} />${this.host._t('device_inbox.show_entities' as any)}
|
||||
</label>` : nothing}
|
||||
<label>
|
||||
<input type="checkbox" .checked=${this.host._showAll}
|
||||
@change=${(event: Event) => {
|
||||
this.host._showHidden = (event.target as HTMLInputElement).checked;
|
||||
this.host._deviceInboxMemo = null;
|
||||
this.host.requestUpdate();
|
||||
}} />${this.host._t('device_inbox.show_hidden' as any)}
|
||||
</label>
|
||||
<span class="device-inbox-filter-help">
|
||||
<label>
|
||||
<input type="checkbox" .checked=${this.host._showAll}
|
||||
@change=${(event: Event) => {
|
||||
this.host._showHidden = (event.target as HTMLInputElement).checked;
|
||||
this.host._deviceInboxMemo = null;
|
||||
this.host.requestUpdate();
|
||||
}} />${this.host._t('device_inbox.show_hidden' as any)}
|
||||
</label>
|
||||
${this._help('device_inbox.show_hidden.help')}
|
||||
</span>
|
||||
</div>
|
||||
${dialog.tab === 'available' ? this._renderDiscoveryFilters(dialog) : nothing}
|
||||
<div class="device-inbox-results" aria-live="polite">
|
||||
@@ -12759,8 +12764,10 @@ public _renderMarkerDialog(): TemplateResult {
|
||||
</label>`
|
||||
: nothing}
|
||||
|
||||
<label>${this.host._t('marker.controls_label')}</label>
|
||||
<div class="rhint">${this.host._t('marker.controls_hint')}</div>
|
||||
<div class="helpfieldlabel">
|
||||
<label for="marker-controls-filter">${this.host._t('marker.controls_label')}</label>
|
||||
${this._help('marker.controls.help')}
|
||||
</div>
|
||||
${d.controls.length
|
||||
? html`<div class="ctrlchips">
|
||||
${d.controls.map((eid) => {
|
||||
@@ -12775,7 +12782,7 @@ public _renderMarkerDialog(): TemplateResult {
|
||||
})}
|
||||
</div>`
|
||||
: nothing}
|
||||
<input class="namein" type="text" placeholder=${this.host._t('marker.controls_filter')}
|
||||
<input id="marker-controls-filter" class="namein" type="text" placeholder=${this.host._t('marker.controls_filter')}
|
||||
.value=${d.controlsFilter}
|
||||
@input=${(e: Event) => (this.host._markerDialog = { ...d, controlsFilter: (e.target as HTMLInputElement).value })} />
|
||||
${d.controlsFilter.trim()
|
||||
@@ -13213,9 +13220,12 @@ public _renderSpaceDialog(): TemplateResult {
|
||||
<span>${this.host._t('space.source_draw')}</span>
|
||||
</label>
|
||||
|
||||
<label>${this.host._t('space.scale_label')}</label>
|
||||
<div class="helpfieldlabel">
|
||||
<label for="space-cell-cm">${this.host._t('space.scale_label')}</label>
|
||||
${this._help('space.cell_cm.help')}
|
||||
</div>
|
||||
<div class="colorrow">
|
||||
<input class="namein tempin" type="number"
|
||||
<input id="space-cell-cm" class="namein tempin" type="number"
|
||||
min=${gridCellFieldValue(CELL_CM_MIN, this.host._imperial)}
|
||||
max=${gridCellFieldValue(CELL_CM_MAX, this.host._imperial)}
|
||||
step="0.1" .value=${d.cellCmInput ?? gridCellFieldValue(d.cellCm, this.host._imperial)}
|
||||
@@ -13241,8 +13251,11 @@ public _renderSpaceDialog(): TemplateResult {
|
||||
${this._boolInput(d.showBorders, (v) => (this.host._spaceDialog = touchSpaceDisplay(d, 'showBorders', v)))}
|
||||
<span>${this.host._t('space.show_borders')}</span>
|
||||
</label>
|
||||
<label>${this.host._t('space.zero_wall_style')}</label>
|
||||
<select class="areasel"
|
||||
<div class="helpfieldlabel">
|
||||
<label for="space-zero-wall-style">${this.host._t('space.zero_wall_style')}</label>
|
||||
${this._help('space.zero_wall_style.help')}
|
||||
</div>
|
||||
<select id="space-zero-wall-style" class="areasel"
|
||||
@change=${(e: Event) => {
|
||||
const value = (e.target as HTMLSelectElement).value;
|
||||
this.host._spaceDialog = {
|
||||
@@ -13256,7 +13269,6 @@ public _renderSpaceDialog(): TemplateResult {
|
||||
${this.host._t('space.zero_wall_solid')}
|
||||
</option>
|
||||
</select>
|
||||
<div class="rhint">${this.host._t('space.zero_wall_help')}</div>
|
||||
<label class="srcrow">
|
||||
${this._boolInput(d.showNames, (v) => (this.host._spaceDialog = touchSpaceDisplay(d, 'showNames', v)))}
|
||||
<span>${this.host._t('space.show_names')}</span>
|
||||
@@ -13304,8 +13316,11 @@ public _renderSpaceDialog(): TemplateResult {
|
||||
};
|
||||
}}></hp-color-opacity>
|
||||
</div>
|
||||
<label>${this.host._t('space.bg_mode')}</label>
|
||||
<select class="areasel"
|
||||
<div class="helpfieldlabel">
|
||||
<label for="space-bg-mode">${this.host._t('space.bg_mode')}</label>
|
||||
${this._help('space.bg_mode.help')}
|
||||
</div>
|
||||
<select id="space-bg-mode" class="areasel"
|
||||
@change=${(e: Event) => {
|
||||
const v = (e.target as HTMLSelectElement).value;
|
||||
this.host._spaceDialog = { ...d, bgMode: v === 'static' || v === 'daynight' ? (v as any) : null };
|
||||
@@ -13329,9 +13344,12 @@ public _renderSpaceDialog(): TemplateResult {
|
||||
: html`<span class="opl">${this.host._t('space.bg_inherited')}</span>`}
|
||||
</div>`
|
||||
: nothing}
|
||||
<label>${this.host._t('space.north')}</label>
|
||||
<div class="helpfieldlabel">
|
||||
<label for="space-north">${this.host._t('space.north')}</label>
|
||||
${this._help('space.north.help')}
|
||||
</div>
|
||||
<div class="colorrow">
|
||||
<input class="namein tempin" type="number" min="0" max="359" step="1"
|
||||
<input id="space-north" class="namein tempin" type="number" min="0" max="359" step="1"
|
||||
placeholder=${this.host._t('space.sun_inherit')}
|
||||
.value=${d.northDeg === null ? '' : String(d.northDeg)}
|
||||
@input=${(e: Event) => {
|
||||
@@ -13355,7 +13373,10 @@ public _renderSpaceDialog(): TemplateResult {
|
||||
<option value="1" ?selected=${d.sunRays === true}>${this.host._t('space.sun_on')}</option>
|
||||
<option value="0" ?selected=${d.sunRays === false}>${this.host._t('space.sun_off')}</option>
|
||||
</select>
|
||||
<label>${this.host._t('space.fill_label')}</label>
|
||||
<div class="helpfieldlabel">
|
||||
<span>${this.host._t('space.fill_label')}</span>
|
||||
${this._help('space.fill_mode.help')}
|
||||
</div>
|
||||
${SPACE_FILL_UI_MODES.map((v) => [v, 'fill.' + v] as const).map(
|
||||
([v, k]) => html`<label class="srcrow">
|
||||
<input type="radio" name="fillmode" .checked=${d.fillMode === v}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { html, nothing, type TemplateResult } from 'lit';
|
||||
import { classifyPlanFile, encodePlanFile, renderBackdropGuard } from './backdrop-pick';
|
||||
import { hasTranslation, langOf, t, type I18nKey } from './i18n';
|
||||
import './hp-help';
|
||||
|
||||
import {
|
||||
DEFAULT_CUSTOM_FILL,
|
||||
@@ -49,6 +51,14 @@ export const ONBOARDING_RUNTIME_FINGERPRINT = BUILD_FINGERPRINT;
|
||||
export class HouseplanOnboardingRuntime {
|
||||
public constructor(public readonly host: HouseplanEditorHostPort) {}
|
||||
|
||||
private _help(key: Extract<I18nKey, `${string}.help`>): TemplateResult | typeof nothing {
|
||||
const ariaKey = `${key}.aria` as I18nKey;
|
||||
const lang = langOf(this.host.hass, this.host._config?.language);
|
||||
if (!hasTranslation(lang, key) || !hasTranslation(lang, ariaKey)) return nothing;
|
||||
return html`<hp-help data-help-key=${key}
|
||||
.text=${t(lang, key)} .ariaLabel=${t(lang, ariaKey)}></hp-help>`;
|
||||
}
|
||||
|
||||
public _openSpaceDialog(mode: 'edit' | 'create', spaceId?: string): void {
|
||||
if (!this.host._serverStorage || !this.host._serverCfg) {
|
||||
this.host._showToast(this.host._t('toast.integration_missing'));
|
||||
@@ -615,9 +625,12 @@ export class HouseplanOnboardingRuntime {
|
||||
<span>${this.host._t('space.source_draw')}</span>
|
||||
</label>
|
||||
|
||||
<label>${this.host._t('space.scale_label')}</label>
|
||||
<div class="helpfieldlabel">
|
||||
<label for="onboarding-space-cell-cm">${this.host._t('space.scale_label')}</label>
|
||||
${this._help('space.cell_cm.help')}
|
||||
</div>
|
||||
<div class="colorrow">
|
||||
<input class="namein tempin" type="number"
|
||||
<input id="onboarding-space-cell-cm" class="namein tempin" type="number"
|
||||
min=${gridCellFieldValue(CELL_CM_MIN, this.host._imperial)}
|
||||
max=${gridCellFieldValue(CELL_CM_MAX, this.host._imperial)}
|
||||
step="0.1"
|
||||
@@ -646,8 +659,11 @@ export class HouseplanOnboardingRuntime {
|
||||
})}
|
||||
<span>${this.host._t('space.show_borders')}</span>
|
||||
</label>
|
||||
<label>${this.host._t('space.zero_wall_style')}</label>
|
||||
<select class="areasel" @change=${(event: Event) => {
|
||||
<div class="helpfieldlabel">
|
||||
<label for="onboarding-space-zero-wall-style">${this.host._t('space.zero_wall_style')}</label>
|
||||
${this._help('space.zero_wall_style.help')}
|
||||
</div>
|
||||
<select id="onboarding-space-zero-wall-style" class="areasel" @change=${(event: Event) => {
|
||||
const value = (event.target as HTMLSelectElement).value;
|
||||
this.host._spaceDialog = {
|
||||
...dialog, zeroWallStyle: value === 'solid' ? 'solid' : 'dashed',
|
||||
@@ -660,7 +676,6 @@ export class HouseplanOnboardingRuntime {
|
||||
${this.host._t('space.zero_wall_solid')}
|
||||
</option>
|
||||
</select>
|
||||
<div class="rhint">${this.host._t('space.zero_wall_help')}</div>
|
||||
<label class="srcrow">
|
||||
${this._boolInput(dialog.showNames, (value) => {
|
||||
this.host._spaceDialog = touchSpaceDisplay(dialog, 'showNames', value);
|
||||
@@ -716,8 +731,11 @@ export class HouseplanOnboardingRuntime {
|
||||
};
|
||||
}}></hp-color-opacity>
|
||||
</div>
|
||||
<label>${this.host._t('space.bg_mode')}</label>
|
||||
<select class="areasel" @change=${(event: Event) => {
|
||||
<div class="helpfieldlabel">
|
||||
<label for="onboarding-space-bg-mode">${this.host._t('space.bg_mode')}</label>
|
||||
${this._help('space.bg_mode.help')}
|
||||
</div>
|
||||
<select id="onboarding-space-bg-mode" class="areasel" @change=${(event: Event) => {
|
||||
const value = (event.target as HTMLSelectElement).value;
|
||||
this.host._spaceDialog = {
|
||||
...dialog,
|
||||
@@ -743,9 +761,12 @@ export class HouseplanOnboardingRuntime {
|
||||
}}>${this.host._t('space.bg_inherit')}</button>`
|
||||
: html`<span class="opl">${this.host._t('space.bg_inherited')}</span>`}
|
||||
</div>` : nothing}
|
||||
<label>${this.host._t('space.north')}</label>
|
||||
<div class="helpfieldlabel">
|
||||
<label for="onboarding-space-north">${this.host._t('space.north')}</label>
|
||||
${this._help('space.north.help')}
|
||||
</div>
|
||||
<div class="colorrow">
|
||||
<input class="namein tempin" type="number" min="0" max="359" step="1"
|
||||
<input id="onboarding-space-north" class="namein tempin" type="number" min="0" max="359" step="1"
|
||||
placeholder=${this.host._t('space.sun_inherit')}
|
||||
.value=${dialog.northDeg === null ? '' : String(dialog.northDeg)}
|
||||
@input=${(event: Event) => {
|
||||
@@ -774,7 +795,10 @@ export class HouseplanOnboardingRuntime {
|
||||
<option value="1" ?selected=${dialog.sunRays === true}>${this.host._t('space.sun_on')}</option>
|
||||
<option value="0" ?selected=${dialog.sunRays === false}>${this.host._t('space.sun_off')}</option>
|
||||
</select>
|
||||
<label>${this.host._t('space.fill_label')}</label>
|
||||
<div class="helpfieldlabel">
|
||||
<span>${this.host._t('space.fill_label')}</span>
|
||||
${this._help('space.fill_mode.help')}
|
||||
</div>
|
||||
${SPACE_FILL_UI_MODES.map((value) => [value, `fill.${value}`] as const).map(
|
||||
([value, key]) => html`<label class="srcrow">
|
||||
<input type="radio" name="fillmode" .checked=${dialog.fillMode === value}
|
||||
|
||||
+21
-5
@@ -380,18 +380,23 @@
|
||||
"import.done": "Bereiche erstellt. Räume einzeichnen: Rasterpunkte anklicken und die Kontur schließen.",
|
||||
"btn.skip": "Überspringen",
|
||||
"space.scale_label": "Maßstab (Rasterzellen-Größe)",
|
||||
"space.cell_cm.help": "Verknüpft das Raster mit realen Abmessungen: Davon hängen Längen und Flächen, Wandstärken, Öffnungsgrößen und der Leuchtradius ab. Eine spätere Änderung verändert die berechneten Abmessungen des gesamten Bereichs, verschiebt aber keine Punkte im Plan.",
|
||||
"space.cell_cm.help.aria": "Hilfe: Maßstab des Bereichs",
|
||||
"space.scale_unit": "cm pro Zelle",
|
||||
"space.scale_unit_imperial": "Zoll pro Zelle",
|
||||
"space.display_section": "Anzeige",
|
||||
"space.show_borders": "Raumgrenzen immer anzeigen",
|
||||
"space.zero_wall_style": "Wände ohne Dicke",
|
||||
"space.zero_wall_style.help": "Gestrichelte Wände ohne Dicke lassen Glow und Sonnenstrahlen durch, durchgezogene blockieren sie als Barriere ohne Fläche. Die Auswahl gilt für alle solchen Wände im Bereich, auch wenn ihre Linie in der Ansicht ausgeblendet ist.",
|
||||
"space.zero_wall_style.help.aria": "Hilfe: Darstellung der Wände ohne Dicke",
|
||||
"space.zero_wall_dashed": "Gestrichelt",
|
||||
"space.zero_wall_solid": "Durchgezogen",
|
||||
"space.zero_wall_help": "Gestrichelte Wände lassen Licht durch. Durchgezogene Wände blockieren Licht auch bei einer Dicke von 0.",
|
||||
"space.show_names": "Raumnamen anzeigen (zum Verschieben ziehen)",
|
||||
"space.room_color": "Farbe der Begrenzung & des Namens",
|
||||
"space.opacity": "Deckkraft",
|
||||
"space.fill_label": "Raumausfüllung",
|
||||
"space.fill_mode.help": "„Eigene Farbe“ gestaltet den Bereich; „Licht“, „Temperatur“ und „LQI“ verwenden aktuelle Daten aus Home Assistant. Glow wird separat aktiviert.",
|
||||
"space.fill_mode.help.aria": "Hilfe: Modus der Raumausfüllung",
|
||||
"fill.none": "Keine",
|
||||
"fill.lqi": "Zigbee-Signal",
|
||||
"fill.light": "Lichter",
|
||||
@@ -460,6 +465,8 @@
|
||||
"device_inbox.only_new": "Nur neu",
|
||||
"device_inbox.show_entities": "Entitäten anzeigen",
|
||||
"device_inbox.show_hidden": "Versteckte auf Plan anzeigen",
|
||||
"device_inbox.show_hidden.help": "Zeigt ausgeblendete und deaktivierte Marker vorübergehend als Bearbeitungs-Geister auf dem Plan. Die gespeicherte Sichtbarkeit der Geräte bleibt unverändert.",
|
||||
"device_inbox.show_hidden.help.aria": "Hilfe: ausgeblendete Geräte auf dem Plan anzeigen",
|
||||
"device_inbox.new": "Neu",
|
||||
"device_inbox.find": "Auf dem Plan finden",
|
||||
"device_inbox.edit": "Bearbeiten",
|
||||
@@ -557,10 +564,13 @@
|
||||
"gs.wall_group": "Wände",
|
||||
"gs.wall_fill": "Wandfüllung",
|
||||
"gs.glow_radius": "Glow-Radius",
|
||||
"gs.glow_radius.help": "Legt den allgemeinen Radius des Lichtscheins in Metern oder Fuß fest; ein gerätespezifischer Radius überschreibt diesen Wert.",
|
||||
"gs.glow_radius.help.aria": "Hilfe: allgemeiner Glow-Radius",
|
||||
"gs.unit_m": "m",
|
||||
"gs.unit_ft": "ft",
|
||||
"marker.controls_label": "Steuert andere Lichtquellen",
|
||||
"marker.controls_hint": "Mit der Tippen-Aktion „Umschalten“ wechselt ein Klick jede hier hinzugefügte Quelle. Die eigene zugeordnete Entität des Markers wird direkt gesteuert und kann nicht hinzugefügt werden; verwenden Sie den untenstehenden Schalter, um ihn als Licht zu klassifizieren.",
|
||||
"marker.controls.help": "Mit der Aktion „Zustand umschalten“ werden die aufgeführten Quellen zusammen mit diesem Marker umgeschaltet. Ihr Glow bleibt an ihren eigenen Markern, und die Verknüpfung allein macht den steuernden Marker nicht zur Lichtquelle.",
|
||||
"marker.controls.help.aria": "Hilfe: andere Lichtquellen steuern",
|
||||
"marker.controls_filter": "Suchlichter und Schalter…",
|
||||
"info.controls": "Steuerungen",
|
||||
"marker.glow_radius_label": "Leuchtradius",
|
||||
@@ -682,7 +692,7 @@
|
||||
"marker.value_source_auto": "Automatisch (wie bisher)",
|
||||
"marker.value_source_missing_hint": "Die gespeicherte Quelle ist derzeit nicht verfügbar. Bis sie wieder verfügbar ist oder ein anderer Wert gewählt wird, zeigt die Fläche —.",
|
||||
"marker.light_role_label": "Ist dieses Gerät eine Lichtquelle?",
|
||||
"marker.light_role.help": "Steuert, ob dieser Marker selbst eine räumliche Lichtquelle ist. Verknüpfte Lichter oben bleiben unabhängige Raumlichtsteuerungen.",
|
||||
"marker.light_role.help": "„Auto“ verwendet die ermittelte Rolle des verknüpften Geräts, „Immer“ erzwingt eine eigene Quelle und „Nie“ schließt sie aus; oben verknüpfte Lichter bleiben unabhängig.",
|
||||
"marker.light_role.help.aria": "Hilfe: ob dieses Gerät eine Lichtquelle ist",
|
||||
"marker.light_role_auto_yes": "Automatisch (Lichtquelle)",
|
||||
"marker.light_role_auto_no": "Automatisch (keine Lichtquelle)",
|
||||
@@ -823,14 +833,16 @@
|
||||
"gs.bg_default": "Standardthema",
|
||||
"gs.bg_theme": "Standardthema",
|
||||
"gs.bg_mode": "Planhintergrund",
|
||||
"gs.bg_mode.help": "„Folgt der Sonne“ verwendet sun.sun und ersatzweise die lokale Browserzeit; „Statische Farbe“ zeigt immer die ausgewählte Farbe.",
|
||||
"gs.bg_mode.help.aria": "Hilfe: allgemeiner Planhintergrund",
|
||||
"gs.bg_static": "Statische Farbe",
|
||||
"gs.bg_daynight": "Folgt der Sonne",
|
||||
"gs.bg_daynight_hint": "Der Hintergrund wechselt durch Morgendämmerung, Tag, Abenddämmerung und Nacht mithilfe von sun.sun oder Ihrer lokalen Uhr, wenn keine Sonnendaten verfügbar sind. Für den Hintergrund ist kein Kompass erforderlich.",
|
||||
"gs.sun_group": "Sonne",
|
||||
"gs.sun_missing": "Die sun.sun-Entität wurde nicht gefunden — der Hintergrund folgt Ihrer lokalen Uhr; Fensterstrahlen sind nicht verfügbar.",
|
||||
"gs.north": "Norden auf dem Plan",
|
||||
"gs.north.help": "Der Winkel wird im Uhrzeigersinn von der oberen Vertikalen des Plans gemessen; Norden wird für Fensterstrahlen benötigt, nicht für den Hintergrund „Folgt der Sonne“.",
|
||||
"gs.north.help.aria": "Hilfe: allgemeine Nordrichtung",
|
||||
"gs.north_ph": "nicht gesetzt",
|
||||
"gs.north_hint": "Norden nur für Fensterstrahlen einstellen (1° Schritte, 15° mit Shift); der Sonnenhintergrund funktioniert auch ohne ihn.",
|
||||
"gs.north_clear": "Löschen",
|
||||
"gs.north_letter": "N",
|
||||
"gs.sun_rays": "Sonnenlicht durch Fenster",
|
||||
@@ -842,7 +854,11 @@
|
||||
"space.bg_inherit": "Allgemein erben",
|
||||
"space.bg_inherited": "erbt allgemeine Einstellungen",
|
||||
"space.bg_mode": "Planhintergrund",
|
||||
"space.bg_mode.help": "Übernehmen Sie den allgemeinen Hintergrund oder überschreiben Sie diesen Bereich mit einer statischen Farbe oder „Folgt der Sonne“.",
|
||||
"space.bg_mode.help.aria": "Hilfe: Hintergrund des Bereichs",
|
||||
"space.north": "Norden auf dem Plan (überschreiben)",
|
||||
"space.north.help": "Überschreibt die allgemeine Nordrichtung für diesen Bereich; der Winkel wird im Uhrzeigersinn von der oberen Vertikalen des Plans gemessen und für Fensterstrahlen verwendet.",
|
||||
"space.north.help.aria": "Hilfe: Norden für diesen Bereich",
|
||||
"space.north_inherited": "geerbt: {v}",
|
||||
"space.sun_rays": "Sonnenlicht durch Fenster",
|
||||
"space.sun_inherit": "Allgemein erben",
|
||||
|
||||
+21
-5
@@ -380,18 +380,23 @@
|
||||
"import.done": "Spaces created. Outline the rooms: click grid dots and close the contour.",
|
||||
"btn.skip": "Skip",
|
||||
"space.scale_label": "Scale (grid cell size)",
|
||||
"space.cell_cm.help": "Links the grid to real dimensions: lengths, areas, wall thickness, opening sizes and glow radius depend on it. Changing it after drawing changes the calculated dimensions of the whole space without moving its points on the plan.",
|
||||
"space.cell_cm.help.aria": "Help: space scale",
|
||||
"space.scale_unit": "cm per cell",
|
||||
"space.scale_unit_imperial": "in per cell",
|
||||
"space.display_section": "Display",
|
||||
"space.show_borders": "Always show room borders",
|
||||
"space.zero_wall_style": "Zero-thickness walls",
|
||||
"space.zero_wall_style.help": "Dashed zero-thickness walls pass Glow and sun rays, while solid ones block them as zero-area barriers. The choice affects every such wall in the space even when its line is hidden in View.",
|
||||
"space.zero_wall_style.help.aria": "Help: zero-thickness wall style",
|
||||
"space.zero_wall_dashed": "Dashed",
|
||||
"space.zero_wall_solid": "Solid",
|
||||
"space.zero_wall_help": "Dashed walls let light through. Solid walls block light even at zero thickness.",
|
||||
"space.show_names": "Show room names (drag to move)",
|
||||
"space.room_color": "Border & name color",
|
||||
"space.opacity": "Opacity",
|
||||
"space.fill_label": "Room fill",
|
||||
"space.fill_mode.help": "“Custom colour” is styling, while “Light”, “Temperature” and “LQI” use current Home Assistant data; Glow is enabled separately.",
|
||||
"space.fill_mode.help.aria": "Help: room fill mode",
|
||||
"fill.none": "None",
|
||||
"fill.lqi": "Zigbee signal",
|
||||
"fill.light": "Lights",
|
||||
@@ -460,6 +465,8 @@
|
||||
"device_inbox.only_new": "New only",
|
||||
"device_inbox.show_entities": "Show entities",
|
||||
"device_inbox.show_hidden": "Show hidden on plan",
|
||||
"device_inbox.show_hidden.help": "Temporarily shows hidden and disabled markers as editor-only ghosts on the plan. Saved device visibility does not change.",
|
||||
"device_inbox.show_hidden.help.aria": "Help: show hidden devices on the plan",
|
||||
"device_inbox.new": "New",
|
||||
"device_inbox.find": "Find on plan",
|
||||
"device_inbox.edit": "Edit",
|
||||
@@ -557,10 +564,13 @@
|
||||
"gs.wall_group": "Walls",
|
||||
"gs.wall_fill": "Wall fill",
|
||||
"gs.glow_radius": "Glow radius",
|
||||
"gs.glow_radius.help": "Sets the default glow radius in metres or feet; a device-specific radius overrides it.",
|
||||
"gs.glow_radius.help.aria": "Help: default glow radius",
|
||||
"gs.unit_m": "m",
|
||||
"gs.unit_ft": "ft",
|
||||
"marker.controls_label": "Controls other light sources",
|
||||
"marker.controls_hint": "With tap action “Toggle”, a click flips every source added here. The marker’s own bound entity is controlled directly and cannot be added; use the switch below to classify it as a light.",
|
||||
"marker.controls.help": "With the “Toggle state” action, the listed sources toggle together with this marker. Their glow stays at their own markers, and the link alone does not turn the controlling marker into a light source.",
|
||||
"marker.controls.help.aria": "Help: controlling other light sources",
|
||||
"marker.controls_filter": "Search lights and switches…",
|
||||
"info.controls": "Controls",
|
||||
"marker.glow_radius_label": "Glow radius",
|
||||
@@ -682,7 +692,7 @@
|
||||
"marker.value_source_auto": "Automatic (as before)",
|
||||
"marker.value_source_missing_hint": "The saved source is currently unavailable. The face shows — until it recovers or you choose another value.",
|
||||
"marker.light_role_label": "Is this device a light source?",
|
||||
"marker.light_role.help": "Controls whether this marker itself is a spatial light source. Linked lights above remain independent room-light controls.",
|
||||
"marker.light_role.help": "“Auto” uses the bound device's resolved role, “Always” forces its own source and “Never” excludes it; linked lights above remain independent.",
|
||||
"marker.light_role.help.aria": "Help: whether this device is a light source",
|
||||
"marker.light_role_auto_yes": "Auto (light source)",
|
||||
"marker.light_role_auto_no": "Auto (not a light source)",
|
||||
@@ -823,14 +833,16 @@
|
||||
"gs.bg_default": "Theme default",
|
||||
"gs.bg_theme": "theme default",
|
||||
"gs.bg_mode": "Plan background",
|
||||
"gs.bg_mode.help": "“Follows the Sun” uses sun.sun, falling back to the browser's local clock; Static always shows the selected colour.",
|
||||
"gs.bg_mode.help.aria": "Help: general plan background",
|
||||
"gs.bg_static": "Static color",
|
||||
"gs.bg_daynight": "Follows the Sun",
|
||||
"gs.bg_daynight_hint": "The background moves through dawn, day, dusk and night using sun.sun, or your local clock when sun data is unavailable. No compass is needed for the background.",
|
||||
"gs.sun_group": "Sun",
|
||||
"gs.sun_missing": "The sun.sun entity was not found — the background follows your local clock; window rays are unavailable.",
|
||||
"gs.north": "North on the plan",
|
||||
"gs.north.help": "The angle is measured clockwise from the plan's upward vertical; north is required for window rays, not for the “Follows the Sun” background.",
|
||||
"gs.north.help.aria": "Help: general north direction",
|
||||
"gs.north_ph": "not set",
|
||||
"gs.north_hint": "Set north only for window rays (1° steps, 15° with Shift); the Sun background works without it.",
|
||||
"gs.north_clear": "Clear",
|
||||
"gs.north_letter": "N",
|
||||
"gs.sun_rays": "Sunlight through windows",
|
||||
@@ -842,7 +854,11 @@
|
||||
"space.bg_inherit": "Inherit general",
|
||||
"space.bg_inherited": "inherits general settings",
|
||||
"space.bg_mode": "Plan background",
|
||||
"space.bg_mode.help": "Inherit the general background or override this space with a static colour or “Follows the Sun”.",
|
||||
"space.bg_mode.help.aria": "Help: space background",
|
||||
"space.north": "North on the plan (override)",
|
||||
"space.north.help": "Overrides general north for this space; the angle is measured clockwise from the plan's upward vertical and is used by window rays.",
|
||||
"space.north.help.aria": "Help: north for this space",
|
||||
"space.north_inherited": "inherited: {v}",
|
||||
"space.sun_rays": "Sunlight through windows",
|
||||
"space.sun_inherit": "Inherit general",
|
||||
|
||||
+21
-5
@@ -380,18 +380,23 @@
|
||||
"import.done": "Espaces créés. Tracez les pièces : cliquez sur les points de la grille et fermez le contour.",
|
||||
"btn.skip": "Passer",
|
||||
"space.scale_label": "Échelle (taille d’une cellule de grille)",
|
||||
"space.cell_cm.help": "Relie la grille aux dimensions réelles : les longueurs, les surfaces, l’épaisseur des murs, la taille des ouvertures et le rayon du halo en dépendent. Une modification ultérieure change les dimensions calculées de tout l’espace sans déplacer ses points sur le plan.",
|
||||
"space.cell_cm.help.aria": "Aide : échelle de l’espace",
|
||||
"space.scale_unit": "cm par cellule",
|
||||
"space.scale_unit_imperial": "po par cellule",
|
||||
"space.display_section": "Affichage",
|
||||
"space.show_borders": "Toujours afficher les contours des pièces",
|
||||
"space.zero_wall_style": "Murs d’épaisseur nulle",
|
||||
"space.zero_wall_style.help": "Les murs d’épaisseur nulle en pointillés laissent passer le halo et les rayons du soleil, tandis que les murs pleins les bloquent comme une barrière sans surface. Ce choix s’applique à tous ces murs de l’espace, même si leur ligne est masquée en mode Vue.",
|
||||
"space.zero_wall_style.help.aria": "Aide : style des murs d’épaisseur nulle",
|
||||
"space.zero_wall_dashed": "Pointillés",
|
||||
"space.zero_wall_solid": "Plein",
|
||||
"space.zero_wall_help": "Les murs en pointillés laissent passer la lumière. Les murs pleins bloquent la lumière même avec une épaisseur nulle.",
|
||||
"space.show_names": "Afficher les noms des pièces (faire glisser pour déplacer)",
|
||||
"space.room_color": "Couleur du contour et du nom",
|
||||
"space.opacity": "Opacité",
|
||||
"space.fill_label": "Remplissage de la pièce",
|
||||
"space.fill_mode.help": "« Couleur personnalisée » définit le style, tandis que « Lumière », « Température » et « LQI » utilisent les données actuelles de Home Assistant. Le halo s’active séparément.",
|
||||
"space.fill_mode.help.aria": "Aide : mode de remplissage des pièces",
|
||||
"fill.none": "Aucun",
|
||||
"fill.lqi": "Signal Zigbee",
|
||||
"fill.light": "Lumières",
|
||||
@@ -460,6 +465,8 @@
|
||||
"device_inbox.only_new": "Nouveaux uniquement",
|
||||
"device_inbox.show_entities": "Afficher les entités",
|
||||
"device_inbox.show_hidden": "Afficher les masqués sur le plan",
|
||||
"device_inbox.show_hidden.help": "Affiche temporairement les marqueurs masqués et désactivés sous forme de fantômes réservés à l’éditeur. La visibilité enregistrée des appareils ne change pas.",
|
||||
"device_inbox.show_hidden.help.aria": "Aide : afficher les appareils masqués sur le plan",
|
||||
"device_inbox.new": "Nouveau",
|
||||
"device_inbox.find": "Trouver sur le plan",
|
||||
"device_inbox.edit": "Modifier",
|
||||
@@ -557,10 +564,13 @@
|
||||
"gs.wall_group": "Murs",
|
||||
"gs.wall_fill": "Remplissage des murs",
|
||||
"gs.glow_radius": "Rayon du halo",
|
||||
"gs.glow_radius.help": "Définit le rayon général du halo en mètres ou en pieds ; le rayon propre à un appareil remplace cette valeur.",
|
||||
"gs.glow_radius.help.aria": "Aide : rayon général du halo",
|
||||
"gs.unit_m": "m",
|
||||
"gs.unit_ft": "pi",
|
||||
"marker.controls_label": "Contrôle d’autres sources lumineuses",
|
||||
"marker.controls_hint": "Avec l’action au toucher « Basculer », un clic inverse l’état de chaque source ajoutée ici. L’entité propre associée au marqueur est contrôlée directement et ne peut pas être ajoutée ; utilisez l’interrupteur ci-dessous pour la classer comme lumière.",
|
||||
"marker.controls.help": "Avec l’action « Basculer l’état », les sources répertoriées basculent avec ce marqueur. Leur halo reste sur leurs propres marqueurs et ce lien ne transforme pas à lui seul le marqueur de contrôle en source lumineuse.",
|
||||
"marker.controls.help.aria": "Aide : contrôler d’autres sources lumineuses",
|
||||
"marker.controls_filter": "Rechercher des lumières et interrupteurs…",
|
||||
"info.controls": "Contrôle",
|
||||
"marker.glow_radius_label": "Rayon du halo",
|
||||
@@ -682,7 +692,7 @@
|
||||
"marker.value_source_auto": "Automatique (comme avant)",
|
||||
"marker.value_source_missing_hint": "La source enregistrée est indisponible. Le marqueur affiche — jusqu’à son retour ou jusqu’au choix d’une autre valeur.",
|
||||
"marker.light_role_label": "Cet appareil est-il une source lumineuse ?",
|
||||
"marker.light_role.help": "Détermine si ce marqueur est lui-même une source lumineuse spatiale. Les lumières liées ci-dessus restent des contrôles de lumière de pièce indépendants.",
|
||||
"marker.light_role.help": "« Auto » utilise le rôle déterminé de l’appareil lié, « Toujours » force sa propre source et « Jamais » l’exclut ; les lumières liées ci-dessus restent indépendantes.",
|
||||
"marker.light_role.help.aria": "Aide : cet appareil est-il une source lumineuse",
|
||||
"marker.light_role_auto_yes": "Auto (source lumineuse)",
|
||||
"marker.light_role_auto_no": "Auto (pas une source lumineuse)",
|
||||
@@ -823,14 +833,16 @@
|
||||
"gs.bg_default": "Valeur par défaut du thème",
|
||||
"gs.bg_theme": "valeur par défaut du thème",
|
||||
"gs.bg_mode": "Arrière-plan du plan",
|
||||
"gs.bg_mode.help": "« Suit le soleil » utilise sun.sun ou, à défaut, l’heure locale du navigateur ; « Couleur statique » affiche toujours la couleur choisie.",
|
||||
"gs.bg_mode.help.aria": "Aide : arrière-plan général du plan",
|
||||
"gs.bg_static": "Couleur statique",
|
||||
"gs.bg_daynight": "Suit le soleil",
|
||||
"gs.bg_daynight_hint": "L’arrière-plan évolue entre l’aube, le jour, le crépuscule et la nuit en utilisant sun.sun, ou votre heure locale si les données du soleil sont indisponibles. Aucune orientation du nord n’est nécessaire pour l’arrière-plan.",
|
||||
"gs.sun_group": "Soleil",
|
||||
"gs.sun_missing": "L’entité sun.sun est introuvable — l’arrière-plan suit votre heure locale ; les rayons de soleil par les fenêtres sont indisponibles.",
|
||||
"gs.north": "Nord sur le plan",
|
||||
"gs.north.help": "L’angle se mesure dans le sens horaire depuis la verticale supérieure du plan ; le nord sert aux rayons des fenêtres, pas à l’arrière-plan « Suit le soleil ».",
|
||||
"gs.north.help.aria": "Aide : direction générale du nord",
|
||||
"gs.north_ph": "non défini",
|
||||
"gs.north_hint": "Définissez le nord uniquement pour les rayons par les fenêtres (pas de 1°, 15° avec Maj) ; l’arrière-plan Soleil fonctionne sans lui.",
|
||||
"gs.north_clear": "Effacer",
|
||||
"gs.north_letter": "N",
|
||||
"gs.sun_rays": "Lumière du soleil à travers les fenêtres",
|
||||
@@ -842,7 +854,11 @@
|
||||
"space.bg_inherit": "Hériter des paramètres généraux",
|
||||
"space.bg_inherited": "hérite des paramètres généraux",
|
||||
"space.bg_mode": "Arrière-plan du plan",
|
||||
"space.bg_mode.help": "Héritez de l’arrière-plan général ou remplacez-le pour cet espace par une couleur statique ou le mode « Suit le soleil ».",
|
||||
"space.bg_mode.help.aria": "Aide : arrière-plan de l’espace",
|
||||
"space.north": "Nord sur le plan (remplacement)",
|
||||
"space.north.help": "Remplace le nord général pour cet espace ; l’angle se mesure dans le sens horaire depuis la verticale supérieure du plan et sert aux rayons des fenêtres.",
|
||||
"space.north.help.aria": "Aide : nord de cet espace",
|
||||
"space.north_inherited": "hérité : {v}",
|
||||
"space.sun_rays": "Lumière du soleil à travers les fenêtres",
|
||||
"space.sun_inherit": "Hériter des paramètres généraux",
|
||||
|
||||
+21
-5
@@ -380,18 +380,23 @@
|
||||
"import.done": "Пространства созданы. Обведите комнаты: кликайте по точкам сетки и замкните контур.",
|
||||
"btn.skip": "Пропустить",
|
||||
"space.scale_label": "Масштаб (размер клетки сетки)",
|
||||
"space.cell_cm.help": "Связывает сетку с реальными размерами: от значения зависят длины и площади, толщина стен, размеры проёмов и радиус свечения. Изменение после разметки меняет расчётные размеры всего пространства, но не двигает его точки на плане.",
|
||||
"space.cell_cm.help.aria": "Подсказка: масштаб пространства",
|
||||
"space.scale_unit": "см на клетку",
|
||||
"space.scale_unit_imperial": "дюйм на клетку",
|
||||
"space.display_section": "Отображение",
|
||||
"space.show_borders": "Всегда отображать границы комнат",
|
||||
"space.zero_wall_style": "Стены нулевой толщины",
|
||||
"space.zero_wall_style.help": "Пунктирные стены нулевой толщины пропускают Glow и солнечные лучи, сплошные блокируют их как барьер нулевой площади. Выбор меняет все такие стены пространства, даже когда их линии скрыты в просмотре.",
|
||||
"space.zero_wall_style.help.aria": "Подсказка: вид стен нулевой толщины",
|
||||
"space.zero_wall_dashed": "Пунктирные",
|
||||
"space.zero_wall_solid": "Сплошные",
|
||||
"space.zero_wall_help": "Пунктирные стены пропускают свет. Сплошные стены блокируют свет, даже при нулевой толщине.",
|
||||
"space.show_names": "Отображать названия комнат (перетаскиваются)",
|
||||
"space.room_color": "Цвет границ и названий",
|
||||
"space.opacity": "Прозрачность",
|
||||
"space.fill_label": "Заливка комнат",
|
||||
"space.fill_mode.help": "«Свой цвет» задаёт оформление, а «Свет», «Температура» и «LQI» используют текущие данные Home Assistant; Glow включается отдельно.",
|
||||
"space.fill_mode.help.aria": "Подсказка: режим заливки комнат",
|
||||
"fill.none": "Нет",
|
||||
"fill.lqi": "По силе зигби-сигнала",
|
||||
"fill.light": "По освещению",
|
||||
@@ -460,6 +465,8 @@
|
||||
"device_inbox.only_new": "Только новые",
|
||||
"device_inbox.show_entities": "Показывать сущности",
|
||||
"device_inbox.show_hidden": "Показывать скрытые на плане",
|
||||
"device_inbox.show_hidden.help": "Временно показывает на плане скрытые и деактивированные маркеры служебными призраками только в редакторе устройств. Сохранённая видимость устройств не меняется.",
|
||||
"device_inbox.show_hidden.help.aria": "Подсказка: показывать скрытые устройства на плане",
|
||||
"device_inbox.new": "Новое",
|
||||
"device_inbox.find": "Найти на плане",
|
||||
"device_inbox.edit": "Настроить",
|
||||
@@ -557,10 +564,13 @@
|
||||
"gs.wall_group": "Стены",
|
||||
"gs.wall_fill": "Цвет заливки стен",
|
||||
"gs.glow_radius": "Радиус свечения",
|
||||
"gs.glow_radius.help": "Задаёт общий радиус светового пятна в метрах или футах; персональный радиус устройства заменяет это значение.",
|
||||
"gs.glow_radius.help.aria": "Подсказка: общий радиус свечения",
|
||||
"gs.unit_m": "м",
|
||||
"gs.unit_ft": "фут",
|
||||
"marker.controls_label": "Управляет другими источниками света",
|
||||
"marker.controls_hint": "При действии «Переключить» клик разом переключает все добавленные здесь источники. Собственная сущность маркера управляется напрямую и сюда не добавляется; чтобы считать её светом, включите флаг ниже.",
|
||||
"marker.controls.help": "При действии «Переключить состояние» перечисленные источники переключаются вместе с этим маркером. Их световые пятна остаются у собственных маркеров, а эта связь сама по себе не делает управляющий маркер источником света.",
|
||||
"marker.controls.help.aria": "Подсказка: управление другими источниками света",
|
||||
"marker.controls_filter": "Поиск ламп и выключателей…",
|
||||
"info.controls": "Управляет",
|
||||
"marker.glow_radius_label": "Радиус свечения",
|
||||
@@ -682,7 +692,7 @@
|
||||
"marker.value_source_auto": "Автоматически (как раньше)",
|
||||
"marker.value_source_missing_hint": "Сохранённый источник сейчас недоступен. До его восстановления или выбора другого значения внутри будет показано —.",
|
||||
"marker.light_role_label": "Является источником света",
|
||||
"marker.light_role.help": "Определяет, является ли сам маркер пространственным источником света. Привязанные выше лампы остаются независимыми источниками для комнаты.",
|
||||
"marker.light_role.help": "«Авто» использует фактическую роль привязанного устройства, «Всегда» принудительно создаёт собственный источник, а «Никогда» исключает его; связанные лампы выше остаются независимыми.",
|
||||
"marker.light_role.help.aria": "Подсказка: является ли устройство источником света",
|
||||
"marker.light_role_auto_yes": "Автоматически (источник света)",
|
||||
"marker.light_role_auto_no": "Автоматически (не источник света)",
|
||||
@@ -823,14 +833,16 @@
|
||||
"gs.bg_default": "Как в теме",
|
||||
"gs.bg_theme": "по умолчанию — из темы",
|
||||
"gs.bg_mode": "Фон плана",
|
||||
"gs.bg_mode.help": "«Следует за Солнцем» использует sun.sun, а при недоступности — локальные часы браузера; статичный режим всегда показывает выбранный цвет.",
|
||||
"gs.bg_mode.help.aria": "Подсказка: общий фон плана",
|
||||
"gs.bg_static": "Статичный цвет",
|
||||
"gs.bg_daynight": "Следует за Солнцем",
|
||||
"gs.bg_daynight_hint": "Фон проходит рассвет, день, закат и ночь по данным sun.sun, а при их недоступности — по локальным часам. Компас для фона не нужен.",
|
||||
"gs.sun_group": "Солнце",
|
||||
"gs.sun_missing": "Сущность sun.sun не найдена — фон следует локальным часам, а оконные лучи недоступны.",
|
||||
"gs.north": "Север на плане",
|
||||
"gs.north.help": "Угол отсчитывается по часовой стрелке от верхней вертикали плана; север нужен для оконных лучей, а не для фона «Следует за Солнцем».",
|
||||
"gs.north.help.aria": "Подсказка: общее направление севера",
|
||||
"gs.north_ph": "не задан",
|
||||
"gs.north_hint": "Север нужен только для оконных лучей (шаг 1°, с Shift 15°); солнечный фон работает без него.",
|
||||
"gs.north_clear": "Сбросить",
|
||||
"gs.north_letter": "С",
|
||||
"gs.sun_rays": "Солнце в окнах",
|
||||
@@ -842,7 +854,11 @@
|
||||
"space.bg_inherit": "Наследовать общий",
|
||||
"space.bg_inherited": "наследуется из общих настроек",
|
||||
"space.bg_mode": "Фон плана",
|
||||
"space.bg_mode.help": "Выберите наследование общего фона либо переопределите это пространство статичным цветом или режимом «Следует за Солнцем».",
|
||||
"space.bg_mode.help.aria": "Подсказка: фон пространства",
|
||||
"space.north": "Север на плане (переопределение)",
|
||||
"space.north.help": "Переопределяет общий север для этого пространства; угол отсчитывается по часовой стрелке от верхней вертикали плана и используется оконными лучами.",
|
||||
"space.north.help.aria": "Подсказка: север для пространства",
|
||||
"space.north_inherited": "наследуется: {v}",
|
||||
"space.sun_rays": "Солнце в окнах",
|
||||
"space.sun_inherit": "Наследовать общий",
|
||||
|
||||
@@ -453,6 +453,33 @@ export const dialogsStyles = css`
|
||||
margin-bottom: var(--sp-1);
|
||||
}
|
||||
.markerhelplabel > label { min-width: 0; overflow-wrap: anywhere; }
|
||||
.helpfieldlabel {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--sp-1);
|
||||
min-width: 0;
|
||||
margin-top: var(--sp-3);
|
||||
color: var(--hp-muted);
|
||||
font-size: var(--fs-s);
|
||||
}
|
||||
.helpfieldlabel.compact { margin-top: 0; }
|
||||
hp-dialog .body .helpfieldlabel > label {
|
||||
min-width: 0;
|
||||
margin-top: 0;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.help-inline-label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--sp-1);
|
||||
}
|
||||
hp-dialog .body .help-inline-label > label {
|
||||
min-width: 0;
|
||||
margin-top: 0;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.markerradios { display: grid; gap: var(--sp-1); min-width: 0; }
|
||||
.markerlightgroup .srcrow > span:first-of-type {
|
||||
min-width: 0;
|
||||
@@ -1324,6 +1351,12 @@ export const dialogsStyles = css`
|
||||
gap: var(--sp-2);
|
||||
cursor: pointer;
|
||||
}
|
||||
.device-inbox-filter-help {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--sp-1);
|
||||
min-width: 0;
|
||||
}
|
||||
.device-inbox-results { display: grid; gap: var(--sp-3); min-width: 0; }
|
||||
.device-inbox-row {
|
||||
display: grid;
|
||||
|
||||
+78
-5
@@ -23,6 +23,11 @@ const ru = dictionaries.get('ru');
|
||||
const de = dictionaries.get('de');
|
||||
const fr = dictionaries.get('fr');
|
||||
const cardSource = readHouseplanProductionSource();
|
||||
const onboardingSource = readFileSync(
|
||||
new URL('../src/houseplan-onboarding-runtime.ts', import.meta.url),
|
||||
'utf8',
|
||||
);
|
||||
const helpSource = `${cardSource}\n${onboardingSource}`;
|
||||
|
||||
test('i18n: registry codes and English fallback are valid', () => {
|
||||
const codes = LANGUAGE_REGISTRY.map(({ code }) => code);
|
||||
@@ -283,9 +288,9 @@ test('issue 252 Optimize keeps internal ids out of the main orphan report', () =
|
||||
}
|
||||
});
|
||||
|
||||
test('i18n: every literal help call has body and full aria keys in both languages', () => {
|
||||
const allCalls = cardSource.match(/this\._help\(/g) || [];
|
||||
const helpKeys = [...cardSource.matchAll(/this\._help\('([^']+\.help)'\)/g)].map((match) => match[1]);
|
||||
test('i18n: every literal help call has body and full aria keys in every language', () => {
|
||||
const allCalls = helpSource.match(/this\._help\(/g) || [];
|
||||
const helpKeys = [...helpSource.matchAll(/this\._help\('([^']+\.help)'\)/g)].map((match) => match[1]);
|
||||
assert.equal(helpKeys.length, allCalls.length, 'every _help call must use one string literal ending in .help');
|
||||
assert.ok(helpKeys.length > 0, 'the help affordance pilot disappeared');
|
||||
for (const key of helpKeys) {
|
||||
@@ -297,6 +302,74 @@ test('i18n: every literal help call has body and full aria keys in both language
|
||||
}
|
||||
});
|
||||
|
||||
test('issue 86 Party 1 has the exact help inventory and canonical RU/EN copy', () => {
|
||||
const copy = {
|
||||
'space.cell_cm.help': [
|
||||
'Links the grid to real dimensions: lengths, areas, wall thickness, opening sizes and glow radius depend on it. Changing it after drawing changes the calculated dimensions of the whole space without moving its points on the plan.',
|
||||
'Связывает сетку с реальными размерами: от значения зависят длины и площади, толщина стен, размеры проёмов и радиус свечения. Изменение после разметки меняет расчётные размеры всего пространства, но не двигает его точки на плане.',
|
||||
],
|
||||
'gs.glow_radius.help': [
|
||||
'Sets the default glow radius in metres or feet; a device-specific radius overrides it.',
|
||||
'Задаёт общий радиус светового пятна в метрах или футах; персональный радиус устройства заменяет это значение.',
|
||||
],
|
||||
'space.fill_mode.help': [
|
||||
'“Custom colour” is styling, while “Light”, “Temperature” and “LQI” use current Home Assistant data; Glow is enabled separately.',
|
||||
'«Свой цвет» задаёт оформление, а «Свет», «Температура» и «LQI» используют текущие данные Home Assistant; Glow включается отдельно.',
|
||||
],
|
||||
'marker.light_role.help': [
|
||||
'“Auto” uses the bound device\'s resolved role, “Always” forces its own source and “Never” excludes it; linked lights above remain independent.',
|
||||
'«Авто» использует фактическую роль привязанного устройства, «Всегда» принудительно создаёт собственный источник, а «Никогда» исключает его; связанные лампы выше остаются независимыми.',
|
||||
],
|
||||
'marker.controls.help': [
|
||||
'With the “Toggle state” action, the listed sources toggle together with this marker. Their glow stays at their own markers, and the link alone does not turn the controlling marker into a light source.',
|
||||
'При действии «Переключить состояние» перечисленные источники переключаются вместе с этим маркером. Их световые пятна остаются у собственных маркеров, а эта связь сама по себе не делает управляющий маркер источником света.',
|
||||
],
|
||||
'gs.north.help': [
|
||||
'The angle is measured clockwise from the plan\'s upward vertical; north is required for window rays, not for the “Follows the Sun” background.',
|
||||
'Угол отсчитывается по часовой стрелке от верхней вертикали плана; север нужен для оконных лучей, а не для фона «Следует за Солнцем».',
|
||||
],
|
||||
'space.north.help': [
|
||||
'Overrides general north for this space; the angle is measured clockwise from the plan\'s upward vertical and is used by window rays.',
|
||||
'Переопределяет общий север для этого пространства; угол отсчитывается по часовой стрелке от верхней вертикали плана и используется оконными лучами.',
|
||||
],
|
||||
'gs.bg_mode.help': [
|
||||
'“Follows the Sun” uses sun.sun, falling back to the browser\'s local clock; Static always shows the selected colour.',
|
||||
'«Следует за Солнцем» использует sun.sun, а при недоступности — локальные часы браузера; статичный режим всегда показывает выбранный цвет.',
|
||||
],
|
||||
'space.bg_mode.help': [
|
||||
'Inherit the general background or override this space with a static colour or “Follows the Sun”.',
|
||||
'Выберите наследование общего фона либо переопределите это пространство статичным цветом или режимом «Следует за Солнцем».',
|
||||
],
|
||||
'space.zero_wall_style.help': [
|
||||
'Dashed zero-thickness walls pass Glow and sun rays, while solid ones block them as zero-area barriers. The choice affects every such wall in the space even when its line is hidden in View.',
|
||||
'Пунктирные стены нулевой толщины пропускают Glow и солнечные лучи, сплошные блокируют их как барьер нулевой площади. Выбор меняет все такие стены пространства, даже когда их линии скрыты в просмотре.',
|
||||
],
|
||||
'device_inbox.show_hidden.help': [
|
||||
'Temporarily shows hidden and disabled markers as editor-only ghosts on the plan. Saved device visibility does not change.',
|
||||
'Временно показывает на плане скрытые и деактивированные маркеры служебными призраками только в редакторе устройств. Сохранённая видимость устройств не меняется.',
|
||||
],
|
||||
};
|
||||
const calls = [...helpSource.matchAll(/this\._help\('([^']+\.help)'\)/g)]
|
||||
.map((match) => match[1]);
|
||||
for (const [key, [english, russian]] of Object.entries(copy)) {
|
||||
assert.ok(calls.includes(key), `${key} has no help trigger`);
|
||||
assert.equal(en[key], english, `canonical English copy changed for ${key}`);
|
||||
assert.equal(ru[key], russian, `canonical Russian copy changed for ${key}`);
|
||||
}
|
||||
assert.equal(Object.keys(copy).length, 11);
|
||||
});
|
||||
|
||||
test('issue 86 removes explanatory hints replaced by contextual help', () => {
|
||||
for (const key of [
|
||||
'marker.controls_hint', 'gs.bg_daynight_hint', 'gs.north_hint', 'space.zero_wall_help',
|
||||
]) {
|
||||
for (const { code } of LANGUAGE_REGISTRY) {
|
||||
assert.equal(dictionaries.get(code)[key], undefined, `${code}:${key} should be removed`);
|
||||
}
|
||||
assert.ok(!helpSource.includes(`'${key}'`), `${key} is still rendered`);
|
||||
}
|
||||
});
|
||||
|
||||
test('light pilot has no duplicate legacy hint copy', () => {
|
||||
for (const key of [
|
||||
'marker.light_role_tip', 'marker.glow_color_tip',
|
||||
@@ -309,10 +382,10 @@ test('light pilot has no duplicate legacy hint copy', () => {
|
||||
});
|
||||
|
||||
test('help hosts do not duplicate their explanation in a title attribute', () => {
|
||||
const calls = [...cardSource.matchAll(/this\._help\('([^']+\.help)'\)/g)];
|
||||
const calls = [...helpSource.matchAll(/this\._help\('([^']+\.help)'\)/g)];
|
||||
assert.ok(calls.length > 0, 'the help affordance pilot disappeared');
|
||||
for (const call of calls) {
|
||||
const prefix = cardSource.slice(Math.max(0, call.index - 700), call.index);
|
||||
const prefix = helpSource.slice(Math.max(0, call.index - 700), call.index);
|
||||
const hosts = [...prefix.matchAll(/<(legend|label|div)\b([^>]*)>/g)];
|
||||
const host = hosts.at(-1);
|
||||
assert.ok(host, `no host element found for ${call[1]}`);
|
||||
|
||||
Reference in New Issue
Block a user