@oicl/openbridge-webcomponents 2.0.0-next.114 → 2.0.0-next.116
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/bundle/openbridge-webcomponents.bundle.js +29 -8
- package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
- package/custom-elements.json +21 -4
- package/dist/building-blocks/readout-block/readout-block.d.ts.map +1 -1
- package/dist/building-blocks/readout-block/readout-block.js +5 -2
- package/dist/building-blocks/readout-block/readout-block.js.map +1 -1
- package/dist/components/text-input-field/text-input-field.d.ts +1 -1
- package/dist/components/text-input-field/text-input-field.d.ts.map +1 -1
- package/dist/components/text-input-field/text-input-field.js +5 -2
- package/dist/components/text-input-field/text-input-field.js.map +1 -1
- package/dist/components/toggle-switch/toggle-switch.d.ts +16 -1
- package/dist/components/toggle-switch/toggle-switch.d.ts.map +1 -1
- package/dist/components/toggle-switch/toggle-switch.js +6 -1
- package/dist/components/toggle-switch/toggle-switch.js.map +1 -1
- package/dist/navigation-instruments/readout/readout-formatters.d.ts +23 -1
- package/dist/navigation-instruments/readout/readout-formatters.d.ts.map +1 -1
- package/dist/navigation-instruments/readout/readout-formatters.js +6 -4
- package/dist/navigation-instruments/readout/readout-formatters.js.map +1 -1
- package/dist/navigation-instruments/readout/readout-shared.d.ts.map +1 -1
- package/dist/navigation-instruments/readout/readout-shared.js +9 -0
- package/dist/navigation-instruments/readout/readout-shared.js.map +1 -1
- package/package.json +1 -1
package/custom-elements.json
CHANGED
|
@@ -66350,7 +66350,15 @@
|
|
|
66350
66350
|
{
|
|
66351
66351
|
"kind": "method",
|
|
66352
66352
|
"name": "fireChangeEvent",
|
|
66353
|
-
"privacy": "private"
|
|
66353
|
+
"privacy": "private",
|
|
66354
|
+
"parameters": [
|
|
66355
|
+
{
|
|
66356
|
+
"name": "e",
|
|
66357
|
+
"type": {
|
|
66358
|
+
"text": "Event"
|
|
66359
|
+
}
|
|
66360
|
+
}
|
|
66361
|
+
]
|
|
66354
66362
|
},
|
|
66355
66363
|
{
|
|
66356
66364
|
"kind": "field",
|
|
@@ -66391,7 +66399,7 @@
|
|
|
66391
66399
|
"type": {
|
|
66392
66400
|
"text": "Event"
|
|
66393
66401
|
},
|
|
66394
|
-
"description": "
|
|
66402
|
+
"description": "{CustomEvent<{value: string}>} Dispatched on value change, carrying the committed value"
|
|
66395
66403
|
},
|
|
66396
66404
|
{
|
|
66397
66405
|
"description": "Fired when the input field is blurred",
|
|
@@ -69027,7 +69035,7 @@
|
|
|
69027
69035
|
"declarations": [
|
|
69028
69036
|
{
|
|
69029
69037
|
"kind": "class",
|
|
69030
|
-
"description": "`<obc-toggle-switch>` – A toggle switch component for binary on/off selection (also known as a switch, toggle, or enable/disable control).\n\nProvides a visual switch control for toggling between two states (checked/unchecked), commonly used for enabling or disabling a setting or feature. The component supports an optional label, description, icon, and divider for flexible presentation in lists or forms.\n\n---\n\n### Features\n- **Binary toggle:** Allows users to switch between checked (on) and unchecked (off) states.\n- **Label and Description:** Displays a primary label and an optional secondary description for context.\n- **Icon Support:** Can display a leading icon via the `icon` slot for visual emphasis.\n- **Disabled State:** Can be set to disabled, preventing user interaction and visually indicating inactivity.\n- **Bottom Divider:** Optional divider for use in lists or grouped settings.\n- **Responsive Layout:** Adapts label/description layout based on content; long descriptions are truncated with ellipsis.\n\n---\n\n### Usage Guidelines\nUse `obc-toggle-switch` for settings or preferences that require a simple on/off or enable/disable control. Ideal for scenarios where the user needs to quickly toggle a feature, such as activating notifications, enabling dark mode, or switching connectivity options. Avoid using for mutually exclusive choices—use radio buttons for those cases.\n\n- Place in forms, settings panels, or lists where binary choices are needed.\n- Use the description property to clarify the effect of the toggle if the label alone is not sufficient.\n- If an icon is relevant, provide it via the `icon` slot to reinforce the meaning.\n- For accessibility, ensure the label clearly describes the toggle's function.\n\n---\n\n### Slots\n| Slot Name | Renders When... | Purpose |\n|-----------|---------------------|-------------------------------------------|\n| icon | `hasIcon` is true | Leading icon to visually represent toggle |\n\n---\n\n### Properties and Attributes\n- `label` (string): Main label for the toggle (required for clarity).\n- `checked` (boolean): Whether the toggle is in the \"on\" state. Defaults to `false`.\n- `disabled` (boolean): Disables interaction and applies a disabled style.\n- `hasDescription` (boolean): If true, shows the description text below the label.\n- `description` (string): Supplementary text shown when `hasDescription` is true.\n- `hasBottomDivider` (boolean): If true, renders a divider below the toggle (useful in lists).\n- `hasIcon` (boolean): If true, displays the `icon` slot before the label.\n\n---\n\n### Events\n- `input` – Fired when the toggle state changes (checked/unchecked).\n\n---\n\n### Best Practices\n- Use concise labels and keep descriptions brief; long descriptions are truncated.\n- Only use the divider when presenting multiple toggles in a list for visual separation.\n- For accessibility, ensure the label is descriptive and unique within the context.\n- Avoid using toggle switches for actions that require confirmation or have destructive effects.\n- For mutually exclusive options, use radio buttons instead.\n\n---\n\n**Example:**\n```html\n<obc-toggle-switch\n label=\"Enable notifications\"\n ?checked=${true}\n ?hasDescription=${true}\n description=\"Receive updates and alerts\"\n ?hasIcon=${true}\n>\n <obi-placeholder slot=\"icon\"></obi-placeholder>\n</obc-toggle-switch>\n```\n\nIn this example, the toggle switch displays a label, an icon, and a description, and is in the checked state.",
|
|
69038
|
+
"description": "`<obc-toggle-switch>` – A toggle switch component for binary on/off selection (also known as a switch, toggle, or enable/disable control).\n\nProvides a visual switch control for toggling between two states (checked/unchecked), commonly used for enabling or disabling a setting or feature. The component supports an optional label, description, icon, and divider for flexible presentation in lists or forms.\n\n---\n\n### Features\n- **Binary toggle:** Allows users to switch between checked (on) and unchecked (off) states.\n- **Label and Description:** Displays a primary label and an optional secondary description for context.\n- **Icon Support:** Can display a leading icon via the `icon` slot for visual emphasis.\n- **Disabled State:** Can be set to disabled, preventing user interaction and visually indicating inactivity.\n- **Bottom Divider:** Optional divider for use in lists or grouped settings.\n- **Responsive Layout:** Adapts label/description layout based on content; long descriptions are truncated with ellipsis.\n\n---\n\n### Usage Guidelines\nUse `obc-toggle-switch` for settings or preferences that require a simple on/off or enable/disable control. Ideal for scenarios where the user needs to quickly toggle a feature, such as activating notifications, enabling dark mode, or switching connectivity options. Avoid using for mutually exclusive choices—use radio buttons for those cases.\n\n- Place in forms, settings panels, or lists where binary choices are needed.\n- Use the description property to clarify the effect of the toggle if the label alone is not sufficient.\n- If an icon is relevant, provide it via the `icon` slot to reinforce the meaning.\n- For accessibility, ensure the label clearly describes the toggle's function.\n\n---\n\n### Slots\n| Slot Name | Renders When... | Purpose |\n|-----------|---------------------|-------------------------------------------|\n| icon | `hasIcon` is true | Leading icon to visually represent toggle |\n\n---\n\n### Properties and Attributes\n- `label` (string): Main label for the toggle (required for clarity).\n- `checked` (boolean): Whether the toggle is in the \"on\" state. Defaults to `false`.\n- `disabled` (boolean): Disables interaction and applies a disabled style.\n- `hasDescription` (boolean): If true, shows the description text below the label.\n- `description` (string): Supplementary text shown when `hasDescription` is true.\n- `hasBottomDivider` (boolean): If true, renders a divider below the toggle (useful in lists).\n- `hasIcon` (boolean): If true, displays the `icon` slot before the label.\n\n---\n\n### Events\n- `input` – Fired when the toggle state changes (checked/unchecked).\n- `change` – Fired when the toggle state changes by user interaction.\n\nBoth events report the state the user selected. When `externalControl` is\ntrue the component does not update itself; the consumer decides whether to\napply the reported state to `checked` and may reject the interaction by\nleaving `checked` unchanged.\n\n---\n\n### Best Practices\n- Use concise labels and keep descriptions brief; long descriptions are truncated.\n- Only use the divider when presenting multiple toggles in a list for visual separation.\n- For accessibility, ensure the label is descriptive and unique within the context.\n- Avoid using toggle switches for actions that require confirmation or have destructive effects.\n- For mutually exclusive options, use radio buttons instead.\n\n---\n\n**Example:**\n```html\n<obc-toggle-switch\n label=\"Enable notifications\"\n ?checked=${true}\n ?hasDescription=${true}\n description=\"Receive updates and alerts\"\n ?hasIcon=${true}\n>\n <obi-placeholder slot=\"icon\"></obi-placeholder>\n</obc-toggle-switch>\n```\n\nIn this example, the toggle switch displays a label, an icon, and a description, and is in the checked state.",
|
|
69031
69039
|
"name": "ObcToggleSwitch",
|
|
69032
69040
|
"slots": [
|
|
69033
69041
|
{
|
|
@@ -69116,6 +69124,15 @@
|
|
|
69116
69124
|
"description": "If true, the toggle is controlled externally.\nUse to control the toggle state from outside the component.",
|
|
69117
69125
|
"attribute": "externalControl"
|
|
69118
69126
|
},
|
|
69127
|
+
{
|
|
69128
|
+
"kind": "field",
|
|
69129
|
+
"name": "_userSelectedChecked",
|
|
69130
|
+
"type": {
|
|
69131
|
+
"text": "boolean | undefined"
|
|
69132
|
+
},
|
|
69133
|
+
"privacy": "private",
|
|
69134
|
+
"description": "The state the user selected in the most recent interaction. In\nexternalControl mode this can differ from `checked` until the consumer\naccepts the change, so the change event reports it instead of `checked`."
|
|
69135
|
+
},
|
|
69119
69136
|
{
|
|
69120
69137
|
"kind": "method",
|
|
69121
69138
|
"name": "_tryChange",
|
|
@@ -69157,7 +69174,7 @@
|
|
|
69157
69174
|
"type": {
|
|
69158
69175
|
"text": "CustomEvent"
|
|
69159
69176
|
},
|
|
69160
|
-
"description": "Dispatched when the value of the input changes by user interaction"
|
|
69177
|
+
"description": "{ObcToggleSwitchChangeEvent} Dispatched when the value of the input changes by user interaction"
|
|
69161
69178
|
}
|
|
69162
69179
|
],
|
|
69163
69180
|
"attributes": [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readout-block.d.ts","sourceRoot":"","sources":["../../../src/building-blocks/readout-block/readout-block.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAgD,MAAM,KAAK,CAAC;AAK9E,OAAO,qCAAqC,CAAC;AAC7C,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,iCAAiC,CAAC;AACzC,OAAO,yCAAyC,CAAC;AACjD,OAAO,
|
|
1
|
+
{"version":3,"file":"readout-block.d.ts","sourceRoot":"","sources":["../../../src/building-blocks/readout-block/readout-block.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAgD,MAAM,KAAK,CAAC;AAK9E,OAAO,qCAAqC,CAAC;AAC7C,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,iCAAiC,CAAC;AACzC,OAAO,yCAAyC,CAAC;AACjD,OAAO,EAOL,gBAAgB,EAEjB,MAAM,4DAA4D,CAAC;AACpE,OAAO,EACL,KAAK,gBAAgB,EAEtB,MAAM,6CAA6C,CAAC;AAGrD,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAC,gBAAgB,EAAC,MAAM,4DAA4D,CAAC;AAE5F;;;;;;GAMG;AACH,oBAAY,mBAAmB;IAC7B,KAAK,UAAU;IACf,QAAQ,aAAa;IACrB,MAAM,WAAW;CAClB;AAED;;;;;GAKG;AACH,oBAAY,gBAAgB;IAC1B,KAAK,UAAU;IACf,MAAM,WAAW;IACjB,KAAK,UAAU;CAChB;AAED;;;;GAIG;AACH,oBAAY,uBAAuB;IACjC,YAAY,kBAAkB;IAC9B,OAAO,YAAY;CACpB;AAED;;;GAGG;AACH,oBAAY,qBAAqB;IAC/B,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,MAAM,WAAW;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBACa,eAAgB,SAAQ,UAAU;IAC7C,oDAAoD;IAC1B,OAAO,EAAE,mBAAmB,CAC1B;IAE5B;;;OAGG;IACuB,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAQ;IAE/D;;;;OAIG;IACuB,SAAS,EAAE,gBAAgB,CAC3B;IAE1B,kDAAkD;IACxB,IAAI,EAAE,gBAAgB,CAA0B;IAE1E;;;;OAIG;IACuB,SAAS,CAAC,EAAE,cAAc,CAAC;IAErD,uCAAuC;IACZ,QAAQ,UAAS;IAE5C,6EAA6E;IACnD,MAAM,EAAE,oBAAoB,CACvB;IAE/B,yDAAyD;IAC9B,SAAS,UAAS;IAE7C,8EAA8E;IACnD,OAAO,UAAS;IAE3C;;;OAGG;IACuB,cAAc,SAAK;IAE7C;;;OAGG;IACuB,SAAS,SAAK;IAExC;;;OAGG;IACwB,WAAW,UAAS;IAE/C,sEAAsE;IAC5C,aAAa,CAAC,EAAE,MAAM,CAAC;IAEjD,0EAA0E;IAC/C,GAAG,UAAS;IAEvC,qCAAqC;IACX,OAAO,SAAS;IAE1C,8DAA8D;IACpC,SAAS,EAAE,mBAAmB,CAC5B;IAE5B,oDAAoD;IAC1B,WAAW,CAAC,EAAE,uBAAuB,CAAC;IAKhE,kEAAkE;IACxC,KAAK,EAAE,OAAO,GAAG,gBAAgB,CAAS;IAEpE,4EAA4E;IACjD,QAAQ,UAAS;IAE5C,0EAA0E;IAChD,SAAS,EAAE,qBAAqB,CAC7B;IAEpB,OAAO,CAAC,eAAe,CAAS;IAEzC,OAAO,KAAK,iBAAiB,GAY5B;IAED,OAAO,KAAK,oBAAoB,GAS/B;IAED,2EAA2E;IAC3E,OAAO,KAAK,YAAY,GASvB;IAED;;;;;OAKG;IACH,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,gBAAgB,CAMtB;IAEF,OAAO,CAAC,UAAU;IAsBlB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;cAiBN,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAYzD,MAAM;IA+Ef,OAAgB,MAAM,0BAA6B;CACpD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,mBAAmB,EAAE,eAAe,CAAC;KACtC;CACF"}
|
|
@@ -6,7 +6,7 @@ import { customElement } from "../../decorator.js";
|
|
|
6
6
|
import { ObcTextboxFontWeight, ObcTextboxAlignment, ObcTextboxSize } from "../../components/textbox/textbox.js";
|
|
7
7
|
import "../../icons/icon-input-right.js";
|
|
8
8
|
import "../../icons/icon-notification-advice.js";
|
|
9
|
-
import { ReadoutValueType, assertReadoutValueType, resolveReadoutNumericValue, resolveReadoutTextValue, formatNumericValue, readoutFormattedInteger } from "../../navigation-instruments/readout/readout-formatters.js";
|
|
9
|
+
import { ReadoutValueType, assertReadoutValueType, resolveReadoutNumericValue, resolveReadoutTextValue, READOUT_UNAVAILABLE_DASH, formatNumericValue, readoutFormattedInteger } from "../../navigation-instruments/readout/readout-formatters.js";
|
|
10
10
|
import { wrapWithAlertFrame } from "../../components/alert-frame/alert-frame.js";
|
|
11
11
|
var __defProp = Object.defineProperty;
|
|
12
12
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -81,6 +81,9 @@ let ObcReadoutBlock = class extends LitElement {
|
|
|
81
81
|
}
|
|
82
82
|
get numericFormatOptions() {
|
|
83
83
|
return {
|
|
84
|
+
// The unavailable placeholder stays short (`\u2012.\u2012\u2012`) rather than
|
|
85
|
+
// spelling out every reserved digit position — `maxDigits` already
|
|
86
|
+
// reserves the width, so it simply sits at the right edge of it.
|
|
84
87
|
showZeroPadding: false,
|
|
85
88
|
minValueLength: this.maxDigits,
|
|
86
89
|
fractionDigits: this.fractionDigits
|
|
@@ -166,7 +169,7 @@ let ObcReadoutBlock = class extends LitElement {
|
|
|
166
169
|
this.valueType
|
|
167
170
|
);
|
|
168
171
|
const textValue = resolveReadoutTextValue(this.value, this.valueType);
|
|
169
|
-
const text = this.off ? this.offText : isTextMode ? textValue ??
|
|
172
|
+
const text = this.off ? this.offText : isTextMode ? textValue ?? READOUT_UNAVAILABLE_DASH : formatNumericValue(valueForFormat, formatOptions);
|
|
170
173
|
const hintCount = this.off || isTextMode || !this.hintedZeros || valueForFormat === void 0 || valueForFormat < 0 ? 0 : Math.max(this.maxDigits - readoutFormattedInteger(text), 0);
|
|
171
174
|
const hinted = hintCount > 0 ? "0".repeat(hintCount) : "";
|
|
172
175
|
const reserver = isTextMode ? this.spaceReserver ?? "" : this.hintedZeros ? this.reserverText : this.widerReserver(this.spaceReserver, this.reserverText);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readout-block.js","sources":["../../../src/building-blocks/readout-block/readout-block.ts"],"sourcesContent":["import {LitElement, html, nothing, unsafeCSS, type TemplateResult} from 'lit';\nimport {property, state} from 'lit/decorators.js';\nimport {classMap} from 'lit/directives/class-map.js';\nimport componentStyle from './readout-block.css?inline';\nimport {customElement} from '../../decorator.js';\nimport '../../components/textbox/textbox.js';\nimport {\n ObcTextboxSize,\n ObcTextboxFontWeight,\n ObcTextboxAlignment,\n} from '../../components/textbox/textbox.js';\nimport '../../icons/icon-input-right.js';\nimport '../../icons/icon-notification-advice.js';\nimport {\n formatNumericValue,\n readoutFormattedInteger,\n assertReadoutValueType,\n resolveReadoutNumericValue,\n resolveReadoutTextValue,\n ReadoutValueType,\n type ReadoutNumericFormatOptions,\n} from '../../navigation-instruments/readout/readout-formatters.js';\nimport {\n type AlertFrameConfig,\n wrapWithAlertFrame,\n} from '../../components/alert-frame/alert-frame.js';\n\n// Re-exported so consumers can configure typography without a second import path.\nexport {\n ObcTextboxSize,\n ObcTextboxFontWeight,\n ObcTextboxAlignment,\n} from '../../components/textbox/textbox.js';\nexport {ReadoutValueType} from '../../navigation-instruments/readout/readout-formatters.js';\n\n/**\n * Semantic variant of the block. Drives the default marker icon and the\n * colour token; the layout is identical across variants.\n * - `value`: the primary reading (no default marker icon).\n * - `setpoint`: a setpoint reference (default `input-right` marker).\n * - `advice`: an advisory reference (default `notification-advice` marker).\n */\nexport enum ReadoutBlockVariant {\n value = 'value',\n setpoint = 'setpoint',\n advice = 'advice',\n}\n\n/**\n * Density tier of the block — drives icon size, the icon↔number gap, and the\n * degree-column width tier. The number typography size is controlled\n * independently via {@link ObcReadoutBlock.valueSize} so a parent can de-emphasise\n * one block relative to another within the same tier.\n */\nexport enum ReadoutBlockSize {\n small = 'small',\n medium = 'medium',\n large = 'large',\n}\n\n/**\n * Per-block measurement quality, rendered as a non-shifting outline chip.\n * - `low-integrity`: the value is suspect.\n * - `invalid`: the value is invalid.\n */\nexport enum ReadoutBlockDataQuality {\n lowIntegrity = 'low-integrity',\n invalid = 'invalid',\n}\n\n/**\n * Pop-up fade phase for a setpoint block. Driven by the parent's setpoint\n * interaction state machine; only meaningful for `role=\"setpoint\"`.\n */\nexport enum ReadoutBlockHidePhase {\n none = 'none',\n hiding = 'hiding',\n hidden = 'hidden',\n}\n\n/**\n * `<obc-readout-block>` – the most atomic readout primitive: a single\n * cap-height-aligned, width-reservable numeric segment (value / setpoint /\n * advice).\n *\n * It renders one `obc-textbox` number with optional hinted leading zeros, a\n * reservable width, an optional leading marker icon (via the `icon` slot or the\n * role default), an optional trailing degree glyph, an `off`/unavailable text\n * state, per-block data-quality and an optional per-block alert frame.\n *\n * Setting `valueType` to `text` renders `value` verbatim (e.g.\n * `\"Auto\"`) instead of a formatted number.\n *\n * This is a building block used inside `obc-readout-list-item` (and, in a future\n * refactor, inside `obc-readout`); it is not normally used on its own. Colour is\n * inherited from the host context (the parent sets the role colour), so the\n * block stays neutral until placed.\n *\n * @experimental Pilot for the new primitives + per-block options Readout API; the\n * API may change in a future release.\n *\n * @slot icon - Replaces the role's default marker icon.\n *\n * @csspart block - The block container (carries role / tone / data-quality).\n * @csspart block-content - The number + degree group.\n * @csspart block-text - The `obc-textbox` rendering the number.\n * @csspart block-icon - The leading marker-icon container.\n * @csspart degree - The trailing degree-glyph column.\n */\n@customElement('obc-readout-block')\nexport class ObcReadoutBlock extends LitElement {\n /** Semantic variant (value / setpoint / advice). */\n @property({type: String}) variant: ReadoutBlockVariant =\n ReadoutBlockVariant.value;\n\n /**\n * The value; `null`/`undefined` renders a dash. A number by default, or text\n * when {@link valueType} is `text`.\n */\n @property({type: String}) value: number | string | null = null;\n\n /**\n * How {@link value} is interpreted. `number` (default) formats it via\n * `fractionDigits`; `text` renders it verbatim and ignores the numeric\n * format options. Passing text while this is `number` throws.\n */\n @property({type: String}) valueType: ReadoutValueType =\n ReadoutValueType.number;\n\n /** Density tier — icon size, gap, degree tier. */\n @property({type: String}) size: ReadoutBlockSize = ReadoutBlockSize.small;\n\n /**\n * Resolved number-typography size. When unset it is derived from `size`\n * (small→s, medium→m, large→l), so a parent that de-emphasises a block (e.g.\n * a secondary setpoint) can pass a smaller size without changing the tier.\n */\n @property({type: String}) valueSize?: ObcTextboxSize;\n\n /** Accent (in-command) colour tone. */\n @property({type: Boolean}) enhanced = false;\n\n /** Number font weight (regular / semibold / bold); colour is independent. */\n @property({type: String}) weight: ObcTextboxFontWeight =\n ObcTextboxFontWeight.regular;\n\n /** Render the trailing cap-height degree glyph (`°`). */\n @property({type: Boolean}) hasDegree = false;\n\n /** Show the leading marker-icon container (always on for setpoint/advice). */\n @property({type: Boolean}) hasIcon = false;\n\n /**\n * Number of fraction digits.\n * @availableWhen valueType==number\n */\n @property({type: Number}) fractionDigits = 0;\n\n /**\n * Integer digits to reserve / hint (independent of `fractionDigits`).\n * @availableWhen valueType==number\n */\n @property({type: Number}) maxDigits = 0;\n\n /**\n * Render muted leading zeros filling the integer part to `maxDigits`.\n * @availableWhen valueType==number\n */\n @property({type: Boolean}) hintedZeros = false;\n\n /** Explicit longest string to reserve width for (e.g. `\"0000.0\"`). */\n @property({type: String}) spaceReserver?: string;\n\n /** Render `offText` instead of a number (e.g. equipment powered down). */\n @property({type: Boolean}) off = false;\n\n /** Text shown when `off` is true. */\n @property({type: String}) offText = 'OFF';\n\n /** Text alignment of the number within its reserved width. */\n @property({type: String}) alignment: ObcTextboxAlignment =\n ObcTextboxAlignment.Right;\n\n /** Per-block measurement quality (outline chip). */\n @property({type: String}) dataQuality?: ReadoutBlockDataQuality;\n\n // `boolean | …` (not `false | …`): the generated Angular wrapper widens a\n // literal-`false` union to `boolean`. `wrapWithAlertFrame` treats any\n // non-object as \"no frame\", so accepting `boolean` is harmless.\n /** Per-block alert frame; nests inside any parent alert frame. */\n @property({type: Object}) alert: boolean | AlertFrameConfig = false;\n\n /** Setpoint focus (touch) state — only meaningful for `role=\"setpoint\"`. */\n @property({type: Boolean}) touching = false;\n\n /** Setpoint pop-up fade phase — only meaningful for `role=\"setpoint\"`. */\n @property({type: String}) hidePhase: ReadoutBlockHidePhase =\n ReadoutBlockHidePhase.none;\n\n @state() private hasAssignedIcon = false;\n\n private get resolvedValueSize(): ObcTextboxSize {\n if (this.valueSize) {\n return this.valueSize;\n }\n switch (this.size) {\n case ReadoutBlockSize.large:\n return ObcTextboxSize.l;\n case ReadoutBlockSize.medium:\n return ObcTextboxSize.m;\n default:\n return ObcTextboxSize.s;\n }\n }\n\n private get numericFormatOptions(): ReadoutNumericFormatOptions {\n return {\n showZeroPadding: false,\n minValueLength: this.maxDigits,\n fractionDigits: this.fractionDigits,\n };\n }\n\n /** Widest possible value string for width reservation (e.g. `\"000.0\"`). */\n private get reserverText(): string {\n const maxDigits = this.maxDigits;\n if (maxDigits <= 0) {\n return '';\n }\n const integer = '0'.repeat(Math.max(maxDigits, 1));\n return this.fractionDigits > 0\n ? `${integer}.${'0'.repeat(this.fractionDigits)}`\n : integer;\n }\n\n /**\n * Effective width reserver: the wider of the explicit `spaceReserver` and the\n * `maxDigits`/`fractionDigits`-derived reserve, so an explicit reserver can\n * never reserve *less* than the formatted value needs. Under tabular-nums the\n * rendered width is proportional to character count, so \"wider\" compares length.\n */\n private widerReserver(explicit: string | undefined, derived: string): string {\n if (!explicit) {\n return derived;\n }\n if (!derived) {\n return explicit;\n }\n return explicit.length >= derived.length ? explicit : derived;\n }\n\n private dataQualityClasses(): Record<string, boolean> {\n return {\n 'data-low-integrity':\n this.dataQuality === ReadoutBlockDataQuality.lowIntegrity,\n 'data-invalid': this.dataQuality === ReadoutBlockDataQuality.invalid,\n };\n }\n\n private onIconSlotChange = (event: Event): void => {\n // `slotchange` fires after the first render once content is (re)assigned,\n // so it covers the initial state without a firstUpdated re-render.\n this.hasAssignedIcon =\n (event.target as HTMLSlotElement).assignedElements({flatten: true})\n .length > 0;\n };\n\n private renderIcon(): TemplateResult | typeof nothing {\n // Value blocks only show an icon when asked; setpoint/advice always reserve\n // their marker. The role default is rendered as a direct child (so it sizes\n // via `.block-icon obi-*`) and hidden once an icon is assigned to the slot —\n // `{flatten: true}` sees through a forwarded-but-empty parent slot, so the\n // default still shows when the consumer overrides nothing.\n const showIcon = this.variant !== ReadoutBlockVariant.value || this.hasIcon;\n if (!showIcon) {\n return nothing;\n }\n let fallback: TemplateResult | typeof nothing = nothing;\n if (this.variant === ReadoutBlockVariant.setpoint) {\n fallback = html`<obi-input-right></obi-input-right>`;\n } else if (this.variant === ReadoutBlockVariant.advice) {\n fallback = html`<obi-notification-advice></obi-notification-advice>`;\n }\n return html`<span class=\"block-icon\" part=\"block-icon\" aria-hidden=\"true\">\n <slot name=\"icon\" @slotchange=${this.onIconSlotChange}></slot>\n ${this.hasAssignedIcon ? nothing : fallback}\n </span>`;\n }\n\n /**\n * A cap-height `°` column whose width scales with the number size. Inherits the\n * block's colour.\n */\n private renderDegreeGlyph(size: ObcTextboxSize): TemplateResult {\n return html`\n <span\n class=${classMap({\n 'degree-column': true,\n [`degree-${size}`]: true,\n 'degree-inherit': true,\n })}\n part=\"degree\"\n >\n <obc-textbox class=\"degree-glyph\" .size=${size} alignment=\"center\"\n >°</obc-textbox\n >\n </span>\n `;\n }\n\n protected override willUpdate(changed: Map<string, unknown>): void {\n super.willUpdate(changed);\n // Validated on EVERY update, deliberately NOT gated on `value`/`valueType`\n // appearing in `changed`. When this assertion throws, Lit's `performUpdate`\n // catch calls `__markUpdated()`, which clears the changed-properties map. A\n // later update driven by any OTHER property — inside `obc-readout-list`,\n // `align()` writing the shared reservers — would then see no `value` in\n // `changed`, skip the check, and render the invalid value as a plain dash:\n // exactly the silent failure this assertion exists to prevent.\n assertReadoutValueType('obc-readout-block', this.value, this.valueType);\n }\n\n override render() {\n const valueSize = this.resolvedValueSize;\n const formatOptions = this.numericFormatOptions;\n const isTextMode = this.valueType === ReadoutValueType.text;\n const valueForFormat = resolveReadoutNumericValue(\n this.value,\n this.valueType\n );\n const textValue = resolveReadoutTextValue(this.value, this.valueType);\n // Text mode renders verbatim and ignores the numeric format options; a\n // blank / missing text value still falls back to the unavailable dash.\n const text = this.off\n ? this.offText\n : isTextMode\n ? (textValue ?? '-')\n : formatNumericValue(valueForFormat, formatOptions);\n // Hinted zeros pad the INTEGER part up to `maxDigits`, independent of\n // `fractionDigits` (the decimal point and fraction digits never count toward\n // `maxDigits`). Negative / dashed values are not padded. Example: value 1.2,\n // maxDigits 3, fractionDigits 1 → \"001.2\".\n const hintCount =\n this.off ||\n isTextMode ||\n !this.hintedZeros ||\n valueForFormat === undefined ||\n valueForFormat < 0\n ? 0\n : Math.max(this.maxDigits - readoutFormattedInteger(text), 0);\n const hinted = hintCount > 0 ? '0'.repeat(hintCount) : '';\n // Hinted zeros own the width — they already fill to `maxDigits` — so when\n // `hintedZeros` is enabled an explicit `spaceReserver` is ignored (it has\n // higher priority). Otherwise the wider of the explicit reserver and the\n // `maxDigits`-derived reserve wins.\n // Text mode ignores the `maxDigits`-derived numeric reserve — only an\n // explicit `spaceReserver` still applies.\n const reserver = isTextMode\n ? (this.spaceReserver ?? '')\n : this.hintedZeros\n ? this.reserverText\n : this.widerReserver(this.spaceReserver, this.reserverText);\n\n const block = html`\n <div\n class=${classMap({\n block: true,\n [`block-${this.variant}`]: true,\n [`size-${this.size}`]: true,\n 'tone-enhanced': this.enhanced,\n touching: this.touching,\n 'is-hiding': this.hidePhase === ReadoutBlockHidePhase.hiding,\n 'is-hidden': this.hidePhase === ReadoutBlockHidePhase.hidden,\n ...this.dataQualityClasses(),\n })}\n part=\"block block-${this.variant}\"\n >\n ${this.renderIcon()}\n <span class=\"block-content\" part=\"block-content\">\n <obc-textbox\n class=\"block-text\"\n part=\"block-text\"\n .size=${valueSize}\n .fontWeight=${this.weight}\n .alignment=${this.alignment}\n .tabularNums=${true}\n >\n ${hinted\n ? html`<span class=\"hinted-zero\" aria-hidden=\"true\"\n >${hinted}</span\n >`\n : nothing}${text}\n ${reserver ? html`<span slot=\"length\">${reserver}</span>` : nothing}\n </obc-textbox>\n ${this.hasDegree ? this.renderDegreeGlyph(valueSize) : nothing}\n </span>\n </div>\n `;\n return wrapWithAlertFrame(this.alert ?? false, block);\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-readout-block': ObcReadoutBlock;\n }\n}\n"],"names":["ReadoutBlockVariant","ReadoutBlockSize","ReadoutBlockDataQuality","ReadoutBlockHidePhase"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"readout-block.js","sources":["../../../src/building-blocks/readout-block/readout-block.ts"],"sourcesContent":["import {LitElement, html, nothing, unsafeCSS, type TemplateResult} from 'lit';\nimport {property, state} from 'lit/decorators.js';\nimport {classMap} from 'lit/directives/class-map.js';\nimport componentStyle from './readout-block.css?inline';\nimport {customElement} from '../../decorator.js';\nimport '../../components/textbox/textbox.js';\nimport {\n ObcTextboxSize,\n ObcTextboxFontWeight,\n ObcTextboxAlignment,\n} from '../../components/textbox/textbox.js';\nimport '../../icons/icon-input-right.js';\nimport '../../icons/icon-notification-advice.js';\nimport {\n formatNumericValue,\n readoutFormattedInteger,\n assertReadoutValueType,\n resolveReadoutNumericValue,\n resolveReadoutTextValue,\n READOUT_UNAVAILABLE_DASH,\n ReadoutValueType,\n type ReadoutNumericFormatOptions,\n} from '../../navigation-instruments/readout/readout-formatters.js';\nimport {\n type AlertFrameConfig,\n wrapWithAlertFrame,\n} from '../../components/alert-frame/alert-frame.js';\n\n// Re-exported so consumers can configure typography without a second import path.\nexport {\n ObcTextboxSize,\n ObcTextboxFontWeight,\n ObcTextboxAlignment,\n} from '../../components/textbox/textbox.js';\nexport {ReadoutValueType} from '../../navigation-instruments/readout/readout-formatters.js';\n\n/**\n * Semantic variant of the block. Drives the default marker icon and the\n * colour token; the layout is identical across variants.\n * - `value`: the primary reading (no default marker icon).\n * - `setpoint`: a setpoint reference (default `input-right` marker).\n * - `advice`: an advisory reference (default `notification-advice` marker).\n */\nexport enum ReadoutBlockVariant {\n value = 'value',\n setpoint = 'setpoint',\n advice = 'advice',\n}\n\n/**\n * Density tier of the block — drives icon size, the icon↔number gap, and the\n * degree-column width tier. The number typography size is controlled\n * independently via {@link ObcReadoutBlock.valueSize} so a parent can de-emphasise\n * one block relative to another within the same tier.\n */\nexport enum ReadoutBlockSize {\n small = 'small',\n medium = 'medium',\n large = 'large',\n}\n\n/**\n * Per-block measurement quality, rendered as a non-shifting outline chip.\n * - `low-integrity`: the value is suspect.\n * - `invalid`: the value is invalid.\n */\nexport enum ReadoutBlockDataQuality {\n lowIntegrity = 'low-integrity',\n invalid = 'invalid',\n}\n\n/**\n * Pop-up fade phase for a setpoint block. Driven by the parent's setpoint\n * interaction state machine; only meaningful for `role=\"setpoint\"`.\n */\nexport enum ReadoutBlockHidePhase {\n none = 'none',\n hiding = 'hiding',\n hidden = 'hidden',\n}\n\n/**\n * `<obc-readout-block>` – the most atomic readout primitive: a single\n * cap-height-aligned, width-reservable numeric segment (value / setpoint /\n * advice).\n *\n * It renders one `obc-textbox` number with optional hinted leading zeros, a\n * reservable width, an optional leading marker icon (via the `icon` slot or the\n * role default), an optional trailing degree glyph, an `off`/unavailable text\n * state, per-block data-quality and an optional per-block alert frame.\n *\n * Setting `valueType` to `text` renders `value` verbatim (e.g.\n * `\"Auto\"`) instead of a formatted number.\n *\n * This is a building block used inside `obc-readout-list-item` (and, in a future\n * refactor, inside `obc-readout`); it is not normally used on its own. Colour is\n * inherited from the host context (the parent sets the role colour), so the\n * block stays neutral until placed.\n *\n * @experimental Pilot for the new primitives + per-block options Readout API; the\n * API may change in a future release.\n *\n * @slot icon - Replaces the role's default marker icon.\n *\n * @csspart block - The block container (carries role / tone / data-quality).\n * @csspart block-content - The number + degree group.\n * @csspart block-text - The `obc-textbox` rendering the number.\n * @csspart block-icon - The leading marker-icon container.\n * @csspart degree - The trailing degree-glyph column.\n */\n@customElement('obc-readout-block')\nexport class ObcReadoutBlock extends LitElement {\n /** Semantic variant (value / setpoint / advice). */\n @property({type: String}) variant: ReadoutBlockVariant =\n ReadoutBlockVariant.value;\n\n /**\n * The value; `null`/`undefined` renders a dash. A number by default, or text\n * when {@link valueType} is `text`.\n */\n @property({type: String}) value: number | string | null = null;\n\n /**\n * How {@link value} is interpreted. `number` (default) formats it via\n * `fractionDigits`; `text` renders it verbatim and ignores the numeric\n * format options. Passing text while this is `number` throws.\n */\n @property({type: String}) valueType: ReadoutValueType =\n ReadoutValueType.number;\n\n /** Density tier — icon size, gap, degree tier. */\n @property({type: String}) size: ReadoutBlockSize = ReadoutBlockSize.small;\n\n /**\n * Resolved number-typography size. When unset it is derived from `size`\n * (small→s, medium→m, large→l), so a parent that de-emphasises a block (e.g.\n * a secondary setpoint) can pass a smaller size without changing the tier.\n */\n @property({type: String}) valueSize?: ObcTextboxSize;\n\n /** Accent (in-command) colour tone. */\n @property({type: Boolean}) enhanced = false;\n\n /** Number font weight (regular / semibold / bold); colour is independent. */\n @property({type: String}) weight: ObcTextboxFontWeight =\n ObcTextboxFontWeight.regular;\n\n /** Render the trailing cap-height degree glyph (`°`). */\n @property({type: Boolean}) hasDegree = false;\n\n /** Show the leading marker-icon container (always on for setpoint/advice). */\n @property({type: Boolean}) hasIcon = false;\n\n /**\n * Number of fraction digits.\n * @availableWhen valueType==number\n */\n @property({type: Number}) fractionDigits = 0;\n\n /**\n * Integer digits to reserve / hint (independent of `fractionDigits`).\n * @availableWhen valueType==number\n */\n @property({type: Number}) maxDigits = 0;\n\n /**\n * Render muted leading zeros filling the integer part to `maxDigits`.\n * @availableWhen valueType==number\n */\n @property({type: Boolean}) hintedZeros = false;\n\n /** Explicit longest string to reserve width for (e.g. `\"0000.0\"`). */\n @property({type: String}) spaceReserver?: string;\n\n /** Render `offText` instead of a number (e.g. equipment powered down). */\n @property({type: Boolean}) off = false;\n\n /** Text shown when `off` is true. */\n @property({type: String}) offText = 'OFF';\n\n /** Text alignment of the number within its reserved width. */\n @property({type: String}) alignment: ObcTextboxAlignment =\n ObcTextboxAlignment.Right;\n\n /** Per-block measurement quality (outline chip). */\n @property({type: String}) dataQuality?: ReadoutBlockDataQuality;\n\n // `boolean | …` (not `false | …`): the generated Angular wrapper widens a\n // literal-`false` union to `boolean`. `wrapWithAlertFrame` treats any\n // non-object as \"no frame\", so accepting `boolean` is harmless.\n /** Per-block alert frame; nests inside any parent alert frame. */\n @property({type: Object}) alert: boolean | AlertFrameConfig = false;\n\n /** Setpoint focus (touch) state — only meaningful for `role=\"setpoint\"`. */\n @property({type: Boolean}) touching = false;\n\n /** Setpoint pop-up fade phase — only meaningful for `role=\"setpoint\"`. */\n @property({type: String}) hidePhase: ReadoutBlockHidePhase =\n ReadoutBlockHidePhase.none;\n\n @state() private hasAssignedIcon = false;\n\n private get resolvedValueSize(): ObcTextboxSize {\n if (this.valueSize) {\n return this.valueSize;\n }\n switch (this.size) {\n case ReadoutBlockSize.large:\n return ObcTextboxSize.l;\n case ReadoutBlockSize.medium:\n return ObcTextboxSize.m;\n default:\n return ObcTextboxSize.s;\n }\n }\n\n private get numericFormatOptions(): ReadoutNumericFormatOptions {\n return {\n // The unavailable placeholder stays short (`\\u2012.\\u2012\\u2012`) rather than\n // spelling out every reserved digit position — `maxDigits` already\n // reserves the width, so it simply sits at the right edge of it.\n showZeroPadding: false,\n minValueLength: this.maxDigits,\n fractionDigits: this.fractionDigits,\n };\n }\n\n /** Widest possible value string for width reservation (e.g. `\"000.0\"`). */\n private get reserverText(): string {\n const maxDigits = this.maxDigits;\n if (maxDigits <= 0) {\n return '';\n }\n const integer = '0'.repeat(Math.max(maxDigits, 1));\n return this.fractionDigits > 0\n ? `${integer}.${'0'.repeat(this.fractionDigits)}`\n : integer;\n }\n\n /**\n * Effective width reserver: the wider of the explicit `spaceReserver` and the\n * `maxDigits`/`fractionDigits`-derived reserve, so an explicit reserver can\n * never reserve *less* than the formatted value needs. Under tabular-nums the\n * rendered width is proportional to character count, so \"wider\" compares length.\n */\n private widerReserver(explicit: string | undefined, derived: string): string {\n if (!explicit) {\n return derived;\n }\n if (!derived) {\n return explicit;\n }\n return explicit.length >= derived.length ? explicit : derived;\n }\n\n private dataQualityClasses(): Record<string, boolean> {\n return {\n 'data-low-integrity':\n this.dataQuality === ReadoutBlockDataQuality.lowIntegrity,\n 'data-invalid': this.dataQuality === ReadoutBlockDataQuality.invalid,\n };\n }\n\n private onIconSlotChange = (event: Event): void => {\n // `slotchange` fires after the first render once content is (re)assigned,\n // so it covers the initial state without a firstUpdated re-render.\n this.hasAssignedIcon =\n (event.target as HTMLSlotElement).assignedElements({flatten: true})\n .length > 0;\n };\n\n private renderIcon(): TemplateResult | typeof nothing {\n // Value blocks only show an icon when asked; setpoint/advice always reserve\n // their marker. The role default is rendered as a direct child (so it sizes\n // via `.block-icon obi-*`) and hidden once an icon is assigned to the slot —\n // `{flatten: true}` sees through a forwarded-but-empty parent slot, so the\n // default still shows when the consumer overrides nothing.\n const showIcon = this.variant !== ReadoutBlockVariant.value || this.hasIcon;\n if (!showIcon) {\n return nothing;\n }\n let fallback: TemplateResult | typeof nothing = nothing;\n if (this.variant === ReadoutBlockVariant.setpoint) {\n fallback = html`<obi-input-right></obi-input-right>`;\n } else if (this.variant === ReadoutBlockVariant.advice) {\n fallback = html`<obi-notification-advice></obi-notification-advice>`;\n }\n return html`<span class=\"block-icon\" part=\"block-icon\" aria-hidden=\"true\">\n <slot name=\"icon\" @slotchange=${this.onIconSlotChange}></slot>\n ${this.hasAssignedIcon ? nothing : fallback}\n </span>`;\n }\n\n /**\n * A cap-height `°` column whose width scales with the number size. Inherits the\n * block's colour.\n */\n private renderDegreeGlyph(size: ObcTextboxSize): TemplateResult {\n return html`\n <span\n class=${classMap({\n 'degree-column': true,\n [`degree-${size}`]: true,\n 'degree-inherit': true,\n })}\n part=\"degree\"\n >\n <obc-textbox class=\"degree-glyph\" .size=${size} alignment=\"center\"\n >°</obc-textbox\n >\n </span>\n `;\n }\n\n protected override willUpdate(changed: Map<string, unknown>): void {\n super.willUpdate(changed);\n // Validated on EVERY update, deliberately NOT gated on `value`/`valueType`\n // appearing in `changed`. When this assertion throws, Lit's `performUpdate`\n // catch calls `__markUpdated()`, which clears the changed-properties map. A\n // later update driven by any OTHER property — inside `obc-readout-list`,\n // `align()` writing the shared reservers — would then see no `value` in\n // `changed`, skip the check, and render the invalid value as a plain dash:\n // exactly the silent failure this assertion exists to prevent.\n assertReadoutValueType('obc-readout-block', this.value, this.valueType);\n }\n\n override render() {\n const valueSize = this.resolvedValueSize;\n const formatOptions = this.numericFormatOptions;\n const isTextMode = this.valueType === ReadoutValueType.text;\n const valueForFormat = resolveReadoutNumericValue(\n this.value,\n this.valueType\n );\n const textValue = resolveReadoutTextValue(this.value, this.valueType);\n // Text mode renders verbatim and ignores the numeric format options; a\n // blank / missing text value still falls back to the unavailable dash.\n const text = this.off\n ? this.offText\n : isTextMode\n ? (textValue ?? READOUT_UNAVAILABLE_DASH)\n : formatNumericValue(valueForFormat, formatOptions);\n // Hinted zeros pad the INTEGER part up to `maxDigits`, independent of\n // `fractionDigits` (the decimal point and fraction digits never count toward\n // `maxDigits`). Negative / dashed values are not padded. Example: value 1.2,\n // maxDigits 3, fractionDigits 1 → \"001.2\".\n const hintCount =\n this.off ||\n isTextMode ||\n !this.hintedZeros ||\n valueForFormat === undefined ||\n valueForFormat < 0\n ? 0\n : Math.max(this.maxDigits - readoutFormattedInteger(text), 0);\n const hinted = hintCount > 0 ? '0'.repeat(hintCount) : '';\n // Hinted zeros own the width — they already fill to `maxDigits` — so when\n // `hintedZeros` is enabled an explicit `spaceReserver` is ignored (it has\n // higher priority). Otherwise the wider of the explicit reserver and the\n // `maxDigits`-derived reserve wins.\n // Text mode ignores the `maxDigits`-derived numeric reserve — only an\n // explicit `spaceReserver` still applies.\n const reserver = isTextMode\n ? (this.spaceReserver ?? '')\n : this.hintedZeros\n ? this.reserverText\n : this.widerReserver(this.spaceReserver, this.reserverText);\n\n const block = html`\n <div\n class=${classMap({\n block: true,\n [`block-${this.variant}`]: true,\n [`size-${this.size}`]: true,\n 'tone-enhanced': this.enhanced,\n touching: this.touching,\n 'is-hiding': this.hidePhase === ReadoutBlockHidePhase.hiding,\n 'is-hidden': this.hidePhase === ReadoutBlockHidePhase.hidden,\n ...this.dataQualityClasses(),\n })}\n part=\"block block-${this.variant}\"\n >\n ${this.renderIcon()}\n <span class=\"block-content\" part=\"block-content\">\n <obc-textbox\n class=\"block-text\"\n part=\"block-text\"\n .size=${valueSize}\n .fontWeight=${this.weight}\n .alignment=${this.alignment}\n .tabularNums=${true}\n >\n ${hinted\n ? html`<span class=\"hinted-zero\" aria-hidden=\"true\"\n >${hinted}</span\n >`\n : nothing}${text}\n ${reserver ? html`<span slot=\"length\">${reserver}</span>` : nothing}\n </obc-textbox>\n ${this.hasDegree ? this.renderDegreeGlyph(valueSize) : nothing}\n </span>\n </div>\n `;\n return wrapWithAlertFrame(this.alert ?? false, block);\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-readout-block': ObcReadoutBlock;\n }\n}\n"],"names":["ReadoutBlockVariant","ReadoutBlockSize","ReadoutBlockDataQuality","ReadoutBlockHidePhase"],"mappings":"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"}
|
|
@@ -42,7 +42,7 @@ export declare enum ObcTextInputFieldPlacement {
|
|
|
42
42
|
* @slot label-icon - Icon displayed before the label text (when `hasLabelIcon` is true)
|
|
43
43
|
* @slot helper-icon - Icon displayed before helper or error text (when `hasHelperIcon` is true)
|
|
44
44
|
* @fires input - Standard input event on value change
|
|
45
|
-
* @fires change -
|
|
45
|
+
* @fires change - {CustomEvent<{value: string}>} Dispatched on value change, carrying the committed value
|
|
46
46
|
* @fires clear - Fired when the clear button is clicked
|
|
47
47
|
* @fires blur - Fired when the input field is blurred
|
|
48
48
|
* @stable
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-input-field.d.ts","sourceRoot":"","sources":["../../../src/components/text-input-field/text-input-field.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EAIV,cAAc,EACd,cAAc,EACf,MAAM,KAAK,CAAC;AAMb,OAAO,+BAA+B,CAAC;AACvC,OAAO,kCAAkC,CAAC;AAC1C,OAAO,0CAA0C,CAAC;AAClD,OAAO,2CAA2C,CAAC;AAEnD,MAAM,MAAM,0BAA0B,GAAG,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CAAC,CAAC;AAEtE;;;GAGG;AACH,oBAAY,sBAAsB;IAChC,IAAI,SAAS;IACb,QAAQ,aAAa;IACrB,KAAK,UAAU;IACf,GAAG,QAAQ;IACX,GAAG,QAAQ;IACX,MAAM,WAAW;IACjB,IAAI,SAAS;IACb,IAAI,SAAS;CACd;AAED,oBAAY,0BAA0B;IACpC,IAAI,SAAS;IACb,MAAM,WAAW;CAClB;AAED,oBAAY,qBAAqB;IAC/B,OAAO,YAAY;IACnB,KAAK,UAAU;CAChB;AAED,oBAAY,0BAA0B;IACpC,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,KAAK,UAAU;CAChB;AAED;;;;;;;;;;;;;GAaG;AACH,qBACa,iBAAkB,SAAQ,UAAU;IACrB,KAAK,SAAM;IACX,WAAW,SAAM;IACjB,IAAI,EAAE,sBAAsB,CACxB;IACJ,SAAS,EAAE,0BAA0B,CAC7B;IAEQ,QAAQ,UAAS;IACjB,QAAQ,UAAS;IACjB,KAAK,UAAS;IACxD,iCAAiC;IACP,SAAS,SAAM;IACzC,kEAAkE;IACvC,oBAAoB,UAAS;IACxD,+EAA+E;IACpD,aAAa,UAAS;IAEjD;;OAEG;IACwB,sBAAsB,UAAS;IAE1D,0CAA0C;IAChB,IAAI,SAAM;IAEpC,2CAA2C;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IAE7C,4CAA4C;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,IAAI,EAAE,qBAAqB,CACrB;IAEL,cAAc,UAAS;IAElD,sDAAsD;IAC3B,cAAc,UAAS;IAExB,UAAU,SAAM;IAEhB,KAAK,SAAM;IACV,QAAQ,UAAS;IAC5C,+BAA+B;IACJ,YAAY,UAAS;IAChD,+BAA+B;IACL,cAAc,EAAE,0BAA0B,CAClC;IAEP,aAAa,UAAS;IACvB,eAAe,EAAE,0BAA0B,CACnC;IAElC,oDAAoD;IAC3C,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,aAAa,CAAM;IAC3B,OAAO,CAAC,yBAAyB,CAAM;IAEzB,OAAO,CAAC,YAAY,CAAC,CAAmB;IAE/D,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,WAAW;IAmBnB,OAAO,CAAC,wBAAwB;IAMhC,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,gBAAgB;IAmBxB,OAAO,CAAC,eAAe;
|
|
1
|
+
{"version":3,"file":"text-input-field.d.ts","sourceRoot":"","sources":["../../../src/components/text-input-field/text-input-field.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EAIV,cAAc,EACd,cAAc,EACf,MAAM,KAAK,CAAC;AAMb,OAAO,+BAA+B,CAAC;AACvC,OAAO,kCAAkC,CAAC;AAC1C,OAAO,0CAA0C,CAAC;AAClD,OAAO,2CAA2C,CAAC;AAEnD,MAAM,MAAM,0BAA0B,GAAG,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CAAC,CAAC;AAEtE;;;GAGG;AACH,oBAAY,sBAAsB;IAChC,IAAI,SAAS;IACb,QAAQ,aAAa;IACrB,KAAK,UAAU;IACf,GAAG,QAAQ;IACX,GAAG,QAAQ;IACX,MAAM,WAAW;IACjB,IAAI,SAAS;IACb,IAAI,SAAS;CACd;AAED,oBAAY,0BAA0B;IACpC,IAAI,SAAS;IACb,MAAM,WAAW;CAClB;AAED,oBAAY,qBAAqB;IAC/B,OAAO,YAAY;IACnB,KAAK,UAAU;CAChB;AAED,oBAAY,0BAA0B;IACpC,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,KAAK,UAAU;CAChB;AAED;;;;;;;;;;;;;GAaG;AACH,qBACa,iBAAkB,SAAQ,UAAU;IACrB,KAAK,SAAM;IACX,WAAW,SAAM;IACjB,IAAI,EAAE,sBAAsB,CACxB;IACJ,SAAS,EAAE,0BAA0B,CAC7B;IAEQ,QAAQ,UAAS;IACjB,QAAQ,UAAS;IACjB,KAAK,UAAS;IACxD,iCAAiC;IACP,SAAS,SAAM;IACzC,kEAAkE;IACvC,oBAAoB,UAAS;IACxD,+EAA+E;IACpD,aAAa,UAAS;IAEjD;;OAEG;IACwB,sBAAsB,UAAS;IAE1D,0CAA0C;IAChB,IAAI,SAAM;IAEpC,2CAA2C;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IAE7C,4CAA4C;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,IAAI,EAAE,qBAAqB,CACrB;IAEL,cAAc,UAAS;IAElD,sDAAsD;IAC3B,cAAc,UAAS;IAExB,UAAU,SAAM;IAEhB,KAAK,SAAM;IACV,QAAQ,UAAS;IAC5C,+BAA+B;IACJ,YAAY,UAAS;IAChD,+BAA+B;IACL,cAAc,EAAE,0BAA0B,CAClC;IAEP,aAAa,UAAS;IACvB,eAAe,EAAE,0BAA0B,CACnC;IAElC,oDAAoD;IAC3C,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,aAAa,CAAM;IAC3B,OAAO,CAAC,yBAAyB,CAAM;IAEzB,OAAO,CAAC,YAAY,CAAC,CAAmB;IAE/D,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,WAAW;IAmBnB,OAAO,CAAC,wBAAwB;IAMhC,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,gBAAgB;IAmBxB,OAAO,CAAC,eAAe;IAOvB,OAAO,KAAK,iBAAiB,GAO5B;IAED,OAAO,KAAK,OAAO,GAMlB;IAEQ,UAAU,CAAC,iBAAiB,EAAE,cAAc;IAU5C,OAAO;IAUP,MAAM;IAwHf,OAAgB,MAAM,0BAA6B;CACpD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,sBAAsB,EAAE,iBAAiB,CAAC;KAC3C;CACF"}
|
|
@@ -129,8 +129,11 @@ let ObcTextInputField = class extends LitElement {
|
|
|
129
129
|
${text}
|
|
130
130
|
</div>`;
|
|
131
131
|
}
|
|
132
|
-
fireChangeEvent() {
|
|
133
|
-
|
|
132
|
+
fireChangeEvent(e) {
|
|
133
|
+
const target = e.target;
|
|
134
|
+
this.dispatchEvent(
|
|
135
|
+
new CustomEvent("change", { detail: { value: target.value } })
|
|
136
|
+
);
|
|
134
137
|
}
|
|
135
138
|
get shouldUpdateValue() {
|
|
136
139
|
if (this.rejectUpdates) return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-input-field.js","sources":["../../../src/components/text-input-field/text-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 './text-input-field.css?inline';\nimport {classMap} from 'lit/directives/class-map.js';\nimport {customElement} from '../../decorator.js';\nimport '../icon-button/icon-button.js';\nimport '../../icons/icon-close-google.js';\nimport '../../icons/icon-visibility-on-google.js';\nimport '../../icons/icon-visibility-off-google.js';\n\nexport type ObcTextInputFieldBlurEvent = CustomEvent<{value: string}>;\n\n/**\n * Common HTML input types for practical use with `<obc-text-input-field>`.\n * Focuses on the most commonly used input types in real applications.\n */\nexport enum HTMLInputTypeAttribute {\n Text = 'text',\n Password = 'password',\n Email = 'email',\n Tel = 'tel',\n Url = 'url',\n Search = 'search',\n Date = 'date',\n Time = 'time',\n}\n\nexport enum ObcTextInputFieldTextAlign {\n Left = 'left',\n Center = 'center',\n}\n\nexport enum ObcTextInputFieldSize {\n Regular = 'regular',\n Large = 'large',\n}\n\nexport enum ObcTextInputFieldPlacement {\n Left = 'left',\n Center = 'center',\n Right = 'right',\n}\n\n/**\n * `<obc-text-input-field>` – A text input field component with optional icons, label, and helper text.\n *\n *\n *\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 input - Standard input event on value change\n * @fires change - Standard change event on value change\n * @fires clear - Fired when the clear button is clicked\n * @fires blur - Fired when the input field is blurred\n * @stable\n */\n@customElement('obc-text-input-field')\nexport class ObcTextInputField extends LitElement {\n @property({type: String}) value = '';\n @property({type: String}) placeholder = '';\n @property({type: String}) type: HTMLInputTypeAttribute =\n HTMLInputTypeAttribute.Text;\n @property({type: String}) textAlign: ObcTextInputFieldTextAlign =\n ObcTextInputFieldTextAlign.Left;\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 /** @availableWhen error==true */\n @property({type: String}) errorText = '';\n /** If true, the input field will not update its value on focus */\n @property({type: Boolean}) rejectUpdatesOnFocus = false;\n /** If true, the value will only be initially set, and not updated on change */\n @property({type: Boolean}) rejectUpdates = false;\n\n /** 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 */\n @property({type: Boolean}) rejectDuplicateUpdates = false;\n\n /** Name attribute for form integration */\n @property({type: String}) name = '';\n\n /** Maximum number of characters allowed */\n @property({type: Number}) maxlength?: number;\n\n /** Minimum number of characters required */\n @property({type: Number}) minlength?: number;\n\n @property({type: String}) size: ObcTextInputFieldSize =\n ObcTextInputFieldSize.Regular;\n\n @property({type: Boolean}) hasLeadingIcon = false;\n\n /** Shows a clear button when the input has a value */\n @property({type: Boolean}) hasClearButton = false;\n\n @property({type: String}) helperText = '';\n\n @property({type: String}) label = '';\n @property({type: Boolean}) required = false;\n /** @availableWhen label!='' */\n @property({type: Boolean}) hasLabelIcon = false;\n /** @availableWhen label!='' */\n @property({type: String}) labelPlacement: ObcTextInputFieldPlacement =\n ObcTextInputFieldPlacement.Left;\n\n @property({type: Boolean}) hasHelperIcon = false;\n @property({type: String}) helperPlacement: ObcTextInputFieldPlacement =\n ObcTextInputFieldPlacement.Left;\n\n /** Internal state for password visibility toggle */\n @state() private passwordVisible = false;\n @state() private hasFocus = false;\n @state() private previousValue = '';\n @state() private previousInputElementValue = '';\n\n @query('.value-input') private inputElement?: HTMLInputElement;\n\n private onInput(e: Event) {\n this.value = (e.target as HTMLInputElement).value;\n this.previousInputElementValue = this.value;\n }\n\n private onFocus() {\n this.hasFocus = true;\n }\n\n private onBlur() {\n this.hasFocus = false;\n }\n\n private handleClear(e: Event) {\n // Prevent label click from triggering unwanted focus behavior\n e.stopPropagation();\n\n this.value = '';\n this.inputElement!.value = '';\n this.dispatchEvent(\n new CustomEvent('clear', {bubbles: true, composed: true})\n );\n // Dispatch input and change events for consistency with native behavior\n this.dispatchEvent(\n new InputEvent('input', {bubbles: true, composed: true})\n );\n this.dispatchEvent(new Event('change', {bubbles: true, composed: true}));\n\n // Return focus to the input field\n this.inputElement?.focus();\n }\n\n private togglePasswordVisibility(e: Event) {\n // Prevent label click from triggering unwanted focus behavior\n e.stopPropagation();\n this.passwordVisible = !this.passwordVisible;\n }\n\n private getInputMode(): string {\n switch (this.type) {\n case HTMLInputTypeAttribute.Tel:\n return 'tel';\n case HTMLInputTypeAttribute.Email:\n return 'email';\n case HTMLInputTypeAttribute.Url:\n return 'url';\n case HTMLInputTypeAttribute.Search:\n return 'search';\n default:\n return 'text';\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 ${this.hasHelperIcon\n ? html`<div class=\"helper-icon\"><slot name=\"helper-icon\"></slot></div>`\n : nothing}\n ${text}\n </div>`;\n }\n\n private fireChangeEvent() {\n this.dispatchEvent(new CustomEvent('change'));\n }\n\n private get shouldUpdateValue(): boolean {\n if (this.rejectUpdates) return false;\n if (this.rejectUpdatesOnFocus && this.hasFocus) return false;\n if (this.rejectDuplicateUpdates && this.value === this.previousValue) {\n return false;\n }\n return true;\n }\n\n private get isEmpty(): boolean {\n const currentValue =\n !this.shouldUpdateValue && this.inputElement\n ? this.inputElement.value\n : this.value;\n return currentValue.trim().length === 0;\n }\n\n override willUpdate(changedProperties: PropertyValues) {\n if (\n changedProperties.has('value') &&\n !this.shouldUpdateValue &&\n this.inputElement\n ) {\n this.value = this.inputElement.value;\n }\n }\n\n override updated() {\n if (\n this.rejectDuplicateUpdates &&\n this.value !== this.previousValue &&\n (this.previousInputElementValue !== this.value || !this.hasFocus)\n ) {\n this.previousValue = this.value;\n }\n }\n\n override render() {\n const hasHelperOrError =\n Boolean(this.helperText) || Boolean(this.error && this.errorText);\n const showClearButton =\n this.hasClearButton && this.value.length > 0 && !this.disabled;\n const isPasswordField = this.type === HTMLInputTypeAttribute.Password;\n const showPasswordToggle = isPasswordField && !this.disabled;\n const isClearButtonVisible = showClearButton && !showPasswordToggle;\n const effectiveType =\n isPasswordField && this.passwordVisible\n ? HTMLInputTypeAttribute.Text\n : this.type;\n\n // Determine trailing button state for padding adjustment\n const hasTrailingButton = showPasswordToggle || isClearButtonVisible;\n\n let value = this.value;\n\n if (!this.shouldUpdateValue && this.inputElement) {\n value = this.inputElement.value;\n }\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 empty: this.isEmpty,\n helpertext: hasHelperOrError,\n haslabel: Boolean(this.label),\n 'has-trailing-button': hasTrailingButton,\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 ${this.hasLabelIcon\n ? html`<div class=\"label-icon\">\n <slot name=\"label-icon\"></slot>\n </div>`\n : nothing}\n <span class=\"label-text\">${this.label}</span>\n ${this.required\n ? html`<div class=\"required-indicator\"></div>`\n : nothing}\n </div>`\n : nothing}\n\n <div class=\"horizontal-container\">\n <div class=\"input-field-container\">\n ${this.hasLeadingIcon\n ? html`<div class=\"leading-icon\">\n <slot name=\"leading-icon\"></slot>\n </div>`\n : nothing}\n <div class=\"label-container\">\n <input\n type=${effectiveType}\n inputmode=${this.getInputMode()}\n class=\"value-input\"\n .value=${value}\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 @input=${this.onInput}\n @change=${this.fireChangeEvent}\n />\n </div>\n ${showPasswordToggle\n ? html`<obc-icon-button\n variant=\"flat\"\n class=\"trailing-icon-button\"\n @click=${this.togglePasswordVisibility}\n aria-label=${this.passwordVisible\n ? 'Hide password'\n : 'Show password'}\n >\n ${this.passwordVisible\n ? html`<obi-visibility-on-google></obi-visibility-on-google>`\n : html`<obi-visibility-off-google></obi-visibility-off-google>`}\n </obc-icon-button>`\n : nothing}\n ${isClearButtonVisible\n ? html`<obc-icon-button\n variant=\"flat\"\n class=\"trailing-icon-button\"\n @click=${this.handleClear}\n aria-label=\"Clear input\"\n >\n <obi-close-google></obi-close-google>\n </obc-icon-button>`\n : nothing}\n </div>\n </div>\n\n ${this.error && this.errorText\n ? this.renderFooterText(this.errorText, true)\n : this.renderFooterText(this.helperText, false)}\n </label>\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-text-input-field': ObcTextInputField;\n }\n}\n"],"names":["HTMLInputTypeAttribute","ObcTextInputFieldTextAlign","ObcTextInputFieldSize","ObcTextInputFieldPlacement"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"text-input-field.js","sources":["../../../src/components/text-input-field/text-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 './text-input-field.css?inline';\nimport {classMap} from 'lit/directives/class-map.js';\nimport {customElement} from '../../decorator.js';\nimport '../icon-button/icon-button.js';\nimport '../../icons/icon-close-google.js';\nimport '../../icons/icon-visibility-on-google.js';\nimport '../../icons/icon-visibility-off-google.js';\n\nexport type ObcTextInputFieldBlurEvent = CustomEvent<{value: string}>;\n\n/**\n * Common HTML input types for practical use with `<obc-text-input-field>`.\n * Focuses on the most commonly used input types in real applications.\n */\nexport enum HTMLInputTypeAttribute {\n Text = 'text',\n Password = 'password',\n Email = 'email',\n Tel = 'tel',\n Url = 'url',\n Search = 'search',\n Date = 'date',\n Time = 'time',\n}\n\nexport enum ObcTextInputFieldTextAlign {\n Left = 'left',\n Center = 'center',\n}\n\nexport enum ObcTextInputFieldSize {\n Regular = 'regular',\n Large = 'large',\n}\n\nexport enum ObcTextInputFieldPlacement {\n Left = 'left',\n Center = 'center',\n Right = 'right',\n}\n\n/**\n * `<obc-text-input-field>` – A text input field component with optional icons, label, and helper text.\n *\n *\n *\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 input - Standard input event on value change\n * @fires change - {CustomEvent<{value: string}>} Dispatched on value change, carrying the committed value\n * @fires clear - Fired when the clear button is clicked\n * @fires blur - Fired when the input field is blurred\n * @stable\n */\n@customElement('obc-text-input-field')\nexport class ObcTextInputField extends LitElement {\n @property({type: String}) value = '';\n @property({type: String}) placeholder = '';\n @property({type: String}) type: HTMLInputTypeAttribute =\n HTMLInputTypeAttribute.Text;\n @property({type: String}) textAlign: ObcTextInputFieldTextAlign =\n ObcTextInputFieldTextAlign.Left;\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 /** @availableWhen error==true */\n @property({type: String}) errorText = '';\n /** If true, the input field will not update its value on focus */\n @property({type: Boolean}) rejectUpdatesOnFocus = false;\n /** If true, the value will only be initially set, and not updated on change */\n @property({type: Boolean}) rejectUpdates = false;\n\n /** 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 */\n @property({type: Boolean}) rejectDuplicateUpdates = false;\n\n /** Name attribute for form integration */\n @property({type: String}) name = '';\n\n /** Maximum number of characters allowed */\n @property({type: Number}) maxlength?: number;\n\n /** Minimum number of characters required */\n @property({type: Number}) minlength?: number;\n\n @property({type: String}) size: ObcTextInputFieldSize =\n ObcTextInputFieldSize.Regular;\n\n @property({type: Boolean}) hasLeadingIcon = false;\n\n /** Shows a clear button when the input has a value */\n @property({type: Boolean}) hasClearButton = false;\n\n @property({type: String}) helperText = '';\n\n @property({type: String}) label = '';\n @property({type: Boolean}) required = false;\n /** @availableWhen label!='' */\n @property({type: Boolean}) hasLabelIcon = false;\n /** @availableWhen label!='' */\n @property({type: String}) labelPlacement: ObcTextInputFieldPlacement =\n ObcTextInputFieldPlacement.Left;\n\n @property({type: Boolean}) hasHelperIcon = false;\n @property({type: String}) helperPlacement: ObcTextInputFieldPlacement =\n ObcTextInputFieldPlacement.Left;\n\n /** Internal state for password visibility toggle */\n @state() private passwordVisible = false;\n @state() private hasFocus = false;\n @state() private previousValue = '';\n @state() private previousInputElementValue = '';\n\n @query('.value-input') private inputElement?: HTMLInputElement;\n\n private onInput(e: Event) {\n this.value = (e.target as HTMLInputElement).value;\n this.previousInputElementValue = this.value;\n }\n\n private onFocus() {\n this.hasFocus = true;\n }\n\n private onBlur() {\n this.hasFocus = false;\n }\n\n private handleClear(e: Event) {\n // Prevent label click from triggering unwanted focus behavior\n e.stopPropagation();\n\n this.value = '';\n this.inputElement!.value = '';\n this.dispatchEvent(\n new CustomEvent('clear', {bubbles: true, composed: true})\n );\n // Dispatch input and change events for consistency with native behavior\n this.dispatchEvent(\n new InputEvent('input', {bubbles: true, composed: true})\n );\n this.dispatchEvent(new Event('change', {bubbles: true, composed: true}));\n\n // Return focus to the input field\n this.inputElement?.focus();\n }\n\n private togglePasswordVisibility(e: Event) {\n // Prevent label click from triggering unwanted focus behavior\n e.stopPropagation();\n this.passwordVisible = !this.passwordVisible;\n }\n\n private getInputMode(): string {\n switch (this.type) {\n case HTMLInputTypeAttribute.Tel:\n return 'tel';\n case HTMLInputTypeAttribute.Email:\n return 'email';\n case HTMLInputTypeAttribute.Url:\n return 'url';\n case HTMLInputTypeAttribute.Search:\n return 'search';\n default:\n return 'text';\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 ${this.hasHelperIcon\n ? html`<div class=\"helper-icon\"><slot name=\"helper-icon\"></slot></div>`\n : nothing}\n ${text}\n </div>`;\n }\n\n private fireChangeEvent(e: Event) {\n const target = e.target as HTMLInputElement;\n this.dispatchEvent(\n new CustomEvent('change', {detail: {value: target.value}})\n );\n }\n\n private get shouldUpdateValue(): boolean {\n if (this.rejectUpdates) return false;\n if (this.rejectUpdatesOnFocus && this.hasFocus) return false;\n if (this.rejectDuplicateUpdates && this.value === this.previousValue) {\n return false;\n }\n return true;\n }\n\n private get isEmpty(): boolean {\n const currentValue =\n !this.shouldUpdateValue && this.inputElement\n ? this.inputElement.value\n : this.value;\n return currentValue.trim().length === 0;\n }\n\n override willUpdate(changedProperties: PropertyValues) {\n if (\n changedProperties.has('value') &&\n !this.shouldUpdateValue &&\n this.inputElement\n ) {\n this.value = this.inputElement.value;\n }\n }\n\n override updated() {\n if (\n this.rejectDuplicateUpdates &&\n this.value !== this.previousValue &&\n (this.previousInputElementValue !== this.value || !this.hasFocus)\n ) {\n this.previousValue = this.value;\n }\n }\n\n override render() {\n const hasHelperOrError =\n Boolean(this.helperText) || Boolean(this.error && this.errorText);\n const showClearButton =\n this.hasClearButton && this.value.length > 0 && !this.disabled;\n const isPasswordField = this.type === HTMLInputTypeAttribute.Password;\n const showPasswordToggle = isPasswordField && !this.disabled;\n const isClearButtonVisible = showClearButton && !showPasswordToggle;\n const effectiveType =\n isPasswordField && this.passwordVisible\n ? HTMLInputTypeAttribute.Text\n : this.type;\n\n // Determine trailing button state for padding adjustment\n const hasTrailingButton = showPasswordToggle || isClearButtonVisible;\n\n let value = this.value;\n\n if (!this.shouldUpdateValue && this.inputElement) {\n value = this.inputElement.value;\n }\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 empty: this.isEmpty,\n helpertext: hasHelperOrError,\n haslabel: Boolean(this.label),\n 'has-trailing-button': hasTrailingButton,\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 ${this.hasLabelIcon\n ? html`<div class=\"label-icon\">\n <slot name=\"label-icon\"></slot>\n </div>`\n : nothing}\n <span class=\"label-text\">${this.label}</span>\n ${this.required\n ? html`<div class=\"required-indicator\"></div>`\n : nothing}\n </div>`\n : nothing}\n\n <div class=\"horizontal-container\">\n <div class=\"input-field-container\">\n ${this.hasLeadingIcon\n ? html`<div class=\"leading-icon\">\n <slot name=\"leading-icon\"></slot>\n </div>`\n : nothing}\n <div class=\"label-container\">\n <input\n type=${effectiveType}\n inputmode=${this.getInputMode()}\n class=\"value-input\"\n .value=${value}\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 @input=${this.onInput}\n @change=${this.fireChangeEvent}\n />\n </div>\n ${showPasswordToggle\n ? html`<obc-icon-button\n variant=\"flat\"\n class=\"trailing-icon-button\"\n @click=${this.togglePasswordVisibility}\n aria-label=${this.passwordVisible\n ? 'Hide password'\n : 'Show password'}\n >\n ${this.passwordVisible\n ? html`<obi-visibility-on-google></obi-visibility-on-google>`\n : html`<obi-visibility-off-google></obi-visibility-off-google>`}\n </obc-icon-button>`\n : nothing}\n ${isClearButtonVisible\n ? html`<obc-icon-button\n variant=\"flat\"\n class=\"trailing-icon-button\"\n @click=${this.handleClear}\n aria-label=\"Clear input\"\n >\n <obi-close-google></obi-close-google>\n </obc-icon-button>`\n : nothing}\n </div>\n </div>\n\n ${this.error && this.errorText\n ? this.renderFooterText(this.errorText, true)\n : this.renderFooterText(this.helperText, false)}\n </label>\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-text-input-field': ObcTextInputField;\n }\n}\n"],"names":["HTMLInputTypeAttribute","ObcTextInputFieldTextAlign","ObcTextInputFieldSize","ObcTextInputFieldPlacement"],"mappings":"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"}
|
|
@@ -3,6 +3,9 @@ import '../icon-button/icon-button.js';
|
|
|
3
3
|
export type ObcToggleSwitchInputEvent = CustomEvent<{
|
|
4
4
|
checked: boolean;
|
|
5
5
|
}>;
|
|
6
|
+
export type ObcToggleSwitchChangeEvent = CustomEvent<{
|
|
7
|
+
checked: boolean;
|
|
8
|
+
}>;
|
|
6
9
|
/**
|
|
7
10
|
* `<obc-toggle-switch>` – A toggle switch component for binary on/off selection (also known as a switch, toggle, or enable/disable control).
|
|
8
11
|
*
|
|
@@ -50,6 +53,12 @@ export type ObcToggleSwitchInputEvent = CustomEvent<{
|
|
|
50
53
|
*
|
|
51
54
|
* ### Events
|
|
52
55
|
* - `input` – Fired when the toggle state changes (checked/unchecked).
|
|
56
|
+
* - `change` – Fired when the toggle state changes by user interaction.
|
|
57
|
+
*
|
|
58
|
+
* Both events report the state the user selected. When `externalControl` is
|
|
59
|
+
* true the component does not update itself; the consumer decides whether to
|
|
60
|
+
* apply the reported state to `checked` and may reject the interaction by
|
|
61
|
+
* leaving `checked` unchanged.
|
|
53
62
|
*
|
|
54
63
|
* ---
|
|
55
64
|
*
|
|
@@ -79,7 +88,7 @@ export type ObcToggleSwitchInputEvent = CustomEvent<{
|
|
|
79
88
|
*
|
|
80
89
|
* @slot icon - Leading icon slot (shown when `hasIcon` is true)
|
|
81
90
|
* @fires input - {ObcToggleSwitchInputEvent} Dispatched when the value of the input changes
|
|
82
|
-
* @fires change - Dispatched when the value of the input changes by user interaction
|
|
91
|
+
* @fires change - {ObcToggleSwitchChangeEvent} Dispatched when the value of the input changes by user interaction
|
|
83
92
|
* @stable
|
|
84
93
|
*/
|
|
85
94
|
export declare class ObcToggleSwitch extends LitElement {
|
|
@@ -121,6 +130,12 @@ export declare class ObcToggleSwitch extends LitElement {
|
|
|
121
130
|
* Use to control the toggle state from outside the component.
|
|
122
131
|
*/
|
|
123
132
|
externalControl: boolean;
|
|
133
|
+
/**
|
|
134
|
+
* The state the user selected in the most recent interaction. In
|
|
135
|
+
* externalControl mode this can differ from `checked` until the consumer
|
|
136
|
+
* accepts the change, so the change event reports it instead of `checked`.
|
|
137
|
+
*/
|
|
138
|
+
private _userSelectedChecked?;
|
|
124
139
|
/**
|
|
125
140
|
* Handles input events to change the toggle state.
|
|
126
141
|
* Prevents changes if the toggle is disabled.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toggle-switch.d.ts","sourceRoot":"","sources":["../../../src/components/toggle-switch/toggle-switch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAA2B,MAAM,KAAK,CAAC;AAGzD,OAAO,+BAA+B,CAAC;AAIvC,MAAM,MAAM,yBAAyB,GAAG,WAAW,CAAC;IAClD,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC,CAAC;AAEH
|
|
1
|
+
{"version":3,"file":"toggle-switch.d.ts","sourceRoot":"","sources":["../../../src/components/toggle-switch/toggle-switch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAA2B,MAAM,KAAK,CAAC;AAGzD,OAAO,+BAA+B,CAAC;AAIvC,MAAM,MAAM,yBAAyB,GAAG,WAAW,CAAC;IAClD,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC,CAAC;AAEH,MAAM,MAAM,0BAA0B,GAAG,WAAW,CAAC;IACnD,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoFG;AACH,qBACa,eAAgB,SAAQ,UAAU;IAC7C;;OAEG;IACuB,KAAK,SAAW;IAE1C;;;OAGG;IACwB,OAAO,UAAS;IAE3C;;OAEG;IACwB,QAAQ,UAAS;IAE5C;;OAEG;IACwB,cAAc,UAAS;IAElD;;;;OAIG;IACuB,WAAW,SAAM;IAE3C;;;OAGG;IACwB,gBAAgB,UAAS;IAEpD;;;OAGG;IACwB,OAAO,UAAS;IAE3C;;;OAGG;IACwB,eAAe,UAAS;IAEnD;;;;OAIG;IACH,OAAO,CAAC,oBAAoB,CAAC,CAAU;IAEvC;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IAuBlB,OAAO,CAAC,gBAAgB;IAYf,MAAM;IAuCf,OAAgB,MAAM,0BAA6B;CACpD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,mBAAmB,EAAE,eAAe,CAAC;KACtC;CACF"}
|
|
@@ -38,6 +38,7 @@ let ObcToggleSwitch = class extends LitElement {
|
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
40
|
const nextChecked = !this.checked;
|
|
41
|
+
this._userSelectedChecked = nextChecked;
|
|
41
42
|
if (!this.externalControl) {
|
|
42
43
|
this.checked = nextChecked;
|
|
43
44
|
}
|
|
@@ -56,7 +57,11 @@ let ObcToggleSwitch = class extends LitElement {
|
|
|
56
57
|
e.preventDefault();
|
|
57
58
|
return;
|
|
58
59
|
}
|
|
59
|
-
this.dispatchEvent(
|
|
60
|
+
this.dispatchEvent(
|
|
61
|
+
new CustomEvent("change", {
|
|
62
|
+
detail: { checked: this._userSelectedChecked ?? this.checked }
|
|
63
|
+
})
|
|
64
|
+
);
|
|
60
65
|
}
|
|
61
66
|
render() {
|
|
62
67
|
return html`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toggle-switch.js","sources":["../../../src/components/toggle-switch/toggle-switch.ts"],"sourcesContent":["import {LitElement, html, nothing, unsafeCSS} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport {classMap} from 'lit/directives/class-map.js';\nimport '../icon-button/icon-button.js';\nimport componentStyle from './toggle-switch.css?inline';\nimport {customElement} from '../../decorator.js';\n\nexport type ObcToggleSwitchInputEvent = CustomEvent<{\n checked: boolean;\n}>;\n\n/**\n * `<obc-toggle-switch>` – A toggle switch component for binary on/off selection (also known as a switch, toggle, or enable/disable control).\n *\n * Provides a visual switch control for toggling between two states (checked/unchecked), commonly used for enabling or disabling a setting or feature. The component supports an optional label, description, icon, and divider for flexible presentation in lists or forms.\n *\n * ---\n *\n * ### Features\n * - **Binary toggle:** Allows users to switch between checked (on) and unchecked (off) states.\n * - **Label and Description:** Displays a primary label and an optional secondary description for context.\n * - **Icon Support:** Can display a leading icon via the `icon` slot for visual emphasis.\n * - **Disabled State:** Can be set to disabled, preventing user interaction and visually indicating inactivity.\n * - **Bottom Divider:** Optional divider for use in lists or grouped settings.\n * - **Responsive Layout:** Adapts label/description layout based on content; long descriptions are truncated with ellipsis.\n *\n * ---\n *\n * ### Usage Guidelines\n * Use `obc-toggle-switch` for settings or preferences that require a simple on/off or enable/disable control. Ideal for scenarios where the user needs to quickly toggle a feature, such as activating notifications, enabling dark mode, or switching connectivity options. Avoid using for mutually exclusive choices—use radio buttons for those cases.\n *\n * - Place in forms, settings panels, or lists where binary choices are needed.\n * - Use the description property to clarify the effect of the toggle if the label alone is not sufficient.\n * - If an icon is relevant, provide it via the `icon` slot to reinforce the meaning.\n * - For accessibility, ensure the label clearly describes the toggle's function.\n *\n * ---\n *\n * ### Slots\n * | Slot Name | Renders When... | Purpose |\n * |-----------|---------------------|-------------------------------------------|\n * | icon | `hasIcon` is true | Leading icon to visually represent toggle |\n *\n * ---\n *\n * ### Properties and Attributes\n * - `label` (string): Main label for the toggle (required for clarity).\n * - `checked` (boolean): Whether the toggle is in the \"on\" state. Defaults to `false`.\n * - `disabled` (boolean): Disables interaction and applies a disabled style.\n * - `hasDescription` (boolean): If true, shows the description text below the label.\n * - `description` (string): Supplementary text shown when `hasDescription` is true.\n * - `hasBottomDivider` (boolean): If true, renders a divider below the toggle (useful in lists).\n * - `hasIcon` (boolean): If true, displays the `icon` slot before the label.\n *\n * ---\n *\n * ### Events\n * - `input` – Fired when the toggle state changes (checked/unchecked).\n *\n * ---\n *\n * ### Best Practices\n * - Use concise labels and keep descriptions brief; long descriptions are truncated.\n * - Only use the divider when presenting multiple toggles in a list for visual separation.\n * - For accessibility, ensure the label is descriptive and unique within the context.\n * - Avoid using toggle switches for actions that require confirmation or have destructive effects.\n * - For mutually exclusive options, use radio buttons instead.\n *\n * ---\n *\n * **Example:**\n * ```html\n * <obc-toggle-switch\n * label=\"Enable notifications\"\n * ?checked=${true}\n * ?hasDescription=${true}\n * description=\"Receive updates and alerts\"\n * ?hasIcon=${true}\n * >\n * <obi-placeholder slot=\"icon\"></obi-placeholder>\n * </obc-toggle-switch>\n * ```\n *\n * In this example, the toggle switch displays a label, an icon, and a description, and is in the checked state.\n *\n * @slot icon - Leading icon slot (shown when `hasIcon` is true)\n * @fires input - {ObcToggleSwitchInputEvent} Dispatched when the value of the input changes\n * @fires change - Dispatched when the value of the input changes by user interaction\n * @stable\n */\n@customElement('obc-toggle-switch')\nexport class ObcToggleSwitch extends LitElement {\n /**\n * Main label for the toggle switch. Should clearly describe the setting being toggled.\n */\n @property({type: String}) label = 'Label';\n\n /**\n * Whether the toggle is in the \"on\" (checked) state.\n * Set to true to display as active/on.\n */\n @property({type: Boolean}) checked = false;\n\n /**\n * Disables the toggle, preventing user interaction and applying a disabled style.\n */\n @property({type: Boolean}) disabled = false;\n\n /**\n * If true, displays the description text below the label.\n */\n @property({type: Boolean}) hasDescription = false;\n\n /**\n * Supplementary description text shown when `hasDescription` is true.\n * Use to clarify the effect or details of the toggle.\n * @availableWhen hasDescription==true\n */\n @property({type: String}) description = '';\n\n /**\n * If true, renders a divider below the toggle switch.\n * Useful for visually separating items in a list.\n */\n @property({type: Boolean}) hasBottomDivider = false;\n\n /**\n * If true, displays a leading icon before the label.\n * Provide icon content via the `icon` slot.\n */\n @property({type: Boolean}) hasIcon = false;\n\n /**\n * If true, the toggle is controlled externally.\n * Use to control the toggle state from outside the component.\n */\n @property({type: Boolean}) externalControl = false;\n\n /**\n * Handles input events to change the toggle state.\n * Prevents changes if the toggle is disabled.\n * @param e {InputEvent}\n * @fires input - Dispatched when the value of the input changes\n */\n private _tryChange(e: InputEvent) {\n if (this.disabled) {\n e.preventDefault();\n return;\n }\n\n const nextChecked = !this.checked;\n if (!this.externalControl) {\n this.checked = nextChecked;\n }\n e.stopPropagation();\n this.dispatchEvent(\n new CustomEvent('input', {\n detail: {checked: nextChecked},\n })\n );\n\n if (this.externalControl) {\n (e.target as HTMLInputElement).checked = this.checked;\n }\n }\n\n private _fireChangeEvent(e: Event) {\n if (this.disabled) {\n e.preventDefault();\n return;\n }\n this.dispatchEvent(new CustomEvent('change'));\n }\n\n override render() {\n return html`\n <label\n class=${classMap({\n checked: this.checked,\n disabled: this.disabled,\n 'has-description': this.hasDescription,\n })}\n >\n <div class=\"icon-label-container\">\n ${this.hasIcon\n ? html`<div class=\"icon-container\"><slot name=\"icon\"></slot></div>`\n : nothing}\n <div class=\"label-container\">\n <span class=\"label\">${this.label}</span>\n ${this.hasDescription\n ? html`<span class=\"description\">${this.description}</span>`\n : nothing}\n </div>\n </div>\n <div class=\"switch\">\n <div class=\"presenter ${classMap({checked: this.checked})}\">\n <div class=\"knob\"></div>\n <input\n type=\"checkbox\"\n .checked=${this.checked}\n ?disabled=${this.disabled}\n @input=${this._tryChange}\n @change=${this._fireChangeEvent}\n />\n </div>\n </div>\n ${this.hasBottomDivider\n ? html`<div class=\"bottom-divider\"></div>`\n : nothing}\n </label>\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-toggle-switch': ObcToggleSwitch;\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;AA2FO,IAAM,kBAAN,cAA8B,WAAW;AAAA,EAAzC,cAAA;AAAA,UAAA,GAAA,SAAA;AAIqB,SAAA,QAAQ;AAMP,SAAA,UAAU;AAKV,SAAA,WAAW;AAKX,SAAA,iBAAiB;AAOlB,SAAA,cAAc;AAMb,SAAA,mBAAmB;AAMnB,SAAA,UAAU;AAMV,SAAA,kBAAkB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQrC,WAAW,GAAe;AAChC,QAAI,KAAK,UAAU;AACjB,QAAE,eAAA;AACF;AAAA,IACF;AAEA,UAAM,cAAc,CAAC,KAAK;AAC1B,QAAI,CAAC,KAAK,iBAAiB;AACzB,WAAK,UAAU;AAAA,IACjB;AACA,MAAE,gBAAA;AACF,SAAK;AAAA,MACH,IAAI,YAAY,SAAS;AAAA,QACvB,QAAQ,EAAC,SAAS,YAAA;AAAA,MAAW,CAC9B;AAAA,IAAA;AAGH,QAAI,KAAK,iBAAiB;AACvB,QAAE,OAA4B,UAAU,KAAK;AAAA,IAChD;AAAA,EACF;AAAA,EAEQ,iBAAiB,GAAU;AACjC,QAAI,KAAK,UAAU;AACjB,QAAE,eAAA;AACF;AAAA,IACF;AACA,SAAK,cAAc,IAAI,YAAY,QAAQ,CAAC;AAAA,EAC9C;AAAA,EAES,SAAS;AAChB,WAAO;AAAA;AAAA,gBAEK,SAAS;AAAA,MACf,SAAS,KAAK;AAAA,MACd,UAAU,KAAK;AAAA,MACf,mBAAmB,KAAK;AAAA,IAAA,CACzB,CAAC;AAAA;AAAA;AAAA,YAGE,KAAK,UACH,oEACA,OAAO;AAAA;AAAA,kCAEa,KAAK,KAAK;AAAA,cAC9B,KAAK,iBACH,iCAAiC,KAAK,WAAW,YACjD,OAAO;AAAA;AAAA;AAAA;AAAA,kCAIW,SAAS,EAAC,SAAS,KAAK,QAAA,CAAQ,CAAC;AAAA;AAAA;AAAA;AAAA,yBAI1C,KAAK,OAAO;AAAA,0BACX,KAAK,QAAQ;AAAA,uBAChB,KAAK,UAAU;AAAA,wBACd,KAAK,gBAAgB;AAAA;AAAA;AAAA;AAAA,UAInC,KAAK,mBACH,2CACA,OAAO;AAAA;AAAA;AAAA,EAGjB;AAGF;AA3Ha,gBA0HK,SAAS,UAAU,cAAc;AAtHvB,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAJb,gBAIe,WAAA,SAAA,CAAA;AAMC,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAVd,gBAUgB,WAAA,WAAA,CAAA;AAKA,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAfd,gBAegB,WAAA,YAAA,CAAA;AAKA,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GApBd,gBAoBgB,WAAA,kBAAA,CAAA;AAOD,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GA3Bb,gBA2Be,WAAA,eAAA,CAAA;AAMC,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAjCd,gBAiCgB,WAAA,oBAAA,CAAA;AAMA,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAvCd,gBAuCgB,WAAA,WAAA,CAAA;AAMA,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GA7Cd,gBA6CgB,WAAA,mBAAA,CAAA;AA7ChB,kBAAN,gBAAA;AAAA,EADN,cAAc,mBAAmB;AAAA,GACrB,eAAA;"}
|
|
1
|
+
{"version":3,"file":"toggle-switch.js","sources":["../../../src/components/toggle-switch/toggle-switch.ts"],"sourcesContent":["import {LitElement, html, nothing, unsafeCSS} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport {classMap} from 'lit/directives/class-map.js';\nimport '../icon-button/icon-button.js';\nimport componentStyle from './toggle-switch.css?inline';\nimport {customElement} from '../../decorator.js';\n\nexport type ObcToggleSwitchInputEvent = CustomEvent<{\n checked: boolean;\n}>;\n\nexport type ObcToggleSwitchChangeEvent = CustomEvent<{\n checked: boolean;\n}>;\n\n/**\n * `<obc-toggle-switch>` – A toggle switch component for binary on/off selection (also known as a switch, toggle, or enable/disable control).\n *\n * Provides a visual switch control for toggling between two states (checked/unchecked), commonly used for enabling or disabling a setting or feature. The component supports an optional label, description, icon, and divider for flexible presentation in lists or forms.\n *\n * ---\n *\n * ### Features\n * - **Binary toggle:** Allows users to switch between checked (on) and unchecked (off) states.\n * - **Label and Description:** Displays a primary label and an optional secondary description for context.\n * - **Icon Support:** Can display a leading icon via the `icon` slot for visual emphasis.\n * - **Disabled State:** Can be set to disabled, preventing user interaction and visually indicating inactivity.\n * - **Bottom Divider:** Optional divider for use in lists or grouped settings.\n * - **Responsive Layout:** Adapts label/description layout based on content; long descriptions are truncated with ellipsis.\n *\n * ---\n *\n * ### Usage Guidelines\n * Use `obc-toggle-switch` for settings or preferences that require a simple on/off or enable/disable control. Ideal for scenarios where the user needs to quickly toggle a feature, such as activating notifications, enabling dark mode, or switching connectivity options. Avoid using for mutually exclusive choices—use radio buttons for those cases.\n *\n * - Place in forms, settings panels, or lists where binary choices are needed.\n * - Use the description property to clarify the effect of the toggle if the label alone is not sufficient.\n * - If an icon is relevant, provide it via the `icon` slot to reinforce the meaning.\n * - For accessibility, ensure the label clearly describes the toggle's function.\n *\n * ---\n *\n * ### Slots\n * | Slot Name | Renders When... | Purpose |\n * |-----------|---------------------|-------------------------------------------|\n * | icon | `hasIcon` is true | Leading icon to visually represent toggle |\n *\n * ---\n *\n * ### Properties and Attributes\n * - `label` (string): Main label for the toggle (required for clarity).\n * - `checked` (boolean): Whether the toggle is in the \"on\" state. Defaults to `false`.\n * - `disabled` (boolean): Disables interaction and applies a disabled style.\n * - `hasDescription` (boolean): If true, shows the description text below the label.\n * - `description` (string): Supplementary text shown when `hasDescription` is true.\n * - `hasBottomDivider` (boolean): If true, renders a divider below the toggle (useful in lists).\n * - `hasIcon` (boolean): If true, displays the `icon` slot before the label.\n *\n * ---\n *\n * ### Events\n * - `input` – Fired when the toggle state changes (checked/unchecked).\n * - `change` – Fired when the toggle state changes by user interaction.\n *\n * Both events report the state the user selected. When `externalControl` is\n * true the component does not update itself; the consumer decides whether to\n * apply the reported state to `checked` and may reject the interaction by\n * leaving `checked` unchanged.\n *\n * ---\n *\n * ### Best Practices\n * - Use concise labels and keep descriptions brief; long descriptions are truncated.\n * - Only use the divider when presenting multiple toggles in a list for visual separation.\n * - For accessibility, ensure the label is descriptive and unique within the context.\n * - Avoid using toggle switches for actions that require confirmation or have destructive effects.\n * - For mutually exclusive options, use radio buttons instead.\n *\n * ---\n *\n * **Example:**\n * ```html\n * <obc-toggle-switch\n * label=\"Enable notifications\"\n * ?checked=${true}\n * ?hasDescription=${true}\n * description=\"Receive updates and alerts\"\n * ?hasIcon=${true}\n * >\n * <obi-placeholder slot=\"icon\"></obi-placeholder>\n * </obc-toggle-switch>\n * ```\n *\n * In this example, the toggle switch displays a label, an icon, and a description, and is in the checked state.\n *\n * @slot icon - Leading icon slot (shown when `hasIcon` is true)\n * @fires input - {ObcToggleSwitchInputEvent} Dispatched when the value of the input changes\n * @fires change - {ObcToggleSwitchChangeEvent} Dispatched when the value of the input changes by user interaction\n * @stable\n */\n@customElement('obc-toggle-switch')\nexport class ObcToggleSwitch extends LitElement {\n /**\n * Main label for the toggle switch. Should clearly describe the setting being toggled.\n */\n @property({type: String}) label = 'Label';\n\n /**\n * Whether the toggle is in the \"on\" (checked) state.\n * Set to true to display as active/on.\n */\n @property({type: Boolean}) checked = false;\n\n /**\n * Disables the toggle, preventing user interaction and applying a disabled style.\n */\n @property({type: Boolean}) disabled = false;\n\n /**\n * If true, displays the description text below the label.\n */\n @property({type: Boolean}) hasDescription = false;\n\n /**\n * Supplementary description text shown when `hasDescription` is true.\n * Use to clarify the effect or details of the toggle.\n * @availableWhen hasDescription==true\n */\n @property({type: String}) description = '';\n\n /**\n * If true, renders a divider below the toggle switch.\n * Useful for visually separating items in a list.\n */\n @property({type: Boolean}) hasBottomDivider = false;\n\n /**\n * If true, displays a leading icon before the label.\n * Provide icon content via the `icon` slot.\n */\n @property({type: Boolean}) hasIcon = false;\n\n /**\n * If true, the toggle is controlled externally.\n * Use to control the toggle state from outside the component.\n */\n @property({type: Boolean}) externalControl = false;\n\n /**\n * The state the user selected in the most recent interaction. In\n * externalControl mode this can differ from `checked` until the consumer\n * accepts the change, so the change event reports it instead of `checked`.\n */\n private _userSelectedChecked?: boolean;\n\n /**\n * Handles input events to change the toggle state.\n * Prevents changes if the toggle is disabled.\n * @param e {InputEvent}\n * @fires input - Dispatched when the value of the input changes\n */\n private _tryChange(e: InputEvent) {\n if (this.disabled) {\n e.preventDefault();\n return;\n }\n\n const nextChecked = !this.checked;\n this._userSelectedChecked = nextChecked;\n if (!this.externalControl) {\n this.checked = nextChecked;\n }\n e.stopPropagation();\n this.dispatchEvent(\n new CustomEvent('input', {\n detail: {checked: nextChecked},\n })\n );\n\n if (this.externalControl) {\n (e.target as HTMLInputElement).checked = this.checked;\n }\n }\n\n private _fireChangeEvent(e: Event) {\n if (this.disabled) {\n e.preventDefault();\n return;\n }\n this.dispatchEvent(\n new CustomEvent('change', {\n detail: {checked: this._userSelectedChecked ?? this.checked},\n })\n );\n }\n\n override render() {\n return html`\n <label\n class=${classMap({\n checked: this.checked,\n disabled: this.disabled,\n 'has-description': this.hasDescription,\n })}\n >\n <div class=\"icon-label-container\">\n ${this.hasIcon\n ? html`<div class=\"icon-container\"><slot name=\"icon\"></slot></div>`\n : nothing}\n <div class=\"label-container\">\n <span class=\"label\">${this.label}</span>\n ${this.hasDescription\n ? html`<span class=\"description\">${this.description}</span>`\n : nothing}\n </div>\n </div>\n <div class=\"switch\">\n <div class=\"presenter ${classMap({checked: this.checked})}\">\n <div class=\"knob\"></div>\n <input\n type=\"checkbox\"\n .checked=${this.checked}\n ?disabled=${this.disabled}\n @input=${this._tryChange}\n @change=${this._fireChangeEvent}\n />\n </div>\n </div>\n ${this.hasBottomDivider\n ? html`<div class=\"bottom-divider\"></div>`\n : nothing}\n </label>\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-toggle-switch': ObcToggleSwitch;\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAqGO,IAAM,kBAAN,cAA8B,WAAW;AAAA,EAAzC,cAAA;AAAA,UAAA,GAAA,SAAA;AAIqB,SAAA,QAAQ;AAMP,SAAA,UAAU;AAKV,SAAA,WAAW;AAKX,SAAA,iBAAiB;AAOlB,SAAA,cAAc;AAMb,SAAA,mBAAmB;AAMnB,SAAA,UAAU;AAMV,SAAA,kBAAkB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAerC,WAAW,GAAe;AAChC,QAAI,KAAK,UAAU;AACjB,QAAE,eAAA;AACF;AAAA,IACF;AAEA,UAAM,cAAc,CAAC,KAAK;AAC1B,SAAK,uBAAuB;AAC5B,QAAI,CAAC,KAAK,iBAAiB;AACzB,WAAK,UAAU;AAAA,IACjB;AACA,MAAE,gBAAA;AACF,SAAK;AAAA,MACH,IAAI,YAAY,SAAS;AAAA,QACvB,QAAQ,EAAC,SAAS,YAAA;AAAA,MAAW,CAC9B;AAAA,IAAA;AAGH,QAAI,KAAK,iBAAiB;AACvB,QAAE,OAA4B,UAAU,KAAK;AAAA,IAChD;AAAA,EACF;AAAA,EAEQ,iBAAiB,GAAU;AACjC,QAAI,KAAK,UAAU;AACjB,QAAE,eAAA;AACF;AAAA,IACF;AACA,SAAK;AAAA,MACH,IAAI,YAAY,UAAU;AAAA,QACxB,QAAQ,EAAC,SAAS,KAAK,wBAAwB,KAAK,QAAA;AAAA,MAAO,CAC5D;AAAA,IAAA;AAAA,EAEL;AAAA,EAES,SAAS;AAChB,WAAO;AAAA;AAAA,gBAEK,SAAS;AAAA,MACf,SAAS,KAAK;AAAA,MACd,UAAU,KAAK;AAAA,MACf,mBAAmB,KAAK;AAAA,IAAA,CACzB,CAAC;AAAA;AAAA;AAAA,YAGE,KAAK,UACH,oEACA,OAAO;AAAA;AAAA,kCAEa,KAAK,KAAK;AAAA,cAC9B,KAAK,iBACH,iCAAiC,KAAK,WAAW,YACjD,OAAO;AAAA;AAAA;AAAA;AAAA,kCAIW,SAAS,EAAC,SAAS,KAAK,QAAA,CAAQ,CAAC;AAAA;AAAA;AAAA;AAAA,yBAI1C,KAAK,OAAO;AAAA,0BACX,KAAK,QAAQ;AAAA,uBAChB,KAAK,UAAU;AAAA,wBACd,KAAK,gBAAgB;AAAA;AAAA;AAAA;AAAA,UAInC,KAAK,mBACH,2CACA,OAAO;AAAA;AAAA;AAAA,EAGjB;AAGF;AAvIa,gBAsIK,SAAS,UAAU,cAAc;AAlIvB,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAJb,gBAIe,WAAA,SAAA,CAAA;AAMC,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAVd,gBAUgB,WAAA,WAAA,CAAA;AAKA,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAfd,gBAegB,WAAA,YAAA,CAAA;AAKA,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GApBd,gBAoBgB,WAAA,kBAAA,CAAA;AAOD,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GA3Bb,gBA2Be,WAAA,eAAA,CAAA;AAMC,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAjCd,gBAiCgB,WAAA,oBAAA,CAAA;AAMA,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAvCd,gBAuCgB,WAAA,WAAA,CAAA;AAMA,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GA7Cd,gBA6CgB,WAAA,mBAAA,CAAA;AA7ChB,kBAAN,gBAAA;AAAA,EADN,cAAc,mBAAmB;AAAA,GACrB,eAAA;"}
|
|
@@ -30,10 +30,32 @@ export declare function isReadoutValueType(value: unknown): value is ReadoutValu
|
|
|
30
30
|
* `Number('')` is `0`, a silently wrong reading.
|
|
31
31
|
*/
|
|
32
32
|
export declare function assertReadoutValueType(tagName: string, value: number | string | null | undefined, valueType: ReadoutValueType): void;
|
|
33
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* The value as a number, or `undefined` when it is text / unavailable.
|
|
35
|
+
*
|
|
36
|
+
* A non-finite number (`NaN`, `±Infinity`) counts as unavailable and renders the
|
|
37
|
+
* dash, the same as `null`. `NaN` is a runtime data condition — a sensor
|
|
38
|
+
* dropout, a `0/0`, a bad parse — not a programmer error, so it must not throw;
|
|
39
|
+
* and `value.toFixed()` would otherwise render the literal text `"NaN"` /
|
|
40
|
+
* `"Infinity"` in place of a reading. This also makes the number path agree with
|
|
41
|
+
* the string path below, which has always resolved a non-finite string to
|
|
42
|
+
* `undefined` — before this, `<obc-readout value="NaN">` rendered a dash while
|
|
43
|
+
* `.value=${NaN}` rendered `"NaN"`.
|
|
44
|
+
*/
|
|
34
45
|
export declare function resolveReadoutNumericValue(value: number | string | null | undefined, valueType: ReadoutValueType): number | undefined;
|
|
35
46
|
/** The value as display text, or `undefined` when not in text mode / blank. */
|
|
36
47
|
export declare function resolveReadoutTextValue(value: number | string | null | undefined, valueType: ReadoutValueType): string | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* The character used for an unavailable ("no reading") value.
|
|
50
|
+
*
|
|
51
|
+
* U+2012 FIGURE DASH, not the ASCII hyphen-minus: it is defined to be the same
|
|
52
|
+
* width as a digit, so the placeholder lines up with the reading it stands in
|
|
53
|
+
* for. Measured in Noto Sans with tabular figures at `size="m"` — digit 13.02px,
|
|
54
|
+
* U+2012 13.02px, U+002D 7.02px, en dash 11.02px, em dash 22.02px. With a
|
|
55
|
+
* hyphen, `-.--` sat 46% narrow per character and its decimal point missed the
|
|
56
|
+
* reading's; with U+2012 the point and every fraction position align exactly.
|
|
57
|
+
*/
|
|
58
|
+
export declare const READOUT_UNAVAILABLE_DASH = "\u2012";
|
|
37
59
|
export declare function formatNumericValue(value: number | undefined, options: ReadoutNumericFormatOptions): string;
|
|
38
60
|
export declare function readoutFormattedInteger(valueText: string): number;
|
|
39
61
|
export declare function getHintZeros(value: number | undefined, { showZeroPadding, minValueLength, fractionDigits }: ReadoutNumericFormatOptions): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readout-formatters.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/readout/readout-formatters.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,2BAA2B,GAAG;IACxC,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF;;;;GAIG;AACH,oBAAY,gBAAgB;IAC1B,MAAM,WAAW;IACjB,IAAI,SAAS;CACd;AAID,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAE5E;AAMD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,EACzC,SAAS,EAAE,gBAAgB,GAC1B,IAAI,CAyBN;AAED
|
|
1
|
+
{"version":3,"file":"readout-formatters.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/readout/readout-formatters.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,2BAA2B,GAAG;IACxC,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF;;;;GAIG;AACH,oBAAY,gBAAgB;IAC1B,MAAM,WAAW;IACjB,IAAI,SAAS;CACd;AAID,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAE5E;AAMD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,EACzC,SAAS,EAAE,gBAAgB,GAC1B,IAAI,CAyBN;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,EACzC,SAAS,EAAE,gBAAgB,GAC1B,MAAM,GAAG,SAAS,CAgBpB;AAED,+EAA+E;AAC/E,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,EACzC,SAAS,EAAE,gBAAgB,GAC1B,MAAM,GAAG,SAAS,CAUpB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,wBAAwB,WAAW,CAAC;AA+BjD,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,OAAO,EAAE,2BAA2B,GACnC,MAAM,CAUR;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CASjE;AAED,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,EAAC,eAAe,EAAE,cAAc,EAAE,cAAc,EAAC,EAAE,2BAA2B,GAC7E,MAAM,CAeR"}
|
|
@@ -32,7 +32,7 @@ function resolveReadoutNumericValue(value, valueType) {
|
|
|
32
32
|
return void 0;
|
|
33
33
|
}
|
|
34
34
|
if (typeof value === "number") {
|
|
35
|
-
return value;
|
|
35
|
+
return Number.isFinite(value) ? value : void 0;
|
|
36
36
|
}
|
|
37
37
|
if (isBlank(value)) {
|
|
38
38
|
return void 0;
|
|
@@ -47,6 +47,7 @@ function resolveReadoutTextValue(value, valueType) {
|
|
|
47
47
|
const text = typeof value === "number" ? String(value) : value;
|
|
48
48
|
return isBlank(text) ? void 0 : text;
|
|
49
49
|
}
|
|
50
|
+
const READOUT_UNAVAILABLE_DASH = "‒";
|
|
50
51
|
function dashedGenerator({
|
|
51
52
|
showZeroPadding,
|
|
52
53
|
minValueLength,
|
|
@@ -54,13 +55,13 @@ function dashedGenerator({
|
|
|
54
55
|
}) {
|
|
55
56
|
const visibleDigits = showZeroPadding ? Math.max(minValueLength, 1) : 1;
|
|
56
57
|
if (fractionDigits < 1) {
|
|
57
|
-
return
|
|
58
|
+
return READOUT_UNAVAILABLE_DASH.repeat(visibleDigits);
|
|
58
59
|
}
|
|
59
60
|
const integerDigits = visibleDigits - fractionDigits;
|
|
60
|
-
return
|
|
61
|
+
return READOUT_UNAVAILABLE_DASH.repeat(Math.max(integerDigits, 1)) + "." + READOUT_UNAVAILABLE_DASH.repeat(fractionDigits);
|
|
61
62
|
}
|
|
62
63
|
function formatNumericValue(value, options) {
|
|
63
|
-
if (value === void 0) {
|
|
64
|
+
if (value === void 0 || !Number.isFinite(value)) {
|
|
64
65
|
return dashedGenerator(options);
|
|
65
66
|
}
|
|
66
67
|
return value.toFixed(options.fractionDigits);
|
|
@@ -89,6 +90,7 @@ function getHintZeros(value, { showZeroPadding, minValueLength, fractionDigits }
|
|
|
89
90
|
return "";
|
|
90
91
|
}
|
|
91
92
|
export {
|
|
93
|
+
READOUT_UNAVAILABLE_DASH,
|
|
92
94
|
ReadoutValueType,
|
|
93
95
|
assertReadoutValueType,
|
|
94
96
|
formatNumericValue,
|