@oicl/openbridge-webcomponents 2.1.0-next.1 → 2.1.0-next.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/bundle/openbridge-webcomponents.bundle.js +390 -301
- package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
- package/custom-elements.json +979 -94
- package/dist/automation/valve-analoge-two-way-icon/valve-analog-two-way-icon.d.ts +25 -1
- package/dist/automation/valve-analoge-two-way-icon/valve-analog-two-way-icon.d.ts.map +1 -1
- package/dist/automation/valve-analoge-two-way-icon/valve-analog-two-way-icon.js +39 -58
- package/dist/automation/valve-analoge-two-way-icon/valve-analog-two-way-icon.js.map +1 -1
- package/dist/building-blocks/alert-list/alert-list-base.d.ts +60 -0
- package/dist/building-blocks/alert-list/alert-list-base.d.ts.map +1 -0
- package/dist/building-blocks/alert-list/alert-list-base.js +191 -0
- package/dist/building-blocks/alert-list/alert-list-base.js.map +1 -0
- package/dist/building-blocks/alert-list/alert-list.css.js.map +1 -1
- package/dist/building-blocks/alert-list/alert-list.d.ts +13 -26
- package/dist/building-blocks/alert-list/alert-list.d.ts.map +1 -1
- package/dist/building-blocks/alert-list/alert-list.js +7 -142
- package/dist/building-blocks/alert-list/alert-list.js.map +1 -1
- package/dist/components/alert-icon/alert-icon.d.ts.map +1 -1
- package/dist/components/alert-icon/alert-icon.js +6 -5
- package/dist/components/alert-icon/alert-icon.js.map +1 -1
- package/dist/components/alert-list-details/alert-list-details.css.js +4 -1
- package/dist/components/alert-list-details/alert-list-details.css.js.map +1 -1
- package/dist/components/alert-menu/alert-menu.css.js +3 -42
- package/dist/components/alert-menu/alert-menu.css.js.map +1 -1
- package/dist/components/alert-menu/alert-menu.d.ts +28 -6
- package/dist/components/alert-menu/alert-menu.d.ts.map +1 -1
- package/dist/components/alert-menu/alert-menu.js +81 -60
- package/dist/components/alert-menu/alert-menu.js.map +1 -1
- package/dist/components/alert-menu-item/alert-menu-item.d.ts +16 -6
- package/dist/components/alert-menu-item/alert-menu-item.d.ts.map +1 -1
- package/dist/components/alert-menu-item/alert-menu-item.js +11 -2
- package/dist/components/alert-menu-item/alert-menu-item.js.map +1 -1
- package/dist/components/number-input-field/number-input-field.css.js +8 -2
- package/dist/components/number-input-field/number-input-field.css.js.map +1 -1
- package/dist/components/number-input-field/number-input-field.d.ts +15 -1
- package/dist/components/number-input-field/number-input-field.d.ts.map +1 -1
- package/dist/components/number-input-field/number-input-field.js +38 -44
- package/dist/components/number-input-field/number-input-field.js.map +1 -1
- package/dist/components/textbox/textbox.css.js +3 -9
- package/dist/components/textbox/textbox.css.js.map +1 -1
- package/dist/components/textbox/textbox.d.ts +3 -0
- package/dist/components/textbox/textbox.d.ts.map +1 -1
- package/dist/components/textbox/textbox.js.map +1 -1
- package/dist/generated/locales/es-419.d.ts +1 -1
- package/dist/generated/locales/es-419.js +1 -1
- package/dist/generated/locales/es-419.js.map +1 -1
- package/dist/navigation-instruments/readout-list-item/readout-list-item.css.js +2 -1
- package/dist/navigation-instruments/readout-list-item/readout-list-item.css.js.map +1 -1
- package/dist/pages/alert-detail-page/alert-detail-page.js +1 -1
- package/dist/pages/alert-detail-page/alert-detail-page.js.map +1 -1
- package/dist/pages/alert-list-page-small/alert-list-page-small-base.d.ts +63 -0
- package/dist/pages/alert-list-page-small/alert-list-page-small-base.d.ts.map +1 -0
- package/dist/pages/alert-list-page-small/alert-list-page-small-base.js +126 -0
- package/dist/pages/alert-list-page-small/alert-list-page-small-base.js.map +1 -0
- package/dist/pages/alert-list-page-small/alert-list-page-small.d.ts +12 -15
- package/dist/pages/alert-list-page-small/alert-list-page-small.d.ts.map +1 -1
- package/dist/pages/alert-list-page-small/alert-list-page-small.js +41 -92
- package/dist/pages/alert-list-page-small/alert-list-page-small.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { customElement } from "../../decorator.js";
|
|
2
|
-
import { getCssVariableValue } from "../../charthelpers/colors.js";
|
|
3
2
|
import __decorate from "../../_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorate.js";
|
|
4
3
|
import number_input_field_default from "./number-input-field.css.js";
|
|
5
4
|
import { formatNumberForDisplay, isAllowedIntermediateInput, parseNumberInput, removeGroupingFromDisplay, valuesEqual } from "./number-input-format.js";
|
|
@@ -25,9 +24,6 @@ var ObcNumberInputFieldPlacement = /* @__PURE__ */ function(ObcNumberInputFieldP
|
|
|
25
24
|
ObcNumberInputFieldPlacement["Right"] = "right";
|
|
26
25
|
return ObcNumberInputFieldPlacement;
|
|
27
26
|
}({});
|
|
28
|
-
var characterWidth = 9.15199279785156;
|
|
29
|
-
var symbolWidth = 4.287994384765653;
|
|
30
|
-
var baseFontSize = 16;
|
|
31
27
|
var ObcNumberInputField = class ObcNumberInputField extends LitElement {
|
|
32
28
|
constructor(..._args) {
|
|
33
29
|
super(..._args);
|
|
@@ -61,6 +57,7 @@ var ObcNumberInputField = class ObcNumberInputField extends LitElement {
|
|
|
61
57
|
this.previousValue = NaN;
|
|
62
58
|
this.previousDisplayText = "";
|
|
63
59
|
this.lastCommittedValue = NaN;
|
|
60
|
+
this.focusFromValueClick = false;
|
|
64
61
|
}
|
|
65
62
|
get displayValue() {
|
|
66
63
|
return this.displayText;
|
|
@@ -84,7 +81,6 @@ var ObcNumberInputField = class ObcNumberInputField extends LitElement {
|
|
|
84
81
|
const parsed = parseNumberInput(raw);
|
|
85
82
|
this.value = parsed;
|
|
86
83
|
this.previousDisplayText = raw;
|
|
87
|
-
this.updateCenterAlignedInputWidth(raw);
|
|
88
84
|
this.dispatchInput();
|
|
89
85
|
}
|
|
90
86
|
isProjectedValueAllowed(projected) {
|
|
@@ -112,6 +108,31 @@ var ObcNumberInputField = class ObcNumberInputField extends LitElement {
|
|
|
112
108
|
onFocus() {
|
|
113
109
|
this.hasFocus = true;
|
|
114
110
|
if (this.readonly) return;
|
|
111
|
+
if (this.focusFromValueClick) {
|
|
112
|
+
this.focusFromValueClick = false;
|
|
113
|
+
requestAnimationFrame(() => void this.ungroupKeepingSelection());
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
this.ungroupDisplay();
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Ungroups a value the user clicked into, once the browser has placed the
|
|
120
|
+
* caret, and moves the caret with its digits. Ungrouping before that shifts
|
|
121
|
+
* the text under the pointer and the caret lands beside the clicked digit.
|
|
122
|
+
*/
|
|
123
|
+
async ungroupKeepingSelection() {
|
|
124
|
+
const input = this.inputElement;
|
|
125
|
+
if (!input || !this.hasFocus) return;
|
|
126
|
+
const grouped = input.value;
|
|
127
|
+
const offsetWithoutGrouping = (offset) => removeGroupingFromDisplay(grouped.slice(0, offset ?? grouped.length), this.getFormatOptions()).length;
|
|
128
|
+
const start = offsetWithoutGrouping(input.selectionStart);
|
|
129
|
+
const end = offsetWithoutGrouping(input.selectionEnd);
|
|
130
|
+
const direction = input.selectionDirection ?? void 0;
|
|
131
|
+
this.ungroupDisplay();
|
|
132
|
+
await this.updateComplete;
|
|
133
|
+
input.setSelectionRange(start, end, direction);
|
|
134
|
+
}
|
|
135
|
+
ungroupDisplay() {
|
|
115
136
|
const source = this.displayOverride || this.displayText;
|
|
116
137
|
this.displayText = removeGroupingFromDisplay(source, this.getFormatOptions());
|
|
117
138
|
this.displayOverride = "";
|
|
@@ -158,22 +179,9 @@ var ObcNumberInputField = class ObcNumberInputField extends LitElement {
|
|
|
158
179
|
if (!this.shouldUpdateValue && this.inputElement) return this.inputElement.value;
|
|
159
180
|
return this.displayText;
|
|
160
181
|
}
|
|
161
|
-
updateCenterAlignedInputWidth(value) {
|
|
162
|
-
if (this.textAlign !== "center") {
|
|
163
|
-
this.style.removeProperty("--obc-number-input-center-width");
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
const fontSize = Number.parseFloat(getCssVariableValue(this, "--global-typography-instrument-value-regular-font-size"));
|
|
167
|
-
const characters = value.replaceAll(/[.,]/g, "");
|
|
168
|
-
const symbols = value.length - characters.length;
|
|
169
|
-
const calculatedWidth = characters.length * characterWidth + symbols * symbolWidth;
|
|
170
|
-
const measuredWidth = Math.ceil(calculatedWidth * fontSize / baseFontSize);
|
|
171
|
-
this.style.setProperty("--obc-number-input-center-width", `${measuredWidth}px`);
|
|
172
|
-
}
|
|
173
182
|
firstUpdated() {
|
|
174
183
|
if (!this.displayText && !this.displayOverride) this.displayText = this.formatValueForDisplay(this.value);
|
|
175
184
|
this.lastCommittedValue = this.value;
|
|
176
|
-
this.updateCenterAlignedInputWidth(this.getEffectiveDisplay());
|
|
177
185
|
}
|
|
178
186
|
get isEmpty() {
|
|
179
187
|
if (this.inputElement) return this.inputElement.value.trim().length === 0;
|
|
@@ -195,7 +203,6 @@ var ObcNumberInputField = class ObcNumberInputField extends LitElement {
|
|
|
195
203
|
}
|
|
196
204
|
updated() {
|
|
197
205
|
if (this.rejectDuplicateUpdates && !valuesEqual(this.value, this.previousValue) && (this.previousDisplayText !== this.displayText || !this.hasFocus)) this.previousValue = this.value;
|
|
198
|
-
this.updateCenterAlignedInputWidth(this.getEffectiveDisplay());
|
|
199
206
|
}
|
|
200
207
|
renderFooterText(text, isError) {
|
|
201
208
|
if (!text) return nothing;
|
|
@@ -212,33 +219,20 @@ var ObcNumberInputField = class ObcNumberInputField extends LitElement {
|
|
|
212
219
|
${text}
|
|
213
220
|
</div>`;
|
|
214
221
|
}
|
|
222
|
+
/**
|
|
223
|
+
* Keeps focus where it is while the chrome around the value is clicked.
|
|
224
|
+
* The wrapper is a `<label>`, so the click itself focuses the input; without
|
|
225
|
+
* this the pointerdown would blur it first and commit an unfinished edit.
|
|
226
|
+
* A click on the value itself is the browser's; it is only noted, so the
|
|
227
|
+
* focus it causes ungroups the value without moving the caret.
|
|
228
|
+
*/
|
|
215
229
|
onPointerDown(e) {
|
|
216
|
-
if (this.disabled) return;
|
|
217
|
-
if (this.
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
e.preventDefault();
|
|
221
|
-
this.inputElement.focus();
|
|
222
|
-
const inputBox = this.inputElement.getBoundingClientRect();
|
|
223
|
-
let selectionStart;
|
|
224
|
-
if (e.clientX < inputBox.left) selectionStart = 0;
|
|
225
|
-
else if (e.clientX > inputBox.right) selectionStart = this.inputElement.value.length;
|
|
226
|
-
else {
|
|
227
|
-
const mouseX = e.clientX;
|
|
228
|
-
let inputX = inputBox.right;
|
|
229
|
-
const text = this.inputElement.value;
|
|
230
|
-
for (let i = text.length - 1; i >= 0; i--) {
|
|
231
|
-
const width = text[i].match(/[.,]/) ? symbolWidth : characterWidth;
|
|
232
|
-
if (mouseX > inputX - width / 2) {
|
|
233
|
-
selectionStart = i + 1;
|
|
234
|
-
break;
|
|
235
|
-
}
|
|
236
|
-
inputX -= width;
|
|
237
|
-
}
|
|
238
|
-
if (selectionStart === void 0) selectionStart = 0;
|
|
239
|
-
}
|
|
240
|
-
this.inputElement.setSelectionRange(selectionStart, selectionStart);
|
|
230
|
+
if (this.disabled || this.readonly) return;
|
|
231
|
+
if (e.target === this.inputElement) {
|
|
232
|
+
this.focusFromValueClick = !this.hasFocus;
|
|
233
|
+
return;
|
|
241
234
|
}
|
|
235
|
+
e.preventDefault();
|
|
242
236
|
}
|
|
243
237
|
render() {
|
|
244
238
|
const hasHelperOrError = Boolean(this.helperText) || Boolean(this.error && this.errorText);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"number-input-field.js","names":[],"sources":["../../../src/components/number-input-field/number-input-field.ts"],"sourcesContent":["import {\n LitElement,\n html,\n nothing,\n unsafeCSS,\n TemplateResult,\n PropertyValues,\n} from 'lit';\nimport {property, state, query} from 'lit/decorators.js';\nimport {ifDefined} from 'lit/directives/if-defined.js';\nimport componentStyle from './number-input-field.css?inline';\nimport {classMap} from 'lit/directives/class-map.js';\nimport {customElement} from '../../decorator.js';\nimport {\n formatNumberForDisplay,\n isAllowedIntermediateInput,\n NumberInputFormatOptions,\n parseNumberInput,\n removeGroupingFromDisplay,\n valuesEqual,\n} from './number-input-format.js';\nimport {getCssVariableValue} from '../../charthelpers/colors.js';\n\nexport type ObcNumberInputFieldInputEvent = CustomEvent<{value: number}>;\nexport type ObcNumberInputFieldChangeEvent = CustomEvent<{value: number}>;\n\nexport enum ObcNumberInputFieldTextAlign {\n Center = 'center',\n Right = 'right',\n RightUnitOutside = 'right-unit-outside',\n}\n\nexport enum ObcNumberInputFieldSize {\n Regular = 'regular',\n Large = 'large',\n}\n\nexport enum ObcNumberInputFieldPlacement {\n Left = 'left',\n Center = 'center',\n Right = 'right',\n}\n\nconst characterWidth = 9.15199279785156;\nconst symbolWidth = 4.287994384765653;\nconst baseFontSize = 16;\n/**\n * `<obc-number-input-field>` – A specialized input field for numerical values with optional unit display.\n *\n * @availableWhen errorText error==true\n * @property rejectUpdatesOnFocus - If true, the input field will not update its value on focus\n * @property rejectUpdates - If true, the value will only be initially set, and not updated on change\n * @property rejectDuplicateUpdates - If true, the input field will not update its value if the value is the same as the previous value\n * This is useful to avoid React re-rendering to reset the value.\n * @property name - Name attribute for form integration\n * @property maxlength - Maximum number of characters allowed\n * @property minlength - Minimum number of characters required\n * @availableWhen hasLabelIcon label!=''\n * @availableWhen labelPlacement label!=''\n * @availableWhen hasHelperIcon helperText!='' || (error==true && errorText!='')\n * @availableWhen helperPlacement helperText!='' || (error==true && errorText!='')\n * @property squared - Internal property for squared corners, used when input is used in stepper-box\n * @property displayOverride - Optional display text override for controlled consumers (e.g. keyboard-numeric)\n * that manage formatted strings while the committed value may be NaN.\n * @property validationPattern - Optional regex pattern. When set, any keystroke or paste whose resulting\n * value does not match this pattern is blocked at the `beforeinput` stage.\n * When unset, a permissive numeric filter (digits, sign, active separators,\n * whitespace) is applied instead.\n * @slot leading-icon - Icon displayed before the input value (when `hasLeadingIcon` is true)\n * @slot label-icon - Icon displayed before the label text (when `hasLabelIcon` is true)\n * @slot helper-icon - Icon displayed before helper or error text (when `hasHelperIcon` is true)\n * @fires {CustomEvent<{value: number}>} input - When the numeric value changes during editing\n * @fires {CustomEvent<{value: number}>} change - When the value is committed on blur\n * @stable\n */\n@customElement('obc-number-input-field')\nexport class ObcNumberInputField extends LitElement {\n @property({type: Number}) value = NaN;\n @property({type: String}) unit = '';\n @property({type: String}) placeholder = '';\n @property({type: String}) textAlign: ObcNumberInputFieldTextAlign =\n ObcNumberInputFieldTextAlign.Right;\n\n @property({type: Boolean, reflect: true}) disabled = false;\n @property({type: Boolean, reflect: true}) readonly = false;\n @property({type: Boolean, reflect: true}) error = false;\n @property({type: String}) errorText = '';\n @property({type: Boolean}) rejectUpdatesOnFocus = false;\n @property({type: Boolean}) rejectUpdates = false;\n\n @property({type: Boolean}) rejectDuplicateUpdates = false;\n\n @property({type: String}) name = '';\n\n @property({type: Number}) maxlength?: number;\n\n @property({type: Number}) minlength?: number;\n\n @property({type: String}) size: ObcNumberInputFieldSize =\n ObcNumberInputFieldSize.Regular;\n\n @property({type: Boolean}) hasLeadingIcon = false;\n @property({type: String}) helperText = '';\n\n @property({type: String}) label = '';\n @property({type: Boolean}) required = false;\n @property({type: Boolean}) hasLabelIcon = false;\n @property({type: String}) labelPlacement: ObcNumberInputFieldPlacement =\n ObcNumberInputFieldPlacement.Left;\n\n @property({type: Boolean}) hasHelperIcon = false;\n @property({type: String}) helperPlacement: ObcNumberInputFieldPlacement =\n ObcNumberInputFieldPlacement.Left;\n\n @property({type: Boolean}) squared = false;\n\n @property({type: String, attribute: false}) displayOverride = '';\n\n @property({type: String}) decimalSeparator?: string;\n @property({type: String}) groupSeparator?: string;\n @property({type: Number}) minFractionDigits = 0;\n @property({type: Number}) maxFractionDigits?: number | undefined;\n\n @property({type: String}) validationPattern = '';\n\n @state() private hasFocus = false;\n @state() private displayText = '';\n @state() private previousValue = NaN;\n @state() private previousDisplayText = '';\n @state() private lastCommittedValue = NaN;\n\n @query('.value-input') private inputElement?: HTMLInputElement;\n\n get displayValue(): string {\n return this.displayText;\n }\n\n private getFormatOptions(): NumberInputFormatOptions {\n return {\n decimalSeparator: this.decimalSeparator,\n groupSeparator: this.groupSeparator,\n minFractionDigits: this.minFractionDigits,\n maxFractionDigits: this.maxFractionDigits,\n };\n }\n\n private formatValueForDisplay(value: number): string {\n return formatNumberForDisplay(value, this.getFormatOptions());\n }\n\n private onInput(e: Event) {\n e.stopPropagation();\n const raw = (e.target as HTMLInputElement).value;\n this.displayText = raw;\n this.displayOverride = '';\n const parsed = parseNumberInput(raw);\n this.value = parsed;\n this.previousDisplayText = raw;\n this.updateCenterAlignedInputWidth(raw);\n this.dispatchInput();\n }\n\n private isProjectedValueAllowed(projected: string): boolean {\n if (this.validationPattern) {\n let regex: RegExp;\n try {\n // Anchor the consumer pattern so it must match the whole projected\n // value rather than any substring (e.g. `[0-9]` must not pass `a1`).\n regex = new RegExp(`^(?:${this.validationPattern})$`);\n } catch {\n // Invalid pattern: fall back to the numeric filter instead of\n // allowing arbitrary input.\n return isAllowedIntermediateInput(projected, this.getFormatOptions());\n }\n return regex.test(projected);\n }\n return isAllowedIntermediateInput(projected, this.getFormatOptions());\n }\n\n private onBeforeInput(e: InputEvent) {\n if (this.disabled || this.readonly) return;\n const input = e.target as HTMLInputElement;\n\n const incoming = e.data ?? e.dataTransfer?.getData('text/plain') ?? null;\n // Deletions, history, and formatting (`insertLineBreak`, `historyUndo`,\n // `deleteContentBackward`, etc.) have `data === null` and no transferable\n // text — always allow them.\n if (incoming === null) return;\n\n const start = input.selectionStart ?? input.value.length;\n const end = input.selectionEnd ?? input.value.length;\n const projected =\n input.value.slice(0, start) + incoming + input.value.slice(end);\n\n if (!this.isProjectedValueAllowed(projected)) {\n e.preventDefault();\n }\n }\n\n private onFocus() {\n this.hasFocus = true;\n // A read-only field has nothing to edit, so it keeps its formatted display\n // instead of switching to the ungrouped editing representation.\n if (this.readonly) return;\n const source = this.displayOverride || this.displayText;\n this.displayText = removeGroupingFromDisplay(\n source,\n this.getFormatOptions()\n );\n this.displayOverride = '';\n }\n\n private onBlur() {\n this.hasFocus = false;\n if (this.readonly) return;\n this.commitDisplay();\n if (!valuesEqual(this.value, this.lastCommittedValue)) {\n this.lastCommittedValue = this.value;\n this.dispatchChange();\n }\n }\n\n private commitDisplay() {\n const trimmed = this.displayText.trim();\n if (trimmed === '') {\n this.value = NaN;\n this.displayText = '';\n this.displayOverride = '';\n return;\n }\n\n const forCommit = trimmed.replace(/[.,]$/, '');\n const parsed = parseNumberInput(forCommit);\n\n if (Number.isFinite(parsed)) {\n this.value = parsed;\n this.displayText = this.formatValueForDisplay(parsed);\n } else {\n this.value = NaN;\n }\n this.displayOverride = '';\n }\n\n private dispatchInput() {\n this.dispatchEvent(\n new CustomEvent('input', {\n detail: {value: this.value},\n })\n );\n }\n\n private dispatchChange() {\n this.dispatchEvent(\n new CustomEvent('change', {\n detail: {value: this.value},\n })\n );\n }\n\n private get shouldUpdateValue(): boolean {\n if (this.rejectUpdates) return false;\n if (this.rejectUpdatesOnFocus && this.hasFocus) return false;\n if (\n this.rejectDuplicateUpdates &&\n valuesEqual(this.value, this.previousValue)\n ) {\n return false;\n }\n return true;\n }\n\n private getEffectiveDisplay(): string {\n if (this.displayOverride) {\n return this.displayOverride;\n }\n if (!this.shouldUpdateValue && this.inputElement) {\n return this.inputElement.value;\n }\n return this.displayText;\n }\n\n private updateCenterAlignedInputWidth(value: string) {\n if (this.textAlign !== ObcNumberInputFieldTextAlign.Center) {\n this.style.removeProperty('--obc-number-input-center-width');\n return;\n }\n\n const fontSize = Number.parseFloat(\n getCssVariableValue(\n this,\n '--global-typography-instrument-value-regular-font-size'\n )\n );\n\n const characters = value.replaceAll(/[.,]/g, '');\n const symbols = value.length - characters.length;\n // These values are based on the font size of 16px\n\n const calculatedWidth =\n characters.length * characterWidth + symbols * symbolWidth;\n\n const measuredWidth = Math.ceil(\n (calculatedWidth * fontSize) / baseFontSize\n );\n this.style.setProperty(\n '--obc-number-input-center-width',\n `${measuredWidth}px`\n );\n }\n\n override firstUpdated() {\n if (!this.displayText && !this.displayOverride) {\n this.displayText = this.formatValueForDisplay(this.value);\n }\n this.lastCommittedValue = this.value;\n this.updateCenterAlignedInputWidth(this.getEffectiveDisplay());\n }\n\n private get isEmpty(): boolean {\n if (this.inputElement) {\n return this.inputElement.value.trim().length === 0;\n }\n return isNaN(this.value);\n }\n\n override willUpdate(changedProperties: PropertyValues) {\n const formatPropsChanged =\n changedProperties.has('decimalSeparator') ||\n changedProperties.has('groupSeparator') ||\n changedProperties.has('minFractionDigits') ||\n changedProperties.has('maxFractionDigits');\n\n if (changedProperties.has('value') && this.shouldUpdateValue) {\n if (!this.hasFocus) {\n this.displayText = this.formatValueForDisplay(this.value);\n this.displayOverride = '';\n this.lastCommittedValue = this.value;\n }\n } else if (formatPropsChanged && !this.hasFocus && this.shouldUpdateValue) {\n this.displayText = this.formatValueForDisplay(this.value);\n this.displayOverride = '';\n }\n\n if (\n changedProperties.has('value') &&\n !this.shouldUpdateValue &&\n this.inputElement\n ) {\n this.value = parseNumberInput(this.inputElement.value);\n }\n }\n\n override updated() {\n if (\n this.rejectDuplicateUpdates &&\n !valuesEqual(this.value, this.previousValue) &&\n (this.previousDisplayText !== this.displayText || !this.hasFocus)\n ) {\n this.previousValue = this.value;\n }\n\n this.updateCenterAlignedInputWidth(this.getEffectiveDisplay());\n }\n\n private renderFooterText(\n text: string,\n isError: boolean\n ): TemplateResult | typeof nothing {\n if (!text) return nothing;\n return html`<div\n id=\"helper-text\"\n class=${classMap({\n [isError ? 'error-text' : 'helper-text']: true,\n [`helper-placement-${this.helperPlacement}`]: true,\n })}\n >\n ${\n this.hasHelperIcon\n ? html`<div class=\"helper-icon\">\n <slot name=\"helper-icon\"></slot>\n </div>`\n : nothing\n }\n ${text}\n </div>`;\n }\n\n private onPointerDown(e: PointerEvent) {\n if (this.disabled) return;\n if (this.readonly) return;\n if (this.inputElement) {\n e.stopPropagation();\n e.preventDefault();\n this.inputElement.focus();\n const inputBox = this.inputElement.getBoundingClientRect();\n let selectionStart: number | undefined;\n if (e.clientX < inputBox.left) {\n // set marker at the left edge of the input\n selectionStart = 0;\n } else if (e.clientX > inputBox.right) {\n // set marker at the right edge of the input\n selectionStart = this.inputElement.value.length;\n } else {\n // set marker at the mouse position\n // Start from the right side of the input and move left until the mouse position is found\n // This is done to set the marker also at label touch.\n // Starts from the right since the label is right aligned.\n const mouseX = e.clientX;\n let inputX = inputBox.right;\n const text = this.inputElement.value;\n for (let i = text.length - 1; i >= 0; i--) {\n const char = text[i];\n const isSymbol = char.match(/[.,]/);\n const width = isSymbol ? symbolWidth : characterWidth;\n if (mouseX > inputX - width / 2) {\n selectionStart = i + 1;\n break;\n }\n inputX -= width;\n }\n if (selectionStart === undefined) {\n selectionStart = 0;\n }\n }\n this.inputElement.setSelectionRange(selectionStart, selectionStart);\n }\n }\n\n override render() {\n const hasHelperOrError =\n Boolean(this.helperText) || Boolean(this.error && this.errorText);\n const unitInside =\n this.unit &&\n this.textAlign !== ObcNumberInputFieldTextAlign.RightUnitOutside;\n const unitOutside =\n this.unit &&\n this.textAlign === ObcNumberInputFieldTextAlign.RightUnitOutside;\n\n const display = this.getEffectiveDisplay();\n\n return html`\n <label\n class=${classMap({\n wrapper: true,\n [`align-${this.textAlign}`]: true,\n [`size-${this.size}`]: true,\n error: this.error,\n disabled: this.disabled,\n readonly: this.readonly,\n empty: this.isEmpty,\n helpertext: hasHelperOrError,\n haslabel: Boolean(this.label),\n squared: this.squared,\n })}\n @pointerdown=${this.onPointerDown}\n >\n ${\n this.label\n ? html`<div\n class=${classMap({\n 'label-text-container': true,\n [`label-placement-${this.labelPlacement}`]: true,\n })}\n >\n ${\n this.hasLabelIcon\n ? html`<div class=\"label-icon\">\n <slot name=\"label-icon\"></slot>\n </div>`\n : nothing\n }\n <span class=\"label-text\">${this.label}</span>\n ${\n this.required\n ? html`<div class=\"required-indicator\"></div>`\n : nothing\n }\n </div>`\n : nothing\n }\n\n <div class=\"horizontal-container\">\n <div class=\"input-field-container\" part=\"input-field-container\">\n ${\n this.hasLeadingIcon\n ? html`<div class=\"leading-icon\">\n <slot name=\"leading-icon\"></slot>\n </div>`\n : nothing\n }\n <div class=\"label-container\">\n <input\n type=\"text\"\n inputmode=\"decimal\"\n class=\"value-input\"\n .value=${display}\n @focus=${this.onFocus}\n @blur=${this.onBlur}\n .placeholder=${this.placeholder}\n name=${ifDefined(this.name || undefined)}\n ?disabled=${this.disabled}\n ?readonly=${this.readonly}\n ?required=${this.required}\n maxlength=${ifDefined(this.maxlength)}\n minlength=${ifDefined(this.minlength)}\n aria-invalid=${this.error ? 'true' : 'false'}\n aria-describedby=${ifDefined(\n hasHelperOrError ? 'helper-text' : undefined\n )}\n autocomplete=\"off\"\n @beforeinput=${this.onBeforeInput}\n @input=${this.onInput}\n />\n ${\n unitInside\n ? html`<span class=\"unit-text\">${this.unit}</span>`\n : nothing\n }\n </div>\n </div>\n ${\n unitOutside\n ? html`<span class=\"unit-text external\">${this.unit}</span>`\n : nothing\n }\n </div>\n\n ${\n this.error && this.errorText\n ? this.renderFooterText(this.errorText, true)\n : this.renderFooterText(this.helperText, false)\n }\n </label>\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-number-input-field': ObcNumberInputField;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"number-input-field.js","names":[],"sources":["../../../src/components/number-input-field/number-input-field.ts"],"sourcesContent":["import {\n LitElement,\n html,\n nothing,\n unsafeCSS,\n TemplateResult,\n PropertyValues,\n} from 'lit';\nimport {property, state, query} from 'lit/decorators.js';\nimport {ifDefined} from 'lit/directives/if-defined.js';\nimport componentStyle from './number-input-field.css?inline';\nimport {classMap} from 'lit/directives/class-map.js';\nimport {customElement} from '../../decorator.js';\nimport {\n formatNumberForDisplay,\n isAllowedIntermediateInput,\n NumberInputFormatOptions,\n parseNumberInput,\n removeGroupingFromDisplay,\n valuesEqual,\n} from './number-input-format.js';\n\nexport type ObcNumberInputFieldInputEvent = CustomEvent<{value: number}>;\nexport type ObcNumberInputFieldChangeEvent = CustomEvent<{value: number}>;\n\nexport enum ObcNumberInputFieldTextAlign {\n Center = 'center',\n Right = 'right',\n RightUnitOutside = 'right-unit-outside',\n}\n\nexport enum ObcNumberInputFieldSize {\n Regular = 'regular',\n Large = 'large',\n}\n\nexport enum ObcNumberInputFieldPlacement {\n Left = 'left',\n Center = 'center',\n Right = 'right',\n}\n\n/**\n * `<obc-number-input-field>` – A specialized input field for numerical values with optional unit display.\n *\n * @availableWhen errorText error==true\n * @property rejectUpdatesOnFocus - If true, the input field will not update its value on focus\n * @property rejectUpdates - If true, the value will only be initially set, and not updated on change\n * @property rejectDuplicateUpdates - If true, the input field will not update its value if the value is the same as the previous value\n * This is useful to avoid React re-rendering to reset the value.\n * @property name - Name attribute for form integration\n * @property maxlength - Maximum number of characters allowed\n * @property minlength - Minimum number of characters required\n * @availableWhen hasLabelIcon label!=''\n * @availableWhen labelPlacement label!=''\n * @availableWhen hasHelperIcon helperText!='' || (error==true && errorText!='')\n * @availableWhen helperPlacement helperText!='' || (error==true && errorText!='')\n * @property squared - Internal property for squared corners, used when input is used in stepper-box\n * @property displayOverride - Optional display text override for controlled consumers (e.g. keyboard-numeric)\n * that manage formatted strings while the committed value may be NaN.\n * @property validationPattern - Optional regex pattern. When set, any keystroke or paste whose resulting\n * value does not match this pattern is blocked at the `beforeinput` stage.\n * When unset, a permissive numeric filter (digits, sign, active separators,\n * whitespace) is applied instead.\n * @slot leading-icon - Icon displayed before the input value (when `hasLeadingIcon` is true)\n * @slot label-icon - Icon displayed before the label text (when `hasLabelIcon` is true)\n * @slot helper-icon - Icon displayed before helper or error text (when `hasHelperIcon` is true)\n * @fires {CustomEvent<{value: number}>} input - When the numeric value changes during editing\n * @fires {CustomEvent<{value: number}>} change - When the value is committed on blur\n * @stable\n */\n@customElement('obc-number-input-field')\nexport class ObcNumberInputField extends LitElement {\n @property({type: Number}) value = NaN;\n @property({type: String}) unit = '';\n @property({type: String}) placeholder = '';\n @property({type: String}) textAlign: ObcNumberInputFieldTextAlign =\n ObcNumberInputFieldTextAlign.Right;\n\n @property({type: Boolean, reflect: true}) disabled = false;\n @property({type: Boolean, reflect: true}) readonly = false;\n @property({type: Boolean, reflect: true}) error = false;\n @property({type: String}) errorText = '';\n @property({type: Boolean}) rejectUpdatesOnFocus = false;\n @property({type: Boolean}) rejectUpdates = false;\n\n @property({type: Boolean}) rejectDuplicateUpdates = false;\n\n @property({type: String}) name = '';\n\n @property({type: Number}) maxlength?: number;\n\n @property({type: Number}) minlength?: number;\n\n @property({type: String}) size: ObcNumberInputFieldSize =\n ObcNumberInputFieldSize.Regular;\n\n @property({type: Boolean}) hasLeadingIcon = false;\n @property({type: String}) helperText = '';\n\n @property({type: String}) label = '';\n @property({type: Boolean}) required = false;\n @property({type: Boolean}) hasLabelIcon = false;\n @property({type: String}) labelPlacement: ObcNumberInputFieldPlacement =\n ObcNumberInputFieldPlacement.Left;\n\n @property({type: Boolean}) hasHelperIcon = false;\n @property({type: String}) helperPlacement: ObcNumberInputFieldPlacement =\n ObcNumberInputFieldPlacement.Left;\n\n @property({type: Boolean}) squared = false;\n\n @property({type: String, attribute: false}) displayOverride = '';\n\n @property({type: String}) decimalSeparator?: string;\n @property({type: String}) groupSeparator?: string;\n @property({type: Number}) minFractionDigits = 0;\n @property({type: Number}) maxFractionDigits?: number | undefined;\n\n @property({type: String}) validationPattern = '';\n\n @state() private hasFocus = false;\n @state() private displayText = '';\n @state() private previousValue = NaN;\n @state() private previousDisplayText = '';\n @state() private lastCommittedValue = NaN;\n\n private focusFromValueClick = false;\n\n @query('.value-input') private inputElement?: HTMLInputElement;\n\n get displayValue(): string {\n return this.displayText;\n }\n\n private getFormatOptions(): NumberInputFormatOptions {\n return {\n decimalSeparator: this.decimalSeparator,\n groupSeparator: this.groupSeparator,\n minFractionDigits: this.minFractionDigits,\n maxFractionDigits: this.maxFractionDigits,\n };\n }\n\n private formatValueForDisplay(value: number): string {\n return formatNumberForDisplay(value, this.getFormatOptions());\n }\n\n private onInput(e: Event) {\n e.stopPropagation();\n const raw = (e.target as HTMLInputElement).value;\n this.displayText = raw;\n this.displayOverride = '';\n const parsed = parseNumberInput(raw);\n this.value = parsed;\n this.previousDisplayText = raw;\n this.dispatchInput();\n }\n\n private isProjectedValueAllowed(projected: string): boolean {\n if (this.validationPattern) {\n let regex: RegExp;\n try {\n // Anchor the consumer pattern so it must match the whole projected\n // value rather than any substring (e.g. `[0-9]` must not pass `a1`).\n regex = new RegExp(`^(?:${this.validationPattern})$`);\n } catch {\n // Invalid pattern: fall back to the numeric filter instead of\n // allowing arbitrary input.\n return isAllowedIntermediateInput(projected, this.getFormatOptions());\n }\n return regex.test(projected);\n }\n return isAllowedIntermediateInput(projected, this.getFormatOptions());\n }\n\n private onBeforeInput(e: InputEvent) {\n if (this.disabled || this.readonly) return;\n const input = e.target as HTMLInputElement;\n\n const incoming = e.data ?? e.dataTransfer?.getData('text/plain') ?? null;\n // Deletions, history, and formatting (`insertLineBreak`, `historyUndo`,\n // `deleteContentBackward`, etc.) have `data === null` and no transferable\n // text — always allow them.\n if (incoming === null) return;\n\n const start = input.selectionStart ?? input.value.length;\n const end = input.selectionEnd ?? input.value.length;\n const projected =\n input.value.slice(0, start) + incoming + input.value.slice(end);\n\n if (!this.isProjectedValueAllowed(projected)) {\n e.preventDefault();\n }\n }\n\n private onFocus() {\n this.hasFocus = true;\n // A read-only field has nothing to edit, so it keeps its formatted display\n // instead of switching to the ungrouped editing representation.\n if (this.readonly) return;\n if (this.focusFromValueClick) {\n this.focusFromValueClick = false;\n requestAnimationFrame(() => void this.ungroupKeepingSelection());\n return;\n }\n this.ungroupDisplay();\n }\n\n /**\n * Ungroups a value the user clicked into, once the browser has placed the\n * caret, and moves the caret with its digits. Ungrouping before that shifts\n * the text under the pointer and the caret lands beside the clicked digit.\n */\n private async ungroupKeepingSelection() {\n const input = this.inputElement;\n if (!input || !this.hasFocus) return;\n const grouped = input.value;\n const offsetWithoutGrouping = (offset: number | null) =>\n removeGroupingFromDisplay(\n grouped.slice(0, offset ?? grouped.length),\n this.getFormatOptions()\n ).length;\n const start = offsetWithoutGrouping(input.selectionStart);\n const end = offsetWithoutGrouping(input.selectionEnd);\n const direction = input.selectionDirection ?? undefined;\n this.ungroupDisplay();\n await this.updateComplete;\n input.setSelectionRange(start, end, direction);\n }\n\n private ungroupDisplay() {\n const source = this.displayOverride || this.displayText;\n this.displayText = removeGroupingFromDisplay(\n source,\n this.getFormatOptions()\n );\n this.displayOverride = '';\n }\n\n private onBlur() {\n this.hasFocus = false;\n if (this.readonly) return;\n this.commitDisplay();\n if (!valuesEqual(this.value, this.lastCommittedValue)) {\n this.lastCommittedValue = this.value;\n this.dispatchChange();\n }\n }\n\n private commitDisplay() {\n const trimmed = this.displayText.trim();\n if (trimmed === '') {\n this.value = NaN;\n this.displayText = '';\n this.displayOverride = '';\n return;\n }\n\n const forCommit = trimmed.replace(/[.,]$/, '');\n const parsed = parseNumberInput(forCommit);\n\n if (Number.isFinite(parsed)) {\n this.value = parsed;\n this.displayText = this.formatValueForDisplay(parsed);\n } else {\n this.value = NaN;\n }\n this.displayOverride = '';\n }\n\n private dispatchInput() {\n this.dispatchEvent(\n new CustomEvent('input', {\n detail: {value: this.value},\n })\n );\n }\n\n private dispatchChange() {\n this.dispatchEvent(\n new CustomEvent('change', {\n detail: {value: this.value},\n })\n );\n }\n\n private get shouldUpdateValue(): boolean {\n if (this.rejectUpdates) return false;\n if (this.rejectUpdatesOnFocus && this.hasFocus) return false;\n if (\n this.rejectDuplicateUpdates &&\n valuesEqual(this.value, this.previousValue)\n ) {\n return false;\n }\n return true;\n }\n\n private getEffectiveDisplay(): string {\n if (this.displayOverride) {\n return this.displayOverride;\n }\n if (!this.shouldUpdateValue && this.inputElement) {\n return this.inputElement.value;\n }\n return this.displayText;\n }\n\n override firstUpdated() {\n if (!this.displayText && !this.displayOverride) {\n this.displayText = this.formatValueForDisplay(this.value);\n }\n this.lastCommittedValue = this.value;\n }\n\n private get isEmpty(): boolean {\n if (this.inputElement) {\n return this.inputElement.value.trim().length === 0;\n }\n return isNaN(this.value);\n }\n\n override willUpdate(changedProperties: PropertyValues) {\n const formatPropsChanged =\n changedProperties.has('decimalSeparator') ||\n changedProperties.has('groupSeparator') ||\n changedProperties.has('minFractionDigits') ||\n changedProperties.has('maxFractionDigits');\n\n if (changedProperties.has('value') && this.shouldUpdateValue) {\n if (!this.hasFocus) {\n this.displayText = this.formatValueForDisplay(this.value);\n this.displayOverride = '';\n this.lastCommittedValue = this.value;\n }\n } else if (formatPropsChanged && !this.hasFocus && this.shouldUpdateValue) {\n this.displayText = this.formatValueForDisplay(this.value);\n this.displayOverride = '';\n }\n\n if (\n changedProperties.has('value') &&\n !this.shouldUpdateValue &&\n this.inputElement\n ) {\n this.value = parseNumberInput(this.inputElement.value);\n }\n }\n\n override updated() {\n if (\n this.rejectDuplicateUpdates &&\n !valuesEqual(this.value, this.previousValue) &&\n (this.previousDisplayText !== this.displayText || !this.hasFocus)\n ) {\n this.previousValue = this.value;\n }\n }\n\n private renderFooterText(\n text: string,\n isError: boolean\n ): TemplateResult | typeof nothing {\n if (!text) return nothing;\n return html`<div\n id=\"helper-text\"\n class=${classMap({\n [isError ? 'error-text' : 'helper-text']: true,\n [`helper-placement-${this.helperPlacement}`]: true,\n })}\n >\n ${\n this.hasHelperIcon\n ? html`<div class=\"helper-icon\">\n <slot name=\"helper-icon\"></slot>\n </div>`\n : nothing\n }\n ${text}\n </div>`;\n }\n\n /**\n * Keeps focus where it is while the chrome around the value is clicked.\n * The wrapper is a `<label>`, so the click itself focuses the input; without\n * this the pointerdown would blur it first and commit an unfinished edit.\n * A click on the value itself is the browser's; it is only noted, so the\n * focus it causes ungroups the value without moving the caret.\n */\n private onPointerDown(e: PointerEvent) {\n if (this.disabled || this.readonly) return;\n if (e.target === this.inputElement) {\n this.focusFromValueClick = !this.hasFocus;\n return;\n }\n e.preventDefault();\n }\n\n override render() {\n const hasHelperOrError =\n Boolean(this.helperText) || Boolean(this.error && this.errorText);\n const unitInside =\n this.unit &&\n this.textAlign !== ObcNumberInputFieldTextAlign.RightUnitOutside;\n const unitOutside =\n this.unit &&\n this.textAlign === ObcNumberInputFieldTextAlign.RightUnitOutside;\n\n const display = this.getEffectiveDisplay();\n\n return html`\n <label\n class=${classMap({\n wrapper: true,\n [`align-${this.textAlign}`]: true,\n [`size-${this.size}`]: true,\n error: this.error,\n disabled: this.disabled,\n readonly: this.readonly,\n empty: this.isEmpty,\n helpertext: hasHelperOrError,\n haslabel: Boolean(this.label),\n squared: this.squared,\n })}\n @pointerdown=${this.onPointerDown}\n >\n ${\n this.label\n ? html`<div\n class=${classMap({\n 'label-text-container': true,\n [`label-placement-${this.labelPlacement}`]: true,\n })}\n >\n ${\n this.hasLabelIcon\n ? html`<div class=\"label-icon\">\n <slot name=\"label-icon\"></slot>\n </div>`\n : nothing\n }\n <span class=\"label-text\">${this.label}</span>\n ${\n this.required\n ? html`<div class=\"required-indicator\"></div>`\n : nothing\n }\n </div>`\n : nothing\n }\n\n <div class=\"horizontal-container\">\n <div class=\"input-field-container\" part=\"input-field-container\">\n ${\n this.hasLeadingIcon\n ? html`<div class=\"leading-icon\">\n <slot name=\"leading-icon\"></slot>\n </div>`\n : nothing\n }\n <div class=\"label-container\">\n <input\n type=\"text\"\n inputmode=\"decimal\"\n class=\"value-input\"\n .value=${display}\n @focus=${this.onFocus}\n @blur=${this.onBlur}\n .placeholder=${this.placeholder}\n name=${ifDefined(this.name || undefined)}\n ?disabled=${this.disabled}\n ?readonly=${this.readonly}\n ?required=${this.required}\n maxlength=${ifDefined(this.maxlength)}\n minlength=${ifDefined(this.minlength)}\n aria-invalid=${this.error ? 'true' : 'false'}\n aria-describedby=${ifDefined(\n hasHelperOrError ? 'helper-text' : undefined\n )}\n autocomplete=\"off\"\n @beforeinput=${this.onBeforeInput}\n @input=${this.onInput}\n />\n ${\n unitInside\n ? html`<span class=\"unit-text\">${this.unit}</span>`\n : nothing\n }\n </div>\n </div>\n ${\n unitOutside\n ? html`<span class=\"unit-text external\">${this.unit}</span>`\n : nothing\n }\n </div>\n\n ${\n this.error && this.errorText\n ? this.renderFooterText(this.errorText, true)\n : this.renderFooterText(this.helperText, false)\n }\n </label>\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-number-input-field': ObcNumberInputField;\n }\n}\n"],"mappings":"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"}
|
|
@@ -19,21 +19,15 @@ var textbox_default = css`* {
|
|
|
19
19
|
letter-spacing: var(--global-typography-generic-l-letter-spacing);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
/* The
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
below. In engines that support text-box-trim the content box collapses to
|
|
26
|
-
the cap height exactly; in Firefox (no text-box-trim) the content keeps its
|
|
27
|
-
natural line box, so align-items:center + overflow:hidden crops it to the
|
|
28
|
-
same height instead. No padding here – the centering provides it.
|
|
29
|
-
(A small top padding could be added later to nudge the text up in Firefox.) */
|
|
22
|
+
/* The box, never clipped: descenders and diacritics paint past its edges. The
|
|
23
|
+
centred content leaves equal padding above and below; without text-box-trim
|
|
24
|
+
the host's zero line-height keeps it centred to within about a pixel. */
|
|
30
25
|
.inner-wrapper {
|
|
31
26
|
box-sizing: border-box;
|
|
32
27
|
display: flex;
|
|
33
28
|
align-items: center;
|
|
34
29
|
justify-content: var(--alignment-justify, flex-end);
|
|
35
30
|
height: var(--height);
|
|
36
|
-
overflow: hidden;
|
|
37
31
|
/* Opt-in: animate a \`size\` change (height + font-size below). Defaults to 0s
|
|
38
32
|
(instant, current behavior) so existing usages and snapshots are unchanged;
|
|
39
33
|
a consumer sets \`--obc-textbox-size-transition\` (e.g. 300ms) to animate the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textbox.css.js","names":[],"sources":["../../../src/components/textbox/textbox.css?inline"],"sourcesContent":[":host {\n display: inline-block;\n line-height: 0;\n}\n\n.wrapper {\n display: inline-flex;\n flex-direction: column;\n width: fit-content;\n --height: 24px;\n --padding: 4px;\n font-family: var(--font-family-main);\n letter-spacing: var(--global-typography-generic-l-letter-spacing);\n}\n\n/* The
|
|
1
|
+
{"version":3,"file":"textbox.css.js","names":[],"sources":["../../../src/components/textbox/textbox.css?inline"],"sourcesContent":[":host {\n display: inline-block;\n line-height: 0;\n}\n\n.wrapper {\n display: inline-flex;\n flex-direction: column;\n width: fit-content;\n --height: 24px;\n --padding: 4px;\n font-family: var(--font-family-main);\n letter-spacing: var(--global-typography-generic-l-letter-spacing);\n}\n\n/* The box, never clipped: descenders and diacritics paint past its edges. The\n centred content leaves equal padding above and below; without text-box-trim\n the host's zero line-height keeps it centred to within about a pixel. */\n.inner-wrapper {\n box-sizing: border-box;\n display: flex;\n align-items: center;\n justify-content: var(--alignment-justify, flex-end);\n height: var(--height);\n /* Opt-in: animate a `size` change (height + font-size below). Defaults to 0s\n (instant, current behavior) so existing usages and snapshots are unchanged;\n a consumer sets `--obc-textbox-size-transition` (e.g. 300ms) to animate the\n swap — used by readout-list-item's setpoint flip-flop. */\n transition: height var(--obc-textbox-size-transition, 0s) ease;\n}\n\n/* The spacer must share the content's exact font metrics so the width it\n reserves equals the rendered content width. font-size-adjust scales the\n font, so it has to match too. */\n.content,\n.length-spacer {\n font-size: calc(var(--height) - 2 * var(--padding));\n font-size-adjust: cap-height 1;\n white-space: nowrap;\n /* Opt-in size animation — see `.inner-wrapper`. */\n transition: font-size var(--obc-textbox-size-transition, 0s) ease;\n}\n\n.content {\n text-box-trim: trim-both;\n text-box-edge: cap alphabetic;\n}\n\n/* Opt-in numeric mode: fixed-width lining numerals so values stay\n column-aligned and width-stable. Applied to the spacer too so the reserved\n width matches the rendered digits exactly. */\n.wrapper.tabular-nums .content,\n.wrapper.tabular-nums .length-spacer {\n font-variant-numeric: tabular-nums lining-nums;\n font-feature-settings:\n \"ss04\" on,\n \"tnum\" on,\n \"lnum\" on;\n}\n\n/* Size override is set on `.wrapper` (not `.inner-wrapper`) so it reaches BOTH\n the visible `.content` AND the sibling `.length-spacer`; otherwise the spacer\n keeps the default (m) `--height` and reserves width at the wrong font size. */\n.wrapper.size-xs {\n --height: 16px;\n}\n\n.wrapper.size-s {\n --height: 20px;\n}\n\n.wrapper.size-m {\n --height: 24px;\n}\n\n.wrapper.size-l {\n --height: 32px;\n}\n\n.wrapper.size-xl {\n --height: 40px;\n}\n\n.wrapper.font-weight-regular {\n font-weight: var(--global-typography-generic-l-font-weight-regular);\n}\n\n.wrapper.font-weight-semibold {\n font-weight: var(--global-typography-generic-l-font-weight-medium);\n}\n\n.wrapper.font-weight-bold {\n font-weight: var(--global-typography-generic-l-font-weight-bold);\n}\n\n.wrapper.alignment-left {\n --alignment-justify: flex-start;\n}\n\n.wrapper.alignment-center {\n --alignment-justify: center;\n}\n\n.wrapper.alignment-right {\n --alignment-justify: flex-end;\n}\n\n/* Reserves the box width from the `length` slot without occupying vertical\n space. Acts as a minimum width so the box does not resize as visible\n text changes. */\n.length-spacer {\n height: 0;\n opacity: 0;\n visibility: hidden;\n overflow: hidden;\n}\n"],"mappings":""}
|
|
@@ -42,6 +42,9 @@ export declare enum ObcTextboxFontWeight {
|
|
|
42
42
|
* - **Reserved width:** content placed in the `length` slot reserves a minimum
|
|
43
43
|
* width invisibly, so the box does not resize as the visible text changes.
|
|
44
44
|
* The box always shows all content – it never crops.
|
|
45
|
+
* - **Cap-to-baseline frame:** the box spans the cap top to the baseline plus
|
|
46
|
+
* the padding; descenders and diacritics paint past its edges, so an
|
|
47
|
+
* ancestor that clips must leave room for them.
|
|
45
48
|
*
|
|
46
49
|
* ## Usage Guidelines
|
|
47
50
|
* - Pass the longest expected string to the `length` slot (e.g. `"888.8"` or
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textbox.d.ts","sourceRoot":"","sources":["../../../src/components/textbox/textbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAkB,MAAM,KAAK,CAAC;AAMhD,oBAAY,mBAAmB;IAC7B,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,KAAK,UAAU;CAChB;AAED,oBAAY,cAAc;IACxB,EAAE,OAAO;IACT,CAAC,MAAM;IACP,CAAC,MAAM;IACP,CAAC,MAAM;IACP,EAAE,OAAO;CACV;AAED,oBAAY,oBAAoB;IAC9B,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,IAAI,SAAS;CACd;AAED
|
|
1
|
+
{"version":3,"file":"textbox.d.ts","sourceRoot":"","sources":["../../../src/components/textbox/textbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAkB,MAAM,KAAK,CAAC;AAMhD,oBAAY,mBAAmB;IAC7B,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,KAAK,UAAU;CAChB;AAED,oBAAY,cAAc;IACxB,EAAE,OAAO;IACT,CAAC,MAAM;IACP,CAAC,MAAM;IACP,CAAC,MAAM;IACP,EAAE,OAAO;CACV;AAED,oBAAY,oBAAoB;IAC9B,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,IAAI,SAAS;CACd;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,qBACa,UAAW,SAAQ,UAAU;IACd,SAAS,EAAE,mBAAmB,CAC5B;IACF,IAAI,EAAE,cAAc,CAAoB;IACxC,UAAU,EAAE,oBAAoB,CAC3B;IACJ,WAAW,UAAS;IAEtC,MAAM;IAuBf,OAAgB,MAAM,0BAA6B;CACpD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,aAAa,EAAE,UAAU,CAAC;KAC3B;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textbox.js","names":[],"sources":["../../../src/components/textbox/textbox.ts"],"sourcesContent":["import {LitElement, html, unsafeCSS} from 'lit';\nimport {customElement} from '../../decorator.js';\nimport componentStyle from './textbox.css?inline';\nimport {property} from 'lit/decorators.js';\nimport {classMap} from 'lit/directives/class-map.js';\n\nexport enum ObcTextboxAlignment {\n Left = 'left',\n Center = 'center',\n Right = 'right',\n}\n\nexport enum ObcTextboxSize {\n xs = 'xs',\n s = 's',\n m = 'm',\n l = 'l',\n xl = 'xl',\n}\n\nexport enum ObcTextboxFontWeight {\n regular = 'regular',\n semibold = 'semibold',\n bold = 'bold',\n}\n\n/**\n * `<obc-textbox>` – A text container that renders inline text at a\n * precise, cap-height-trimmed size with configurable alignment and reservable\n * width.\n *\n * Use it to present short, read-only strings – such as values, labels, or\n * units – where vertical metrics must line up exactly across rows and the\n * horizontal footprint should stay stable while the text changes (for example\n * a numeric value that updates frequently). Synonyms: text container, value\n * box, label box.\n *\n * ## Features / Variants\n * - **Size:** `xs`, `s`, `m` (default), `l`, `xl` – each maps to a fixed box\n * height (16 / 20 / 24 / 32 / 40 px) with 4px padding above and below, giving\n * cap heights of 8 / 12 / 16 / 24 / 32 px so text aligns to a predictable\n * grid.\n * - **Font weight:** `regular` (default), `semibold`, `bold`.\n * - **Tabular numbers:** `tabularNums` (default off) renders digits as\n * fixed-width, lining numerals (`tabular-nums lining-nums` + the `ss04`/`tnum`/\n * `lnum` features) so numeric values stay column-aligned and stable in width\n * as they update – use it for readouts and other live numeric displays.\n * - **Alignment:** `left`, `center`, `right` (default) – positions the text\n * within the box's width when the box is wider than the content.\n * - **Reserved width:** content placed in the `length` slot reserves a minimum\n * width invisibly, so the box does not resize as the visible text changes.\n * The box always shows all content – it never crops.\n *\n * ## Usage Guidelines\n * - Pass the longest expected string to the `length` slot (e.g. `\"888.8\"` or\n * `\"Wind speed\"`) so the box reserves space and does not jump in width as the\n * visible value updates.\n * - This is a display primitive for static text – use an input component for\n * editable values.\n *\n * ## Slots\n * | Slot | Renders when… | Purpose |\n * |-----------|--------------------|------------------------------------------------------|\n * | (default) | Always | The visible text content. |\n * | `length` | Always (invisible) | Reserves a minimum width based on its content width. |\n *\n * @slot - The visible text content.\n * @slot length - Reserves a minimum width based on its content width.\n * @stable\n */\n@customElement('obc-textbox')\nexport class ObcTextbox extends LitElement {\n @property({type: String}) alignment: ObcTextboxAlignment =\n ObcTextboxAlignment.Right;\n @property({type: String}) size: ObcTextboxSize = ObcTextboxSize.m;\n @property({type: String}) fontWeight: ObcTextboxFontWeight =\n ObcTextboxFontWeight.regular;\n @property({type: Boolean}) tabularNums = false;\n\n override render() {\n return html`\n <div\n class=${classMap({\n wrapper: true,\n [`alignment-${this.alignment}`]: true,\n [`size-${this.size}`]: true,\n [`font-weight-${this.fontWeight}`]: true,\n 'tabular-nums': this.tabularNums,\n })}\n >\n <div class=\"inner-wrapper\">\n <div class=\"content\">\n <slot></slot>\n </div>\n </div>\n <div class=\"length-spacer\" aria-hidden=\"true\">\n <slot name=\"length\"></slot>\n </div>\n </div>\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-textbox': ObcTextbox;\n }\n}\n"],"mappings":";;;;;;;AAMA,IAAY,sBAAL,yBAAA,qBAAA;CACL,oBAAA,UAAA;CACA,oBAAA,YAAA;CACA,oBAAA,WAAA;;AACF,EAAA,CAAA,CAAA;AAEA,IAAY,iBAAL,yBAAA,gBAAA;CACL,eAAA,QAAA;CACA,eAAA,OAAA;CACA,eAAA,OAAA;CACA,eAAA,OAAA;CACA,eAAA,QAAA;;AACF,EAAA,CAAA,CAAA;AAEA,IAAY,uBAAL,yBAAA,sBAAA;CACL,qBAAA,aAAA;CACA,qBAAA,cAAA;CACA,qBAAA,UAAA;;AACF,EAAA,CAAA,CAAA;
|
|
1
|
+
{"version":3,"file":"textbox.js","names":[],"sources":["../../../src/components/textbox/textbox.ts"],"sourcesContent":["import {LitElement, html, unsafeCSS} from 'lit';\nimport {customElement} from '../../decorator.js';\nimport componentStyle from './textbox.css?inline';\nimport {property} from 'lit/decorators.js';\nimport {classMap} from 'lit/directives/class-map.js';\n\nexport enum ObcTextboxAlignment {\n Left = 'left',\n Center = 'center',\n Right = 'right',\n}\n\nexport enum ObcTextboxSize {\n xs = 'xs',\n s = 's',\n m = 'm',\n l = 'l',\n xl = 'xl',\n}\n\nexport enum ObcTextboxFontWeight {\n regular = 'regular',\n semibold = 'semibold',\n bold = 'bold',\n}\n\n/**\n * `<obc-textbox>` – A text container that renders inline text at a\n * precise, cap-height-trimmed size with configurable alignment and reservable\n * width.\n *\n * Use it to present short, read-only strings – such as values, labels, or\n * units – where vertical metrics must line up exactly across rows and the\n * horizontal footprint should stay stable while the text changes (for example\n * a numeric value that updates frequently). Synonyms: text container, value\n * box, label box.\n *\n * ## Features / Variants\n * - **Size:** `xs`, `s`, `m` (default), `l`, `xl` – each maps to a fixed box\n * height (16 / 20 / 24 / 32 / 40 px) with 4px padding above and below, giving\n * cap heights of 8 / 12 / 16 / 24 / 32 px so text aligns to a predictable\n * grid.\n * - **Font weight:** `regular` (default), `semibold`, `bold`.\n * - **Tabular numbers:** `tabularNums` (default off) renders digits as\n * fixed-width, lining numerals (`tabular-nums lining-nums` + the `ss04`/`tnum`/\n * `lnum` features) so numeric values stay column-aligned and stable in width\n * as they update – use it for readouts and other live numeric displays.\n * - **Alignment:** `left`, `center`, `right` (default) – positions the text\n * within the box's width when the box is wider than the content.\n * - **Reserved width:** content placed in the `length` slot reserves a minimum\n * width invisibly, so the box does not resize as the visible text changes.\n * The box always shows all content – it never crops.\n * - **Cap-to-baseline frame:** the box spans the cap top to the baseline plus\n * the padding; descenders and diacritics paint past its edges, so an\n * ancestor that clips must leave room for them.\n *\n * ## Usage Guidelines\n * - Pass the longest expected string to the `length` slot (e.g. `\"888.8\"` or\n * `\"Wind speed\"`) so the box reserves space and does not jump in width as the\n * visible value updates.\n * - This is a display primitive for static text – use an input component for\n * editable values.\n *\n * ## Slots\n * | Slot | Renders when… | Purpose |\n * |-----------|--------------------|------------------------------------------------------|\n * | (default) | Always | The visible text content. |\n * | `length` | Always (invisible) | Reserves a minimum width based on its content width. |\n *\n * @slot - The visible text content.\n * @slot length - Reserves a minimum width based on its content width.\n * @stable\n */\n@customElement('obc-textbox')\nexport class ObcTextbox extends LitElement {\n @property({type: String}) alignment: ObcTextboxAlignment =\n ObcTextboxAlignment.Right;\n @property({type: String}) size: ObcTextboxSize = ObcTextboxSize.m;\n @property({type: String}) fontWeight: ObcTextboxFontWeight =\n ObcTextboxFontWeight.regular;\n @property({type: Boolean}) tabularNums = false;\n\n override render() {\n return html`\n <div\n class=${classMap({\n wrapper: true,\n [`alignment-${this.alignment}`]: true,\n [`size-${this.size}`]: true,\n [`font-weight-${this.fontWeight}`]: true,\n 'tabular-nums': this.tabularNums,\n })}\n >\n <div class=\"inner-wrapper\">\n <div class=\"content\">\n <slot></slot>\n </div>\n </div>\n <div class=\"length-spacer\" aria-hidden=\"true\">\n <slot name=\"length\"></slot>\n </div>\n </div>\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-textbox': ObcTextbox;\n }\n}\n"],"mappings":";;;;;;;AAMA,IAAY,sBAAL,yBAAA,qBAAA;CACL,oBAAA,UAAA;CACA,oBAAA,YAAA;CACA,oBAAA,WAAA;;AACF,EAAA,CAAA,CAAA;AAEA,IAAY,iBAAL,yBAAA,gBAAA;CACL,eAAA,QAAA;CACA,eAAA,OAAA;CACA,eAAA,OAAA;CACA,eAAA,OAAA;CACA,eAAA,QAAA;;AACF,EAAA,CAAA,CAAA;AAEA,IAAY,uBAAL,yBAAA,sBAAA;CACL,qBAAA,aAAA;CACA,qBAAA,cAAA;CACA,qBAAA,UAAA;;AACF,EAAA,CAAA,CAAA;AAkDO,IAAM,aAAN,MAAM,mBAAmB,WAAW;;;;;;EAMA,KAAA,cAAA;;CAEzC,SAAkB;EAChB,OAAO,IAAI;;gBAEC,SAAS;GACf,SAAS;IACR,aAAa,KAAK,cAAc;IAChC,QAAQ,KAAK,SAAS;IACtB,eAAe,KAAK,eAAe;GACpC,gBAAgB,KAAK;EACvB,CAAC,EAAE;;;;;;;;;;;;CAYT;;EAEyB,KAAA,SAAA,UAAU,eAAc;;AACnD;AA/BG,WAAA,CAAA,SAAS,EAAC,MAAM,OAAM,CAAC,CAAA,GAAA,WAAA,WAAA,aAAA,KAAA,CAAA;AAEvB,WAAA,CAAA,SAAS,EAAC,MAAM,OAAM,CAAC,CAAA,GAAA,WAAA,WAAA,QAAA,KAAA,CAAA;AACvB,WAAA,CAAA,SAAS,EAAC,MAAM,OAAM,CAAC,CAAA,GAAA,WAAA,WAAA,cAAA,KAAA,CAAA;AAEvB,WAAA,CAAA,SAAS,EAAC,MAAM,QAAO,CAAC,CAAA,GAAA,WAAA,WAAA,eAAA,KAAA,CAAA;AAP1B,aAAA,WAAA,CAAA,cAAc,aAAa,CAAA,GAAA,UAAA"}
|
|
@@ -24,8 +24,8 @@ export declare const templates: {
|
|
|
24
24
|
s16fccc311f4779f6: string;
|
|
25
25
|
seb27af82aef6a03e: string;
|
|
26
26
|
sfa32c219a0764262: string;
|
|
27
|
-
s5ba9818f6a39054c: string;
|
|
28
27
|
sa45a194b58837e4f: string;
|
|
28
|
+
s5ba9818f6a39054c: string;
|
|
29
29
|
sa6ef04345891fb38: string;
|
|
30
30
|
s3cf89cb47fdde7e9: string;
|
|
31
31
|
s47278872f6826da8: string;
|
|
@@ -27,8 +27,8 @@ var templates = {
|
|
|
27
27
|
"s16fccc311f4779f6": `Rectified`,
|
|
28
28
|
"seb27af82aef6a03e": `No rectified alerts`,
|
|
29
29
|
"sfa32c219a0764262": `ACK`,
|
|
30
|
-
"s5ba9818f6a39054c": `Go to the 'Alert list' for more details or to manage existing alerts.`,
|
|
31
30
|
"sa45a194b58837e4f": `Active`,
|
|
31
|
+
"s5ba9818f6a39054c": `Go to the 'Alert list' for more details or to manage existing alerts.`,
|
|
32
32
|
"sa6ef04345891fb38": `ACK visible`,
|
|
33
33
|
"s3cf89cb47fdde7e9": `Link`,
|
|
34
34
|
"s47278872f6826da8": `Dusk`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"es-419.js","names":[],"sources":["../../../src/generated/locales/es-419.ts"],"sourcesContent":["\n // Do not modify this file by hand!\n // Re-generate this file by running lit-localize\n\n \n \n\n /* eslint-disable no-irregular-whitespace */\n /* eslint-disable @typescript-eslint/no-explicit-any */\n\n export const templates = {\n 's0f3699a7bd401f61': `Noche`,\n's1125d159f7e64df5': `Pantalla`,\n's8119af112f965c78': `Brillantez`,\n'sa7f8e003ff63ef9f': `No alertas activas`,\n'se0955919920ee87d': `Día`,\n'scd93bdcb7863611a': `Alarm`,\n's34be76c6b1eadbef': `Warning`,\n'sf11564cc75a8d5a6': `Caution`,\n'sa45f3300b97dabe8': `Critical`,\n's9deeefd89ca8a81d': `High`,\n'sac6bdc71f750ac96': `Medium`,\n's24f3a319b88552c1': `Low`,\n'sca9e13f23f0c433e': `Diagnostic`,\n'sf268637d594dacb2': `Shelved`,\n's88d1c1e15ca1aade': `Alerts`,\n's68395a4c26a9e8ac': `Silence`,\n'sf993bb199fefbe04': `All`,\n's01b603dddbaba7b6': `Unacked`,\n'se92d11374fcdf768': `No unacknowledged alerts`,\n's2a2488656f97b746': `No shelved alerts`,\n'sf59d9197d2e50c93': `Blocked`,\n's61a9ee872da3a0cd': `No blocked alerts`,\n's16fccc311f4779f6': `Rectified`,\n'seb27af82aef6a03e': `No rectified alerts`,\n'sfa32c219a0764262': `ACK`,\n's5ba9818f6a39054c': `Go to the 'Alert list' for more details or to manage existing alerts.`,\n'
|
|
1
|
+
{"version":3,"file":"es-419.js","names":[],"sources":["../../../src/generated/locales/es-419.ts"],"sourcesContent":["\n // Do not modify this file by hand!\n // Re-generate this file by running lit-localize\n\n \n \n\n /* eslint-disable no-irregular-whitespace */\n /* eslint-disable @typescript-eslint/no-explicit-any */\n\n export const templates = {\n 's0f3699a7bd401f61': `Noche`,\n's1125d159f7e64df5': `Pantalla`,\n's8119af112f965c78': `Brillantez`,\n'sa7f8e003ff63ef9f': `No alertas activas`,\n'se0955919920ee87d': `Día`,\n'scd93bdcb7863611a': `Alarm`,\n's34be76c6b1eadbef': `Warning`,\n'sf11564cc75a8d5a6': `Caution`,\n'sa45f3300b97dabe8': `Critical`,\n's9deeefd89ca8a81d': `High`,\n'sac6bdc71f750ac96': `Medium`,\n's24f3a319b88552c1': `Low`,\n'sca9e13f23f0c433e': `Diagnostic`,\n'sf268637d594dacb2': `Shelved`,\n's88d1c1e15ca1aade': `Alerts`,\n's68395a4c26a9e8ac': `Silence`,\n'sf993bb199fefbe04': `All`,\n's01b603dddbaba7b6': `Unacked`,\n'se92d11374fcdf768': `No unacknowledged alerts`,\n's2a2488656f97b746': `No shelved alerts`,\n'sf59d9197d2e50c93': `Blocked`,\n's61a9ee872da3a0cd': `No blocked alerts`,\n's16fccc311f4779f6': `Rectified`,\n'seb27af82aef6a03e': `No rectified alerts`,\n'sfa32c219a0764262': `ACK`,\n'sa45a194b58837e4f': `Active`,\n's5ba9818f6a39054c': `Go to the 'Alert list' for more details or to manage existing alerts.`,\n'sa6ef04345891fb38': `ACK visible`,\n's3cf89cb47fdde7e9': `Link`,\n's47278872f6826da8': `Dusk`,\n's9e34794bcfdc6665': `Bright`,\n's33e301ba1f4a6864': `Screen Control`,\n'sc5a5b268010fc312': `Audio muted`,\n's740deeebbea89396': `Audio on`,\n'sb1772b5e873910c2': `Microphone muted`,\n'sae9a175972fdc8a6': `Microphone on`,\n'scdec9ef5c73b26a1': `Wi-Fi`,\n's08e6bd98452e6bb9': `Audio`,\n's232f88877550dfa9': `Microphone`,\n's2eda024d0ca3dbae': `Battery`,\n's7c876ab46924ee3e': `Wi-Fi settings`,\n'scbad6893328e2b26': `Audio settings`,\n'se80af7d953b783b6': `Microphone settings`,\n's77a0727520efc502': `Charging`,\n'sfa0a009c85861b5b': `Powered & not charging`,\n's2d91daeb457fbd1d': `On battery`,\n's67e59d6159bcaa4f': `Battery settings`,\n's9d8b8aa2b404c2c8': `Settings`,\n'sc16e00a7a8b2fde2': `Back`,\n's463b8c4e92751ba5': `Options`,\n'sd2208cd1a767644b': `Disconnect`,\n's40bbf4a98d873400': `Push to talk`,\n's345be9d2d7ce0228': `Usage`,\n's0200a1a60221ccd3': `Battery saving mode`,\n's186609156d69afdc': `Other networks`,\n'sfd77270c3f54f664': `Output`,\n'sdb1595f5c742dfbb': `Input`,\n's37cbecaec58e2192': `Mode`,\n's065289e6cba017c6': `Transcribe`,\n's5e8250fb85d64c23': `Close`,\n's6d8c02aee480af7a': `Menu`,\n's6abb1cd87fe0114e': `Home`,\n's18c92783d4042bbc': `Dimming`,\n'sa48f81f001b893d2': `User`,\n'sf7eeef8b4d6e602d': `Apps`,\n's37a9e8aec5713460': `More`,\n's76b886a513fca0d8': `Username is required`,\n'seb1d48da15e775c9': `Password is required`,\n's5e27738a2e8eb763': `Sign in`,\n's03f42eea72154959': `Username`,\n'sf6e1665c7022a1f8': `Password`,\n's981f6febad4df84a': `Recently signed in`,\n'sbce70cbdb856635e': `Recent`,\n's8506875a9d95f22c': `Use another account`,\n's7cfe12cd14df9950': `Sign out`,\n's5be3c6d61cd9182f': `Notifications`,\n's744d993d03f29851': `Screen`,\n'sa81e2cdaf6921adc': `System`,\n's3374200692e9843d': `No alerts`,\n's6686fcc6d2c8f0bd': `Note`,\n'sfbc33dd48f23752c': `Tag ID`,\n's079a052719914d71': `Category`,\n'sa2b9faa7ad068cfc': `Activated`,\n's35aab6bf5dda3be0': `Alert timer`,\n'sdc7335a13d9e03f5': `Acknowledged`,\n's93c7817bb872836a': `Acknowledged by`,\n'sf2de3605b3655264': `Shelfing timer`,\n's097d821eb8e9069f': `Shelved by`,\n'sa711a6fcc9552dbf': `Readout`,\n };\n "],"mappings":";;;AAUI,IAAa,YAAY;CACvB,qBAAqB;CAC3B,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;AACjB"}
|
|
@@ -226,7 +226,8 @@ obc-readout-block {
|
|
|
226
226
|
gap: var(--global-size-spacing-target-padding);
|
|
227
227
|
flex: 1 1 auto;
|
|
228
228
|
min-inline-size: 0;
|
|
229
|
-
overflow: clip;
|
|
229
|
+
overflow-x: clip;
|
|
230
|
+
overflow-y: visible; /* a label's descenders and diacritics paint past its cap-to-baseline box */
|
|
230
231
|
/* a leading-src chip's 1px outline is drawn outside its box at the container edge */
|
|
231
232
|
overflow-clip-margin: 1px;
|
|
232
233
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readout-list-item.css.js","names":[],"sources":["../../../src/navigation-instruments/readout-list-item/readout-list-item.css?inline"],"sourcesContent":["* {\n box-sizing: border-box;\n}\n\n:host {\n display: block;\n width: 100%;\n}\n\nobc-readout-block {\n @mixin readout-block-color-bridge --obc-readout-list-item;\n}\n\n@mixin readout-block-slot-icons;\n\n/* ---------- Root / surface ----------\n * `.root` is the touch target (a <button> when clickable, otherwise a <div>).\n * `.surface` is the visible box that carries padding, corner radius, the\n * data-quality background/border, and — when clickable — the flat interaction\n * states. */\n.root {\n display: block;\n inline-size: 100%;\n margin: 0;\n /* Neutralise the native <button> chrome (default padding + appearance) when\n `.root` is the clickable touch target, so clickable rows don't inset their\n `.surface` and misalign with non-clickable `<div>` rows. */\n padding: 0;\n border: none;\n background: none;\n appearance: none;\n font: inherit;\n color: inherit;\n text-align: inherit;\n}\n\n.root.clickable {\n cursor: pointer;\n /* prettier-ignore */\n @mixin style style=flat visibleWrapperClass=.surface;\n}\n\n.root.clickable:focus {\n outline: none;\n}\n\n/* Flip-flop: animate the value↔setpoint cap-height swap by forwarding obc-textbox's\n opt-in size-transition var. 300ms matches the instrument setpoint marker\n (svghelpers/setpoint.ts). Override via `--obc-readout-list-item-flip-flop-duration`. */\n.root.flip-flop {\n --obc-textbox-size-transition: var(\n --obc-readout-list-item-flip-flop-duration,\n 300ms\n );\n}\n\n.surface {\n display: block;\n inline-size: 100%;\n border-radius: var(--global-border-radius-border-radius-base);\n}\n\n/* Clickable corner variants. The `.clickable` qualifier is redundant for\n matching (a `border-*` class is only ever set alongside `.clickable`) but\n raises specificity to (0,4,0) so the interactive corner shape wins over the\n data-quality rules below — which also target `.surface` at (0,3,0) — when a\n row is both clickable and low-integrity/invalid. Standalone data-quality rows\n keep their own radius. */\n.root.clickable.border-squared .surface {\n border-radius: 0;\n}\n.root.clickable.border-round-corners .surface {\n border-radius: var(--global-border-radius-border-radius-floating);\n}\n.root.clickable.border-round .surface {\n border-radius: var(--global-border-radius-border-radius-round);\n}\n\n/* ---------- Content row ----------\n * Label on the left, value/unit cluster on the right, optional source after a\n * trailing divider. All segments bottom-align so cap heights sit on a shared\n * baseline. */\n.content {\n display: flex;\n align-items: flex-end;\n justify-content: space-between;\n inline-size: 100%;\n min-inline-size: 0;\n}\n\n/* Reserve the value cap-height per tier so the row height and the bottom\n baseline stay constant regardless of which parts (label / value / unit / src /\n setpoint / advice / icons) are present. */\n.size-small .content {\n min-block-size: var(\n --global-typography-instrument-value-regular-container-height\n );\n}\n.size-medium .content {\n min-block-size: var(\n --global-typography-instrument-value-medium-container-height\n );\n}\n.size-large .content {\n min-block-size: var(\n --global-typography-instrument-value-large-container-height\n );\n}\n\n/* The value is the primary data, so under width pressure the label side yields\n first: the label-container shrinks (and clips a too-long label) while\n `.value-area` keeps its intrinsic width. */\n.label-container {\n display: inline-flex;\n align-items: flex-end;\n gap: var(--global-size-spacing-target-padding);\n flex: 1 1 auto;\n min-inline-size: 0;\n overflow: clip;\n /* a leading-src chip's 1px outline is drawn outside its box at the container edge */\n overflow-clip-margin: 1px;\n}\n\n.label-stack {\n display: inline-flex;\n flex-direction: column;\n align-items: flex-start;\n justify-content: flex-end;\n min-inline-size: 0;\n}\n\n.value-area {\n margin-inline-start: auto; /* right-aligns a label-less row's value, which has no label container to push it */\n display: inline-flex;\n align-items: flex-end;\n justify-content: flex-end;\n flex: 0 0 auto;\n min-inline-size: 0;\n}\n\n.value-cluster {\n display: inline-flex;\n align-items: flex-end;\n justify-content: flex-end;\n}\n\n.unit-area {\n display: inline-flex;\n align-items: flex-end;\n}\n\n/* ---------- Value reading (value + degree + unit) ----------\n * Groups the value block, its degree column and the trailing unit so the value\n * alert frame can wrap all three. Layout-neutral: it adds no gap, so the content\n * sits exactly where it did when these were siblings of `.value-area`. */\n.value-reading {\n position: relative;\n display: inline-flex;\n align-items: flex-end;\n}\n\n/* ---------- Value data quality (low-integrity / invalid) ----------\n * The value's per-block data-quality chip, applied to the whole reading (value +\n * degree + unit) rather than hugging the value alone — the same logic as the\n * value alert frame, minus its custom padding. Same look as the block/source\n * chip (1px outline, check radius, alert-quality colours). Uses `outline` (not\n * `border`) so it never shifts the value's width / cross-row column alignment.\n * Setpoint/advice keep their own in-block chip; the row-level data quality on\n * `.surface` is unchanged. */\n.value-reading.data-low-integrity,\n.value-reading.data-invalid {\n outline: 1px solid;\n border-radius: var(--global-border-radius-border-radius-check);\n}\n.value-reading.data-low-integrity {\n background: var(--alert-low-integrity-background-color);\n outline-color: var(--alert-low-integrity-border-color);\n}\n.value-reading.data-invalid {\n background: var(--alert-invalid-background-color);\n outline-color: var(--alert-invalid-border-color);\n}\n\n/* ---------- Value alert overlay ----------\n * Reserves no space, so the frame never changes the row height or the column\n * alignment. The box sits on the 4px/2px padding line, where obc-alert-frame\n * centres its stroke (Figma 58:10120). */\n.value-alert-overlay {\n --_obc-readout-value-frame-padding-horizontal: 4px;\n --_obc-readout-value-frame-padding-vertical: 2px;\n position: absolute;\n inset-inline: calc(-1 * var(--_obc-readout-value-frame-padding-horizontal));\n inset-block: calc(-1 * var(--_obc-readout-value-frame-padding-vertical));\n /* Display-only: never intercept clicks on a clickable row. */\n pointer-events: none;\n}\n\n/* The readout building blocks (advice / setpoint / value) now render inside\n `obc-readout-block`; their layout / colour / hinted-zero / data-quality CSS\n lives there. The list-item only bridges the public colour vars (see top) and\n keeps the surrounding row layout below. */\n\n.label {\n color: var(\n --obc-readout-list-item-label-color,\n var(--element-inactive-color)\n );\n}\n.unit {\n color: var(--obc-readout-list-item-unit-color, var(--element-inactive-color));\n}\n.source {\n color: var(\n --obc-readout-list-item-source-color,\n var(--element-neutral-color)\n );\n}\n\n/* ---------- Source data quality ----------\n * Independent of (and nests inside) the row-level data-quality frame. Uses\n * `outline` (not `border`) so the chip never shifts the source's width. (The\n * per-block value/setpoint/advice chips live in `obc-readout-block`.) */\n.source.data-low-integrity,\n.source.data-invalid {\n outline: 1px solid;\n border-radius: var(--global-border-radius-border-radius-check);\n}\n.source.data-low-integrity {\n background: var(--alert-low-integrity-background-color);\n outline-color: var(--alert-low-integrity-border-color);\n}\n.source.data-invalid {\n background: var(--alert-invalid-background-color);\n outline-color: var(--alert-invalid-border-color);\n}\n\n/* ---------- Source state chip & deviation (Figma 6.1 Readout-block-source)\n * `enhanced` renders the amplified chip, `caution`/`warning` the alert chip.\n * Like the data-quality chip these use `outline`, so toggling a state never\n * shifts the row. TODO(designer): Figma pads the chip 4px; a padding here\n * would shift the row on live state changes, so the chip hugs the text like\n * the data-quality chip does. */\n.source-block {\n display: inline-flex;\n flex-direction: column;\n align-items: flex-start;\n}\n.source-block.source-state-enhanced,\n.source-block.source-state-caution,\n.source-block.source-state-warning {\n outline: 1px solid;\n border-radius: var(--global-border-radius-border-radius-check);\n}\n.source-block.source-state-enhanced {\n background: var(--amplified-enabled-background-color);\n outline-color: var(--amplified-enabled-border-color);\n}\n.source-block.source-state-enhanced .source,\n.source-block.source-state-enhanced .source-deviation {\n color: var(--on-amplified-active-color);\n}\n.source-block.source-state-caution {\n background: var(--alert-caution-color);\n outline-color: var(--alert-caution-outline-color);\n}\n.source-block.source-state-caution .source,\n.source-block.source-state-caution .source-deviation {\n color: var(--on-caution-active-color);\n}\n.source-block.source-state-warning {\n background: var(--alert-warning-color);\n outline-color: var(--alert-warning-outline-color);\n}\n.source-block.source-state-warning .source,\n.source-block.source-state-warning .source-deviation {\n color: var(--on-warning-active-color);\n}\n\n.source-deviation {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n color: var(--element-inactive-color);\n}\n.source-deviation obi-delta {\n display: block;\n inline-size: 12px;\n block-size: 12px;\n}\n\n.leading-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: none;\n color: var(--element-neutral-color);\n}\n.leading-icon ::slotted(*) {\n display: block;\n inline-size: 100%;\n block-size: 100%;\n}\n\n.divider {\n flex: none;\n inline-size: 1px;\n background-color: var(--border-outline-color);\n align-self: stretch;\n}\n\n/* ---------- Value↔unit gap & degree column ----------\n * Default 2px between the value digits and the unit. A degree (or a\n * hasDegreeSpacer reserve) replaces the 2px with a cap-height degree column\n * whose width scales with the value size, so value digits + units align across\n * degree / no-degree rows of the same value size. */\n.value-unit-gap {\n flex: none;\n inline-size: var(\n --instrument-components-readout-general-horizontal-trim-padding\n );\n}\n\n.degree-column {\n flex: none;\n display: inline-flex;\n align-items: flex-end;\n justify-content: center;\n inline-size: var(--_obc-readout-list-item-degree-width, 0);\n overflow: clip;\n color: var(--obc-readout-list-item-value-color, var(--element-neutral-color));\n}\n.degree-column.tone-enhanced {\n color: var(\n --obc-readout-list-item-value-enhanced-color,\n var(--element-neutral-enhanced-color)\n );\n}\n/* Setpoint/advice degree glyphs inherit their block's colour. */\n.degree-column.degree-inherit {\n color: inherit;\n}\n.degree-column.degree-xs {\n --_obc-readout-list-item-degree-width: var(\n --global-typography-instrument-value-small-degree-unit-width\n );\n}\n.degree-column.degree-s {\n --_obc-readout-list-item-degree-width: var(\n --global-typography-instrument-value-regular-degree-unit-width\n );\n}\n.degree-column.degree-m {\n --_obc-readout-list-item-degree-width: var(\n --global-typography-instrument-value-medium-degree-unit-width\n );\n}\n.degree-column.degree-l,\n.degree-column.degree-xl {\n --_obc-readout-list-item-degree-width: var(\n --global-typography-instrument-value-large-degree-unit-width\n );\n}\n\n/* Degree spacer: rendered AFTER the unit on a non-degree row that sets\n hasDegreeSpacer. Its width (degree-compensation-padding = degree-column width\n minus the 2px value↔unit gap) shifts the unit left so the row's value digits\n stay aligned with degree rows in the same column. */\n.degree-spacer {\n flex: none;\n align-self: stretch;\n inline-size: var(--_obc-readout-list-item-degree-spacer-width, 0);\n}\n.size-small .degree-spacer {\n --_obc-readout-list-item-degree-spacer-width: var(\n --instrument-components-readout-list-item-regular-degree-compensation-padding\n );\n}\n.size-medium .degree-spacer {\n --_obc-readout-list-item-degree-spacer-width: var(\n --instrument-components-readout-list-item-medium-degree-compensation-padding\n );\n}\n.size-large .degree-spacer {\n --_obc-readout-list-item-degree-spacer-width: var(\n --instrument-components-readout-list-item-large-degree-compensation-padding\n );\n}\n\n/* ---------- Size tiers ----------\n * Public small/medium/large map to the design token regular/medium/large\n * tiers. */\n.size-small .surface {\n padding-inline: var(\n --instrument-components-readout-list-item-regular-container-padding-horizontal\n );\n padding-block: var(\n --instrument-components-readout-list-item-regular-container-padding-vertical\n );\n}\n.size-small .content {\n gap: var(\n --instrument-components-readout-list-item-regular-content-container-gap\n );\n}\n.size-small .value-cluster {\n gap: var(\n --instrument-components-readout-list-item-regular-value-container-gap\n );\n}\n.size-small .leading-icon {\n inline-size: var(--instrument-components-readout-general-regular-icon-size);\n block-size: var(--instrument-components-readout-general-regular-icon-size);\n}\n.size-small .divider {\n block-size: var(\n --global-typography-instrument-value-regular-container-height\n );\n}\n\n.size-medium .surface {\n padding-inline: var(\n --instrument-components-readout-list-item-medium-container-padding-horizontal\n );\n padding-block: var(\n --instrument-components-readout-list-item-medium-container-padding-vertical\n );\n}\n.size-medium .content {\n gap: var(\n --instrument-components-readout-list-item-medium-content-container-gap\n );\n}\n.size-medium .value-cluster {\n gap: var(\n --instrument-components-readout-list-item-medium-value-container-gap\n );\n}\n.size-medium .leading-icon {\n inline-size: var(--instrument-components-readout-general-medium-icon-size);\n block-size: var(--instrument-components-readout-general-medium-icon-size);\n}\n.size-medium .divider {\n block-size: var(--global-typography-instrument-value-medium-container-height);\n}\n\n.size-large .surface {\n padding-inline: var(\n --instrument-components-readout-list-item-large-container-padding-horizontal\n );\n padding-block: var(\n --instrument-components-readout-list-item-large-container-padding-vertical\n );\n min-block-size: var(\n --instrument-components-readout-list-item-large-min-height\n );\n}\n.size-large .content {\n gap: var(--instrument-components-readout-list-item-large-content-gap);\n}\n.size-large .value-cluster {\n gap: var(--instrument-components-readout-list-item-large-value-gap);\n}\n.size-large .leading-icon {\n inline-size: var(--instrument-components-readout-general-large-icon-size);\n block-size: var(--instrument-components-readout-general-large-icon-size);\n}\n.size-large .divider {\n block-size: var(--global-typography-instrument-value-large-container-height);\n}\n\n/* ---------- Stacking ----------\n * leading-unit / leading-src move the unit / source up beside the label and\n * suppress the trailing variant. (Handled in markup; these rules tighten the\n * label-stack gap.) */\n.stacking-leading-src .content {\n gap: var(--global-size-spacing-target-padding);\n}\n\n/* leading-src-inline: the source follows the label on one line, bottom-aligned\n so the `xs` source and the label share a cap baseline. The label↔source gap\n reuses the tier's content gap (8px, matching Figma 46596:102880). */\n.stacking-leading-src-inline .label-stack {\n flex-direction: row;\n align-items: flex-end;\n}\n.size-small.stacking-leading-src-inline .label-stack {\n gap: var(\n --instrument-components-readout-list-item-regular-content-container-gap\n );\n}\n.size-medium.stacking-leading-src-inline .label-stack {\n gap: var(\n --instrument-components-readout-list-item-medium-content-container-gap\n );\n}\n.size-large.stacking-leading-src-inline .label-stack {\n gap: var(--instrument-components-readout-list-item-large-content-gap);\n}\n\n/* ---------- Data quality ----------\n * Orthogonal to the alert frame — both can apply at once. */\n.root.data-low-integrity .surface,\n.root.data-invalid .surface {\n /* `outline` (not `border`) so the data-quality frame does not inset the\n content by 1px — keeps the row's value column-aligned with unframed rows.\n Matches the per-block data-quality rules. */\n outline: 1px solid var(--_obc-readout-list-item-data-border);\n background: var(--_obc-readout-list-item-data-background);\n border-radius: var(--global-border-radius-border-radius-check);\n}\n.root.data-low-integrity {\n --_obc-readout-list-item-data-background: var(\n --alert-low-integrity-background-color\n );\n --_obc-readout-list-item-data-border: var(--alert-low-integrity-border-color);\n}\n.root.data-invalid {\n --_obc-readout-list-item-data-background: var(\n --alert-invalid-background-color\n );\n --_obc-readout-list-item-data-border: var(--alert-invalid-border-color);\n}\n\n/* ---------- Debug overlay ----------\n * `showDebugOverlay` outlines each readout building block (red), the degree\n * columns (blue) and the degree spacer (green) so reserver widths / alignment\n * are visible. A development aid (mirrors the donut chart's `showDebugOverlay`);\n * off by default. */\n:host([showDebugOverlay]) obc-readout-block::part(block) {\n outline: 1px solid rgba(220, 0, 0, 0.7);\n outline-offset: -1px;\n}\n:host([showDebugOverlay]) obc-readout-block::part(degree),\n:host([showDebugOverlay]) .degree-column {\n outline: 1px solid rgba(0, 0, 220, 0.7);\n outline-offset: -1px;\n}\n:host([showDebugOverlay]) .degree-spacer {\n outline: 1px solid rgba(0, 160, 0, 0.8);\n outline-offset: -1px;\n}\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"readout-list-item.css.js","names":[],"sources":["../../../src/navigation-instruments/readout-list-item/readout-list-item.css?inline"],"sourcesContent":["* {\n box-sizing: border-box;\n}\n\n:host {\n display: block;\n width: 100%;\n}\n\nobc-readout-block {\n @mixin readout-block-color-bridge --obc-readout-list-item;\n}\n\n@mixin readout-block-slot-icons;\n\n/* ---------- Root / surface ----------\n * `.root` is the touch target (a <button> when clickable, otherwise a <div>).\n * `.surface` is the visible box that carries padding, corner radius, the\n * data-quality background/border, and — when clickable — the flat interaction\n * states. */\n.root {\n display: block;\n inline-size: 100%;\n margin: 0;\n /* Neutralise the native <button> chrome (default padding + appearance) when\n `.root` is the clickable touch target, so clickable rows don't inset their\n `.surface` and misalign with non-clickable `<div>` rows. */\n padding: 0;\n border: none;\n background: none;\n appearance: none;\n font: inherit;\n color: inherit;\n text-align: inherit;\n}\n\n.root.clickable {\n cursor: pointer;\n /* prettier-ignore */\n @mixin style style=flat visibleWrapperClass=.surface;\n}\n\n.root.clickable:focus {\n outline: none;\n}\n\n/* Flip-flop: animate the value↔setpoint cap-height swap by forwarding obc-textbox's\n opt-in size-transition var. 300ms matches the instrument setpoint marker\n (svghelpers/setpoint.ts). Override via `--obc-readout-list-item-flip-flop-duration`. */\n.root.flip-flop {\n --obc-textbox-size-transition: var(\n --obc-readout-list-item-flip-flop-duration,\n 300ms\n );\n}\n\n.surface {\n display: block;\n inline-size: 100%;\n border-radius: var(--global-border-radius-border-radius-base);\n}\n\n/* Clickable corner variants. The `.clickable` qualifier is redundant for\n matching (a `border-*` class is only ever set alongside `.clickable`) but\n raises specificity to (0,4,0) so the interactive corner shape wins over the\n data-quality rules below — which also target `.surface` at (0,3,0) — when a\n row is both clickable and low-integrity/invalid. Standalone data-quality rows\n keep their own radius. */\n.root.clickable.border-squared .surface {\n border-radius: 0;\n}\n.root.clickable.border-round-corners .surface {\n border-radius: var(--global-border-radius-border-radius-floating);\n}\n.root.clickable.border-round .surface {\n border-radius: var(--global-border-radius-border-radius-round);\n}\n\n/* ---------- Content row ----------\n * Label on the left, value/unit cluster on the right, optional source after a\n * trailing divider. All segments bottom-align so cap heights sit on a shared\n * baseline. */\n.content {\n display: flex;\n align-items: flex-end;\n justify-content: space-between;\n inline-size: 100%;\n min-inline-size: 0;\n}\n\n/* Reserve the value cap-height per tier so the row height and the bottom\n baseline stay constant regardless of which parts (label / value / unit / src /\n setpoint / advice / icons) are present. */\n.size-small .content {\n min-block-size: var(\n --global-typography-instrument-value-regular-container-height\n );\n}\n.size-medium .content {\n min-block-size: var(\n --global-typography-instrument-value-medium-container-height\n );\n}\n.size-large .content {\n min-block-size: var(\n --global-typography-instrument-value-large-container-height\n );\n}\n\n/* The value is the primary data, so under width pressure the label side yields\n first: the label-container shrinks (and clips a too-long label) while\n `.value-area` keeps its intrinsic width. */\n.label-container {\n display: inline-flex;\n align-items: flex-end;\n gap: var(--global-size-spacing-target-padding);\n flex: 1 1 auto;\n min-inline-size: 0;\n overflow-x: clip;\n overflow-y: visible; /* a label's descenders and diacritics paint past its cap-to-baseline box */\n /* a leading-src chip's 1px outline is drawn outside its box at the container edge */\n overflow-clip-margin: 1px;\n}\n\n.label-stack {\n display: inline-flex;\n flex-direction: column;\n align-items: flex-start;\n justify-content: flex-end;\n min-inline-size: 0;\n}\n\n.value-area {\n margin-inline-start: auto; /* right-aligns a label-less row's value, which has no label container to push it */\n display: inline-flex;\n align-items: flex-end;\n justify-content: flex-end;\n flex: 0 0 auto;\n min-inline-size: 0;\n}\n\n.value-cluster {\n display: inline-flex;\n align-items: flex-end;\n justify-content: flex-end;\n}\n\n.unit-area {\n display: inline-flex;\n align-items: flex-end;\n}\n\n/* ---------- Value reading (value + degree + unit) ----------\n * Groups the value block, its degree column and the trailing unit so the value\n * alert frame can wrap all three. Layout-neutral: it adds no gap, so the content\n * sits exactly where it did when these were siblings of `.value-area`. */\n.value-reading {\n position: relative;\n display: inline-flex;\n align-items: flex-end;\n}\n\n/* ---------- Value data quality (low-integrity / invalid) ----------\n * The value's per-block data-quality chip, applied to the whole reading (value +\n * degree + unit) rather than hugging the value alone — the same logic as the\n * value alert frame, minus its custom padding. Same look as the block/source\n * chip (1px outline, check radius, alert-quality colours). Uses `outline` (not\n * `border`) so it never shifts the value's width / cross-row column alignment.\n * Setpoint/advice keep their own in-block chip; the row-level data quality on\n * `.surface` is unchanged. */\n.value-reading.data-low-integrity,\n.value-reading.data-invalid {\n outline: 1px solid;\n border-radius: var(--global-border-radius-border-radius-check);\n}\n.value-reading.data-low-integrity {\n background: var(--alert-low-integrity-background-color);\n outline-color: var(--alert-low-integrity-border-color);\n}\n.value-reading.data-invalid {\n background: var(--alert-invalid-background-color);\n outline-color: var(--alert-invalid-border-color);\n}\n\n/* ---------- Value alert overlay ----------\n * Reserves no space, so the frame never changes the row height or the column\n * alignment. The box sits on the 4px/2px padding line, where obc-alert-frame\n * centres its stroke (Figma 58:10120). */\n.value-alert-overlay {\n --_obc-readout-value-frame-padding-horizontal: 4px;\n --_obc-readout-value-frame-padding-vertical: 2px;\n position: absolute;\n inset-inline: calc(-1 * var(--_obc-readout-value-frame-padding-horizontal));\n inset-block: calc(-1 * var(--_obc-readout-value-frame-padding-vertical));\n /* Display-only: never intercept clicks on a clickable row. */\n pointer-events: none;\n}\n\n/* The readout building blocks (advice / setpoint / value) now render inside\n `obc-readout-block`; their layout / colour / hinted-zero / data-quality CSS\n lives there. The list-item only bridges the public colour vars (see top) and\n keeps the surrounding row layout below. */\n\n.label {\n color: var(\n --obc-readout-list-item-label-color,\n var(--element-inactive-color)\n );\n}\n.unit {\n color: var(--obc-readout-list-item-unit-color, var(--element-inactive-color));\n}\n.source {\n color: var(\n --obc-readout-list-item-source-color,\n var(--element-neutral-color)\n );\n}\n\n/* ---------- Source data quality ----------\n * Independent of (and nests inside) the row-level data-quality frame. Uses\n * `outline` (not `border`) so the chip never shifts the source's width. (The\n * per-block value/setpoint/advice chips live in `obc-readout-block`.) */\n.source.data-low-integrity,\n.source.data-invalid {\n outline: 1px solid;\n border-radius: var(--global-border-radius-border-radius-check);\n}\n.source.data-low-integrity {\n background: var(--alert-low-integrity-background-color);\n outline-color: var(--alert-low-integrity-border-color);\n}\n.source.data-invalid {\n background: var(--alert-invalid-background-color);\n outline-color: var(--alert-invalid-border-color);\n}\n\n/* ---------- Source state chip & deviation (Figma 6.1 Readout-block-source)\n * `enhanced` renders the amplified chip, `caution`/`warning` the alert chip.\n * Like the data-quality chip these use `outline`, so toggling a state never\n * shifts the row. TODO(designer): Figma pads the chip 4px; a padding here\n * would shift the row on live state changes, so the chip hugs the text like\n * the data-quality chip does. */\n.source-block {\n display: inline-flex;\n flex-direction: column;\n align-items: flex-start;\n}\n.source-block.source-state-enhanced,\n.source-block.source-state-caution,\n.source-block.source-state-warning {\n outline: 1px solid;\n border-radius: var(--global-border-radius-border-radius-check);\n}\n.source-block.source-state-enhanced {\n background: var(--amplified-enabled-background-color);\n outline-color: var(--amplified-enabled-border-color);\n}\n.source-block.source-state-enhanced .source,\n.source-block.source-state-enhanced .source-deviation {\n color: var(--on-amplified-active-color);\n}\n.source-block.source-state-caution {\n background: var(--alert-caution-color);\n outline-color: var(--alert-caution-outline-color);\n}\n.source-block.source-state-caution .source,\n.source-block.source-state-caution .source-deviation {\n color: var(--on-caution-active-color);\n}\n.source-block.source-state-warning {\n background: var(--alert-warning-color);\n outline-color: var(--alert-warning-outline-color);\n}\n.source-block.source-state-warning .source,\n.source-block.source-state-warning .source-deviation {\n color: var(--on-warning-active-color);\n}\n\n.source-deviation {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n color: var(--element-inactive-color);\n}\n.source-deviation obi-delta {\n display: block;\n inline-size: 12px;\n block-size: 12px;\n}\n\n.leading-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: none;\n color: var(--element-neutral-color);\n}\n.leading-icon ::slotted(*) {\n display: block;\n inline-size: 100%;\n block-size: 100%;\n}\n\n.divider {\n flex: none;\n inline-size: 1px;\n background-color: var(--border-outline-color);\n align-self: stretch;\n}\n\n/* ---------- Value↔unit gap & degree column ----------\n * Default 2px between the value digits and the unit. A degree (or a\n * hasDegreeSpacer reserve) replaces the 2px with a cap-height degree column\n * whose width scales with the value size, so value digits + units align across\n * degree / no-degree rows of the same value size. */\n.value-unit-gap {\n flex: none;\n inline-size: var(\n --instrument-components-readout-general-horizontal-trim-padding\n );\n}\n\n.degree-column {\n flex: none;\n display: inline-flex;\n align-items: flex-end;\n justify-content: center;\n inline-size: var(--_obc-readout-list-item-degree-width, 0);\n overflow: clip;\n color: var(--obc-readout-list-item-value-color, var(--element-neutral-color));\n}\n.degree-column.tone-enhanced {\n color: var(\n --obc-readout-list-item-value-enhanced-color,\n var(--element-neutral-enhanced-color)\n );\n}\n/* Setpoint/advice degree glyphs inherit their block's colour. */\n.degree-column.degree-inherit {\n color: inherit;\n}\n.degree-column.degree-xs {\n --_obc-readout-list-item-degree-width: var(\n --global-typography-instrument-value-small-degree-unit-width\n );\n}\n.degree-column.degree-s {\n --_obc-readout-list-item-degree-width: var(\n --global-typography-instrument-value-regular-degree-unit-width\n );\n}\n.degree-column.degree-m {\n --_obc-readout-list-item-degree-width: var(\n --global-typography-instrument-value-medium-degree-unit-width\n );\n}\n.degree-column.degree-l,\n.degree-column.degree-xl {\n --_obc-readout-list-item-degree-width: var(\n --global-typography-instrument-value-large-degree-unit-width\n );\n}\n\n/* Degree spacer: rendered AFTER the unit on a non-degree row that sets\n hasDegreeSpacer. Its width (degree-compensation-padding = degree-column width\n minus the 2px value↔unit gap) shifts the unit left so the row's value digits\n stay aligned with degree rows in the same column. */\n.degree-spacer {\n flex: none;\n align-self: stretch;\n inline-size: var(--_obc-readout-list-item-degree-spacer-width, 0);\n}\n.size-small .degree-spacer {\n --_obc-readout-list-item-degree-spacer-width: var(\n --instrument-components-readout-list-item-regular-degree-compensation-padding\n );\n}\n.size-medium .degree-spacer {\n --_obc-readout-list-item-degree-spacer-width: var(\n --instrument-components-readout-list-item-medium-degree-compensation-padding\n );\n}\n.size-large .degree-spacer {\n --_obc-readout-list-item-degree-spacer-width: var(\n --instrument-components-readout-list-item-large-degree-compensation-padding\n );\n}\n\n/* ---------- Size tiers ----------\n * Public small/medium/large map to the design token regular/medium/large\n * tiers. */\n.size-small .surface {\n padding-inline: var(\n --instrument-components-readout-list-item-regular-container-padding-horizontal\n );\n padding-block: var(\n --instrument-components-readout-list-item-regular-container-padding-vertical\n );\n}\n.size-small .content {\n gap: var(\n --instrument-components-readout-list-item-regular-content-container-gap\n );\n}\n.size-small .value-cluster {\n gap: var(\n --instrument-components-readout-list-item-regular-value-container-gap\n );\n}\n.size-small .leading-icon {\n inline-size: var(--instrument-components-readout-general-regular-icon-size);\n block-size: var(--instrument-components-readout-general-regular-icon-size);\n}\n.size-small .divider {\n block-size: var(\n --global-typography-instrument-value-regular-container-height\n );\n}\n\n.size-medium .surface {\n padding-inline: var(\n --instrument-components-readout-list-item-medium-container-padding-horizontal\n );\n padding-block: var(\n --instrument-components-readout-list-item-medium-container-padding-vertical\n );\n}\n.size-medium .content {\n gap: var(\n --instrument-components-readout-list-item-medium-content-container-gap\n );\n}\n.size-medium .value-cluster {\n gap: var(\n --instrument-components-readout-list-item-medium-value-container-gap\n );\n}\n.size-medium .leading-icon {\n inline-size: var(--instrument-components-readout-general-medium-icon-size);\n block-size: var(--instrument-components-readout-general-medium-icon-size);\n}\n.size-medium .divider {\n block-size: var(--global-typography-instrument-value-medium-container-height);\n}\n\n.size-large .surface {\n padding-inline: var(\n --instrument-components-readout-list-item-large-container-padding-horizontal\n );\n padding-block: var(\n --instrument-components-readout-list-item-large-container-padding-vertical\n );\n min-block-size: var(\n --instrument-components-readout-list-item-large-min-height\n );\n}\n.size-large .content {\n gap: var(--instrument-components-readout-list-item-large-content-gap);\n}\n.size-large .value-cluster {\n gap: var(--instrument-components-readout-list-item-large-value-gap);\n}\n.size-large .leading-icon {\n inline-size: var(--instrument-components-readout-general-large-icon-size);\n block-size: var(--instrument-components-readout-general-large-icon-size);\n}\n.size-large .divider {\n block-size: var(--global-typography-instrument-value-large-container-height);\n}\n\n/* ---------- Stacking ----------\n * leading-unit / leading-src move the unit / source up beside the label and\n * suppress the trailing variant. (Handled in markup; these rules tighten the\n * label-stack gap.) */\n.stacking-leading-src .content {\n gap: var(--global-size-spacing-target-padding);\n}\n\n/* leading-src-inline: the source follows the label on one line, bottom-aligned\n so the `xs` source and the label share a cap baseline. The label↔source gap\n reuses the tier's content gap (8px, matching Figma 46596:102880). */\n.stacking-leading-src-inline .label-stack {\n flex-direction: row;\n align-items: flex-end;\n}\n.size-small.stacking-leading-src-inline .label-stack {\n gap: var(\n --instrument-components-readout-list-item-regular-content-container-gap\n );\n}\n.size-medium.stacking-leading-src-inline .label-stack {\n gap: var(\n --instrument-components-readout-list-item-medium-content-container-gap\n );\n}\n.size-large.stacking-leading-src-inline .label-stack {\n gap: var(--instrument-components-readout-list-item-large-content-gap);\n}\n\n/* ---------- Data quality ----------\n * Orthogonal to the alert frame — both can apply at once. */\n.root.data-low-integrity .surface,\n.root.data-invalid .surface {\n /* `outline` (not `border`) so the data-quality frame does not inset the\n content by 1px — keeps the row's value column-aligned with unframed rows.\n Matches the per-block data-quality rules. */\n outline: 1px solid var(--_obc-readout-list-item-data-border);\n background: var(--_obc-readout-list-item-data-background);\n border-radius: var(--global-border-radius-border-radius-check);\n}\n.root.data-low-integrity {\n --_obc-readout-list-item-data-background: var(\n --alert-low-integrity-background-color\n );\n --_obc-readout-list-item-data-border: var(--alert-low-integrity-border-color);\n}\n.root.data-invalid {\n --_obc-readout-list-item-data-background: var(\n --alert-invalid-background-color\n );\n --_obc-readout-list-item-data-border: var(--alert-invalid-border-color);\n}\n\n/* ---------- Debug overlay ----------\n * `showDebugOverlay` outlines each readout building block (red), the degree\n * columns (blue) and the degree spacer (green) so reserver widths / alignment\n * are visible. A development aid (mirrors the donut chart's `showDebugOverlay`);\n * off by default. */\n:host([showDebugOverlay]) obc-readout-block::part(block) {\n outline: 1px solid rgba(220, 0, 0, 0.7);\n outline-offset: -1px;\n}\n:host([showDebugOverlay]) obc-readout-block::part(degree),\n:host([showDebugOverlay]) .degree-column {\n outline: 1px solid rgba(0, 0, 220, 0.7);\n outline-offset: -1px;\n}\n:host([showDebugOverlay]) .degree-spacer {\n outline: 1px solid rgba(0, 160, 0, 0.8);\n outline-offset: -1px;\n}\n"],"mappings":""}
|
|
@@ -99,7 +99,7 @@ var ObcAlertDetailPage = class ObcAlertDetailPage extends LitElement {
|
|
|
99
99
|
[`type-${this.type}`]: true,
|
|
100
100
|
"status-acknowledged": isAcknowledged(this.alert) && isActive(this.alert),
|
|
101
101
|
"status-unacknowledged": !isAcknowledged(this.alert) && isActive(this.alert),
|
|
102
|
-
"status-resolved": isActive(this.alert)
|
|
102
|
+
"status-resolved": !isActive(this.alert)
|
|
103
103
|
})}
|
|
104
104
|
>
|
|
105
105
|
<div class="header">
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alert-detail-page.js","names":[],"sources":["../../../src/pages/alert-detail-page/alert-detail-page.ts"],"sourcesContent":["import {LitElement, TemplateResult, html, nothing, unsafeCSS} from 'lit';\nimport {customElement} from '../../decorator.js';\nimport compentStyle from './alert-detail-page.css?inline';\nimport {property} from 'lit/decorators.js';\nimport '../../components/button/button.js';\nimport '../../components/icon-button/icon-button.js';\nimport '../../components/alert-icon/alert-icon.js';\nimport '../../icons/icon-close-google.js';\nimport '../../icons/icon-alerts-shelf.js';\nimport '../../icons/icon-command-locked-f.js';\nimport '../../icons/icon-alert-category-a.js';\nimport '../../icons/icon-alert-category-b.js';\nimport '../../icons/icon-alert-category-c.js';\nimport {\n Alert,\n AlertCategory,\n formatTimeSince,\n isAcknowledged,\n isActive,\n TimeSinceFn,\n} from '../../types.js';\nimport {classMap} from 'lit/directives/class-map.js';\nimport {localized, msg} from '@lit/localize';\n\nexport enum AlertDetailPageType {\n page = 'page',\n modal = 'modal',\n card = 'card',\n}\n\n@localized()\n/**\n * @slot note-label - Label for the note section, rendered when `hasNote` is true\n * @slot note - Note content, rendered when `hasNote` is true\n * @slot readout-graph-title - Title for the readout graph, rendered when `hasReadoutGraph` is true\n * @slot readout-graph - Readout graph content, rendered when `hasReadoutGraph` is true\n * @slot action - Action controls, rendered when `hasActions` is true\n * @slot <detail>-label - Overrides the label of the `<detail>` field (e.g. `tagId-label`, `category-label`, `time-label`)\n * @slot <detail>-value - Overrides the value of the `<detail>` field (e.g. `tagId-value`, `category-value`, `time-value`)\n * @beta\n */\n@customElement('obc-alert-detail-page')\nexport class ObcAlertDetailPage extends LitElement {\n @property({type: String}) type: AlertDetailPageType =\n AlertDetailPageType.page;\n\n @property({attribute: false}) alert!: Alert;\n @property({type: Boolean}) hasNote = false;\n @property({type: Boolean}) hasActions = false;\n @property({type: Boolean}) hasTagId = false;\n @property({type: Boolean}) hasCategory = false;\n @property({type: Boolean}) hasActivated = false;\n @property({type: Boolean}) hasTimer = false;\n @property({type: Boolean}) hasAcknowledged = false;\n @property({type: Boolean}) hasAcknowledgedBy = false;\n @property({type: Boolean}) hasRectified = false;\n @property({type: Boolean}) hasShelvingTimer = false;\n @property({type: Boolean}) hasShelvedBy = false;\n @property({type: Boolean}) hasReadoutGraph = false;\n @property({attribute: false}) timeFormatter: (time: Date) => string = (\n time: Date\n ) => time.toLocaleTimeString(undefined, {hour12: false});\n\n @property({attribute: false}) timeSinceFormatter: TimeSinceFn =\n formatTimeSince;\n\n private _interval: number | null = null;\n\n override connectedCallback() {\n super.connectedCallback();\n this._interval = window.setInterval(() => {\n this.requestUpdate();\n }, 1000) as unknown as number;\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n if (this._interval) {\n window.clearInterval(this._interval);\n }\n }\n\n get alertStatusIcon() {\n if (this.alert.shelved) {\n return html`<obi-alerts-shelf class=\"icon status\"></obi-alerts-shelf>`;\n }\n if (this.alert.blocked) {\n return html`<obi-command-locked-f\n class=\"icon status\"\n ></obi-command-locked-f>`;\n }\n return nothing;\n }\n\n private renderDetail(\n has: boolean,\n slotName: string,\n defaultTitle: string,\n getValue: (\n alert: Alert\n ) => string | Date | AlertCategory | undefined | boolean,\n options: {timer?: boolean} = {}\n ) {\n if (has) {\n const rawValue = getValue(this.alert);\n let value: string | TemplateResult | undefined | boolean;\n let isIcon = false;\n\n if (rawValue instanceof Date) {\n if (options.timer) {\n value = this.timeSinceFormatter(rawValue as Date);\n } else {\n value = this.timeFormatter(rawValue as Date);\n }\n } else if (slotName === 'category') {\n isIcon = true;\n if (rawValue === AlertCategory.a) {\n value = html`<obi-alert-category-a></obi-alert-category-a>`;\n } else if (rawValue === AlertCategory.b) {\n value = html`<obi-alert-category-b></obi-alert-category-b>`;\n } else if (rawValue === AlertCategory.c) {\n value = html`<obi-alert-category-c></obi-alert-category-c>`;\n }\n } else {\n value = rawValue as string | boolean | undefined;\n }\n return html`\n <div class=\"detail\">\n <div class=\"detail-title\">\n <slot name=\"${slotName}-label\">${defaultTitle}</slot>\n </div>\n <div class=\"detail-value ${isIcon ? 'icon' : ''}\">\n <slot name=\"${slotName}-value\"> ${value} </slot>\n </div>\n </div>\n `;\n }\n return nothing;\n }\n\n override render() {\n if (!this.alert) {\n console.error('Alert is not set in alert-detail-page');\n return nothing;\n }\n const showCloseButton = [AlertDetailPageType.modal].includes(this.type);\n\n return html`\n <div\n class=${classMap({\n wrapper: true,\n [`type-${this.type}`]: true,\n 'status-acknowledged':\n isAcknowledged(this.alert) && isActive(this.alert),\n 'status-unacknowledged':\n !isAcknowledged(this.alert) && isActive(this.alert),\n 'status-resolved': isActive(this.alert),\n })}\n >\n <div class=\"header\">\n ${this.alertStatusIcon}\n <div class=\"icon alert\">\n <obc-alert-icon\n .type=${this.alert.type}\n .acknowledged=${isAcknowledged(this.alert)}\n .active=${isActive(this.alert)}\n ></obc-alert-icon>\n </div>\n <div class=\"title\">\n <span>${this.alert.source}</span>\n </div>\n ${\n showCloseButton\n ? html`<div class=\"close-button\">\n <obc-icon-button variant=\"flat\" aria-label=${msg('Close')}>\n <obi-close-google></obi-close-google>\n </obc-icon-button>\n </div>`\n : nothing\n }\n </div>\n <div class=\"divider\"></div>\n <div class=\"body\">\n <div class=\"description\">\n <span>${this.alert.text}</span>\n </div>\n ${\n this.hasNote\n ? html`<div class=\"description sub-description\">\n <div class=\"label\">\n <slot name=\"note-label\">${msg('Note')}</slot>\n </div>\n <slot name=\"note\">${this.alert.note}</slot>\n </div>`\n : nothing\n }\n ${this.renderDetail(\n this.hasTagId,\n 'tagId',\n msg('Tag ID'),\n (alert) => alert.tagId\n )}\n ${this.renderDetail(\n this.hasCategory,\n 'category',\n msg('Category'),\n (alert) => alert.category\n )}\n ${this.renderDetail(\n this.hasActivated,\n 'time',\n msg('Activated'),\n (alert) => alert.time\n )}\n ${this.renderDetail(\n this.hasTimer,\n 'activated-timer',\n msg('Alert timer'),\n (alert) => alert.time,\n {timer: true}\n )}\n ${this.renderDetail(\n this.hasAcknowledged,\n 'acknowledgedAt',\n msg('Acknowledged'),\n (alert) => alert.acknowledged && alert.acknowledged.acknowledgedAt\n )}\n ${this.renderDetail(\n this.hasRectified,\n 'rectified',\n msg('Rectified'),\n (alert) => alert.active !== true && alert.active.rectifiedTime\n )}\n ${this.renderDetail(\n this.hasAcknowledgedBy,\n 'acknowledged-by',\n msg('Acknowledged by'),\n (alert) => alert.acknowledged && alert.acknowledged.acknowledgedBy\n )}\n ${this.renderDetail(\n this.hasShelvingTimer,\n 'shelving-timer',\n msg('Shelfing timer'),\n (alert) => alert.shelved && alert.shelved.shelvedStartTime,\n {timer: true}\n )}\n ${this.renderDetail(\n this.hasShelvedBy,\n 'shelved-by',\n msg('Shelved by'),\n (alert) => alert.shelved && alert.shelved.shelvedBy\n )}\n ${\n this.hasReadoutGraph\n ? html`\n <div class=\"readout-graph\">\n <div class=\"readout-graph-title\">\n <slot name=\"readout-graph-title\">${msg('Readout')}</slot>\n </div>\n <div class=\"readout-graph-container\">\n <slot name=\"readout-graph\"></slot>\n </div>\n </div>\n `\n : nothing\n }\n </div>\n ${\n this.hasActions\n ? html`<div class=\"actions\">\n <slot name=\"action\"></slot>\n </div>`\n : nothing\n }\n </div>\n `;\n }\n\n static override styles = unsafeCSS(compentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-alert-detail-page': ObcAlertDetailPage;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"alert-detail-page.js","names":[],"sources":["../../../src/pages/alert-detail-page/alert-detail-page.ts"],"sourcesContent":["import {LitElement, TemplateResult, html, nothing, unsafeCSS} from 'lit';\nimport {customElement} from '../../decorator.js';\nimport compentStyle from './alert-detail-page.css?inline';\nimport {property} from 'lit/decorators.js';\nimport '../../components/button/button.js';\nimport '../../components/icon-button/icon-button.js';\nimport '../../components/alert-icon/alert-icon.js';\nimport '../../icons/icon-close-google.js';\nimport '../../icons/icon-alerts-shelf.js';\nimport '../../icons/icon-command-locked-f.js';\nimport '../../icons/icon-alert-category-a.js';\nimport '../../icons/icon-alert-category-b.js';\nimport '../../icons/icon-alert-category-c.js';\nimport {\n Alert,\n AlertCategory,\n formatTimeSince,\n isAcknowledged,\n isActive,\n TimeSinceFn,\n} from '../../types.js';\nimport {classMap} from 'lit/directives/class-map.js';\nimport {localized, msg} from '@lit/localize';\n\nexport enum AlertDetailPageType {\n page = 'page',\n modal = 'modal',\n card = 'card',\n}\n\n@localized()\n/**\n * @slot note-label - Label for the note section, rendered when `hasNote` is true\n * @slot note - Note content, rendered when `hasNote` is true\n * @slot readout-graph-title - Title for the readout graph, rendered when `hasReadoutGraph` is true\n * @slot readout-graph - Readout graph content, rendered when `hasReadoutGraph` is true\n * @slot action - Action controls, rendered when `hasActions` is true\n * @slot <detail>-label - Overrides the label of the `<detail>` field (e.g. `tagId-label`, `category-label`, `time-label`)\n * @slot <detail>-value - Overrides the value of the `<detail>` field (e.g. `tagId-value`, `category-value`, `time-value`)\n * @beta\n */\n@customElement('obc-alert-detail-page')\nexport class ObcAlertDetailPage extends LitElement {\n @property({type: String}) type: AlertDetailPageType =\n AlertDetailPageType.page;\n\n @property({attribute: false}) alert!: Alert;\n @property({type: Boolean}) hasNote = false;\n @property({type: Boolean}) hasActions = false;\n @property({type: Boolean}) hasTagId = false;\n @property({type: Boolean}) hasCategory = false;\n @property({type: Boolean}) hasActivated = false;\n @property({type: Boolean}) hasTimer = false;\n @property({type: Boolean}) hasAcknowledged = false;\n @property({type: Boolean}) hasAcknowledgedBy = false;\n @property({type: Boolean}) hasRectified = false;\n @property({type: Boolean}) hasShelvingTimer = false;\n @property({type: Boolean}) hasShelvedBy = false;\n @property({type: Boolean}) hasReadoutGraph = false;\n @property({attribute: false}) timeFormatter: (time: Date) => string = (\n time: Date\n ) => time.toLocaleTimeString(undefined, {hour12: false});\n\n @property({attribute: false}) timeSinceFormatter: TimeSinceFn =\n formatTimeSince;\n\n private _interval: number | null = null;\n\n override connectedCallback() {\n super.connectedCallback();\n this._interval = window.setInterval(() => {\n this.requestUpdate();\n }, 1000) as unknown as number;\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n if (this._interval) {\n window.clearInterval(this._interval);\n }\n }\n\n get alertStatusIcon() {\n if (this.alert.shelved) {\n return html`<obi-alerts-shelf class=\"icon status\"></obi-alerts-shelf>`;\n }\n if (this.alert.blocked) {\n return html`<obi-command-locked-f\n class=\"icon status\"\n ></obi-command-locked-f>`;\n }\n return nothing;\n }\n\n private renderDetail(\n has: boolean,\n slotName: string,\n defaultTitle: string,\n getValue: (\n alert: Alert\n ) => string | Date | AlertCategory | undefined | boolean,\n options: {timer?: boolean} = {}\n ) {\n if (has) {\n const rawValue = getValue(this.alert);\n let value: string | TemplateResult | undefined | boolean;\n let isIcon = false;\n\n if (rawValue instanceof Date) {\n if (options.timer) {\n value = this.timeSinceFormatter(rawValue as Date);\n } else {\n value = this.timeFormatter(rawValue as Date);\n }\n } else if (slotName === 'category') {\n isIcon = true;\n if (rawValue === AlertCategory.a) {\n value = html`<obi-alert-category-a></obi-alert-category-a>`;\n } else if (rawValue === AlertCategory.b) {\n value = html`<obi-alert-category-b></obi-alert-category-b>`;\n } else if (rawValue === AlertCategory.c) {\n value = html`<obi-alert-category-c></obi-alert-category-c>`;\n }\n } else {\n value = rawValue as string | boolean | undefined;\n }\n return html`\n <div class=\"detail\">\n <div class=\"detail-title\">\n <slot name=\"${slotName}-label\">${defaultTitle}</slot>\n </div>\n <div class=\"detail-value ${isIcon ? 'icon' : ''}\">\n <slot name=\"${slotName}-value\"> ${value} </slot>\n </div>\n </div>\n `;\n }\n return nothing;\n }\n\n override render() {\n if (!this.alert) {\n console.error('Alert is not set in alert-detail-page');\n return nothing;\n }\n const showCloseButton = [AlertDetailPageType.modal].includes(this.type);\n\n return html`\n <div\n class=${classMap({\n wrapper: true,\n [`type-${this.type}`]: true,\n 'status-acknowledged':\n isAcknowledged(this.alert) && isActive(this.alert),\n 'status-unacknowledged':\n !isAcknowledged(this.alert) && isActive(this.alert),\n 'status-resolved': !isActive(this.alert),\n })}\n >\n <div class=\"header\">\n ${this.alertStatusIcon}\n <div class=\"icon alert\">\n <obc-alert-icon\n .type=${this.alert.type}\n .acknowledged=${isAcknowledged(this.alert)}\n .active=${isActive(this.alert)}\n ></obc-alert-icon>\n </div>\n <div class=\"title\">\n <span>${this.alert.source}</span>\n </div>\n ${\n showCloseButton\n ? html`<div class=\"close-button\">\n <obc-icon-button variant=\"flat\" aria-label=${msg('Close')}>\n <obi-close-google></obi-close-google>\n </obc-icon-button>\n </div>`\n : nothing\n }\n </div>\n <div class=\"divider\"></div>\n <div class=\"body\">\n <div class=\"description\">\n <span>${this.alert.text}</span>\n </div>\n ${\n this.hasNote\n ? html`<div class=\"description sub-description\">\n <div class=\"label\">\n <slot name=\"note-label\">${msg('Note')}</slot>\n </div>\n <slot name=\"note\">${this.alert.note}</slot>\n </div>`\n : nothing\n }\n ${this.renderDetail(\n this.hasTagId,\n 'tagId',\n msg('Tag ID'),\n (alert) => alert.tagId\n )}\n ${this.renderDetail(\n this.hasCategory,\n 'category',\n msg('Category'),\n (alert) => alert.category\n )}\n ${this.renderDetail(\n this.hasActivated,\n 'time',\n msg('Activated'),\n (alert) => alert.time\n )}\n ${this.renderDetail(\n this.hasTimer,\n 'activated-timer',\n msg('Alert timer'),\n (alert) => alert.time,\n {timer: true}\n )}\n ${this.renderDetail(\n this.hasAcknowledged,\n 'acknowledgedAt',\n msg('Acknowledged'),\n (alert) => alert.acknowledged && alert.acknowledged.acknowledgedAt\n )}\n ${this.renderDetail(\n this.hasRectified,\n 'rectified',\n msg('Rectified'),\n (alert) => alert.active !== true && alert.active.rectifiedTime\n )}\n ${this.renderDetail(\n this.hasAcknowledgedBy,\n 'acknowledged-by',\n msg('Acknowledged by'),\n (alert) => alert.acknowledged && alert.acknowledged.acknowledgedBy\n )}\n ${this.renderDetail(\n this.hasShelvingTimer,\n 'shelving-timer',\n msg('Shelfing timer'),\n (alert) => alert.shelved && alert.shelved.shelvedStartTime,\n {timer: true}\n )}\n ${this.renderDetail(\n this.hasShelvedBy,\n 'shelved-by',\n msg('Shelved by'),\n (alert) => alert.shelved && alert.shelved.shelvedBy\n )}\n ${\n this.hasReadoutGraph\n ? html`\n <div class=\"readout-graph\">\n <div class=\"readout-graph-title\">\n <slot name=\"readout-graph-title\">${msg('Readout')}</slot>\n </div>\n <div class=\"readout-graph-container\">\n <slot name=\"readout-graph\"></slot>\n </div>\n </div>\n `\n : nothing\n }\n </div>\n ${\n this.hasActions\n ? html`<div class=\"actions\">\n <slot name=\"action\"></slot>\n </div>`\n : nothing\n }\n </div>\n `;\n }\n\n static override styles = unsafeCSS(compentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-alert-detail-page': ObcAlertDetailPage;\n }\n}\n"],"mappings":"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"}
|