@oicl/openbridge-webcomponents-full-bundle 2.0.0-next.77 → 2.0.0-next.79

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.
Files changed (53) hide show
  1. package/.storybook/vitest.setup.ts +24 -0
  2. package/bundle/openbridge-webcomponents.bundle.js +117 -29
  3. package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
  4. package/custom-elements.json +77 -5
  5. package/dist/components/input/input.d.ts +1 -0
  6. package/dist/components/input/input.d.ts.map +1 -0
  7. package/dist/components/input/input.js +2 -0
  8. package/dist/components/input/input.js.map +1 -0
  9. package/dist/components/pagination/pagination.d.ts +9 -0
  10. package/dist/components/pagination/pagination.d.ts.map +1 -1
  11. package/dist/components/pagination/pagination.js +12 -2
  12. package/dist/components/pagination/pagination.js.map +1 -1
  13. package/dist/components/slider/slider.d.ts +14 -1
  14. package/dist/components/slider/slider.d.ts.map +1 -1
  15. package/dist/components/slider/slider.js +17 -0
  16. package/dist/components/slider/slider.js.map +1 -1
  17. package/dist/components/slider-double/slider-double.d.ts +17 -1
  18. package/dist/components/slider-double/slider-double.d.ts.map +1 -1
  19. package/dist/components/slider-double/slider-double.js +15 -0
  20. package/dist/components/slider-double/slider-double.js.map +1 -1
  21. package/dist/components/toggle-button-group/toggle-button-group.d.ts +4 -0
  22. package/dist/components/toggle-button-group/toggle-button-group.d.ts.map +1 -1
  23. package/dist/components/toggle-button-group/toggle-button-group.js +15 -3
  24. package/dist/components/toggle-button-group/toggle-button-group.js.map +1 -1
  25. package/dist/components/toggle-button-vertical-group/toggle-button-vertical-group.d.ts +4 -0
  26. package/dist/components/toggle-button-vertical-group/toggle-button-vertical-group.d.ts.map +1 -1
  27. package/dist/components/toggle-button-vertical-group/toggle-button-vertical-group.js +10 -3
  28. package/dist/components/toggle-button-vertical-group/toggle-button-vertical-group.js.map +1 -1
  29. package/dist/components/toggle-switch/toggle-switch.d.ts +2 -0
  30. package/dist/components/toggle-switch/toggle-switch.d.ts.map +1 -1
  31. package/dist/components/toggle-switch/toggle-switch.js +8 -0
  32. package/dist/components/toggle-switch/toggle-switch.js.map +1 -1
  33. package/dist/navigation-instruments/indicator-graph/indicator-graph.css.js +34 -20
  34. package/dist/navigation-instruments/indicator-graph/indicator-graph.css.js.map +1 -1
  35. package/dist/navigation-instruments/indicator-graph/indicator-graph.d.ts.map +1 -1
  36. package/dist/navigation-instruments/indicator-graph/indicator-graph.js +2 -1
  37. package/dist/navigation-instruments/indicator-graph/indicator-graph.js.map +1 -1
  38. package/dist/navigation-instruments/watch/watch.css.js +4 -0
  39. package/dist/navigation-instruments/watch/watch.css.js.map +1 -1
  40. package/package.json +1 -1
  41. package/src/components/input/input.ts +0 -0
  42. package/src/components/pagination/pagination.ts +25 -2
  43. package/src/components/slider/slider.ts +27 -1
  44. package/src/components/slider-double/slider-double.ts +28 -1
  45. package/src/components/toggle-button-group/toggle-button-group.ts +26 -3
  46. package/src/components/toggle-button-vertical-group/toggle-button-vertical-group.ts +28 -3
  47. package/src/components/toggle-switch/toggle-switch.ts +10 -0
  48. package/src/navigation-instruments/indicator-graph/indicator-graph.css +34 -20
  49. package/src/navigation-instruments/indicator-graph/indicator-graph.ts +2 -1
  50. package/src/navigation-instruments/watch/watch.css +4 -0
  51. package/src/navigation-instruments/watch/watch.stories.ts +161 -171
  52. package/src/storybook-util.ts +1 -1
  53. package/vitest.config.ts +6 -0
@@ -40,7 +40,7 @@ let ObcToggleButtonVerticalGroup = class extends LitElement {
40
40
  if (this.disabled) return null;
41
41
  return Array.from(this.options).find((opt) => !opt.disabled) || null;
42
42
  }
43
- updateSelection(newValue, emitEvent = true) {
43
+ updateSelection(newValue, emitValueEvent = true, emitChangeEvent = false) {
44
44
  const oldValue = this.value;
45
45
  if (!this.hasAnyEnabledOption()) {
46
46
  this.options.forEach((option) => {
@@ -69,13 +69,20 @@ let ObcToggleButtonVerticalGroup = class extends LitElement {
69
69
  option.selected = option.value === newValue;
70
70
  });
71
71
  this.updateDividers();
72
- if (emitEvent && oldValue !== newValue) {
72
+ if (emitValueEvent && oldValue !== newValue) {
73
73
  this.dispatchEvent(
74
74
  new CustomEvent("value", {
75
75
  detail: { value: newValue, previousValue: oldValue }
76
76
  })
77
77
  );
78
78
  }
79
+ if (emitChangeEvent && oldValue !== newValue) {
80
+ this.dispatchEvent(
81
+ new CustomEvent("change", {
82
+ detail: { value: newValue }
83
+ })
84
+ );
85
+ }
79
86
  }
80
87
  firstUpdated(changed) {
81
88
  super.firstUpdated(changed);
@@ -174,7 +181,7 @@ let ObcToggleButtonVerticalGroup = class extends LitElement {
174
181
  }
175
182
  onOptionSelected(e) {
176
183
  const { value } = e.detail;
177
- this.updateSelection(value);
184
+ this.updateSelection(value, true, true);
178
185
  }
179
186
  render() {
180
187
  const classes = {
@@ -1 +1 @@
1
- {"version":3,"file":"toggle-button-vertical-group.js","sources":["../../../src/components/toggle-button-vertical-group/toggle-button-vertical-group.ts"],"sourcesContent":["import {LitElement, html, unsafeCSS, PropertyValues} from 'lit';\nimport {property, queryAssignedElements} from 'lit/decorators.js';\nimport {customElement} from '../../decorator.js';\nimport {classMap} from 'lit/directives/class-map.js';\n\nimport {\n ObcToggleButtonVerticalOption,\n ObcToggleButtonVerticalOptionType,\n} from '../toggle-button-vertical-option/toggle-button-vertical-option.js';\n\nimport style from './toggle-button-vertical-group.css?inline';\n\nexport type ObcToggleButtonVerticalGroupValueChangeEvent = CustomEvent<{\n value: string;\n previousValue: string;\n}>;\n\n/**\n * `<obc-toggle-button-vertical-group>` – A vertically oriented segmented control for selecting a single option from a set.\n *\n * Provides a vertical stack of connected toggle buttons where only one option can be selected at a time.\n * Each option is represented by an `<obc-toggle-button-vertical-option>` child element. The group manages selection\n * state automatically, deselecting the previous option when a new one is chosen.\n *\n * Appears as a visually unified vertical column of buttons with clear selection indicators. Commonly used for sidebar\n * navigation, vertical filter controls, or mode selection in vertical layouts. Ideal for scenarios where vertical\n * space is available and horizontal space is limited, such as side panels or navigation drawers.\n *\n * ### Features\n *\n * - **Single selection mode:** Only one option can be active at a time; selecting a new option automatically\n * deselects the previous one. Similar to radio button behavior but with a button-like vertical appearance.\n * - **Visual variants:**\n * - `regular` (default): Standard appearance with full background and border styling.\n * - `flat`: Minimal style with reduced visual weight, no prominent background or border.\n * - `normal`: **TODO(designer)** – Clarify the visual difference and intended use case for the `normal` variant compared to `regular` and `flat`.\n * - **Layout behavior:**\n * - By default, the group stretches to fill available container width, with options stacked vertically.\n * - When `hugWidth` is true, the group shrinks to fit its content width instead of expanding.\n * - **Empty selection mode:** When `allowEmptySelection` is true, a `value` that does not match any enabled\n * option leaves the group with no option selected, instead of defaulting to the first enabled option. Use\n * this when a selection may legitimately be absent (e.g. unset, loading, or error states) so the UI does not\n * imply a choice the user has not made.\n * - **Disabled state:** Setting `disabled` on the group disables all contained options at once. Individual\n * options can also be disabled independently while the group remains enabled.\n * - **Divider management:** Automatically shows visual dividers between options and hides the divider after\n * the last option for a clean, unified appearance.\n * - **Property propagation:** The group automatically synchronizes the `type` property to all child\n * `<obc-toggle-button-vertical-option>` elements for consistent styling.\n * - **Automatic fallback selection:** If the current value is set to a disabled or non-existent option, the\n * group automatically selects the first enabled option to ensure a valid state.\n *\n * ### Usage Guidelines\n *\n * Use `<obc-toggle-button-vertical-group>` when you need users to choose exactly one option from a small set of\n * mutually exclusive choices (typically 2-5 options) in a vertical layout. It provides a more compact and visually\n * integrated alternative to radio buttons for vertical navigation or control panels.\n *\n * **Ideal use cases:**\n * - Sidebar navigation toggles (e.g., dashboard/reports/settings views)\n * - Vertical filter controls (e.g., all/active/archived items)\n * - Mode selectors in vertical panels (e.g., edit/preview/code modes)\n * - View toggles in constrained horizontal spaces (e.g., mobile side panels)\n * - Control panels with vertical layout preference\n *\n * **When not to use:**\n * - For binary on/off choices, use a switch or checkbox instead.\n * - For multiple selections from a set, use checkboxes or chips.\n * - For many options (6+), consider a dropdown/select or radio button list for better scannability.\n * - For horizontal layouts with adequate space, use `<obc-toggle-button-group>` instead.\n * - For navigation between pages or sections, use tabs or a navigation menu.\n *\n * **Best Practices:**\n * - Each option must have a unique `value` property to prevent selection conflicts.\n * - Provide clear, concise labels for each option. Keep text short (1-2 words ideal).\n * - For icon-only buttons, ensure icons are universally recognizable or provide tooltips.\n * - Set an initial `value` to indicate the default selection, or the first enabled option will be selected automatically.\n * - Avoid disabling the currently selected option; if an option becomes unavailable, selection will shift to the first enabled option.\n * - Use `type=\"flat\"` in dense UIs or when the toggle is secondary to other content.\n * - Ensure adequate vertical space for the number of options to avoid excessive scrolling or cramped layouts.\n *\n * ### Slots\n *\n * | Slot Name | Renders When... | Purpose |\n * |-----------|-----------------|---------|\n * | (default) | Always | Place one or more `<obc-toggle-button-vertical-option>` elements here to define the selectable options in the group. Each option can include an icon via its own `icon` slot. |\n *\n * ### Events\n *\n * - `value` – Fired when the selected value changes, either through user interaction or programmatic change.\n * Event detail: `{ value: string, previousValue: string }`. Listen to this event to react to selection changes.\n *\n * ### Example\n *\n * ```html\n * <obc-toggle-button-vertical-group value=\"list\" type=\"regular\">\n * <obc-toggle-button-vertical-option value=\"list\" label=\"List\" hasIcon>\n * <obi-placeholder slot=\"icon\"></obi-placeholder>\n * </obc-toggle-button-vertical-option>\n * <obc-toggle-button-vertical-option value=\"grid\" label=\"Grid\" hasIcon>\n * <obi-placeholder slot=\"icon\"></obi-placeholder>\n * </obc-toggle-button-vertical-option>\n * <obc-toggle-button-vertical-option value=\"table\" label=\"Table\" hasIcon>\n * <obi-placeholder slot=\"icon\"></obi-placeholder>\n * </obc-toggle-button-vertical-option>\n * </obc-toggle-button-vertical-group>\n * ```\n *\n * @slot - Place one or more `<obc-toggle-button-vertical-option>` elements here to define the selectable options.\n * @fires value {CustomEvent<{value: string, previousValue: string}>} Fired when the selected value changes.\n */\n@customElement('obc-toggle-button-vertical-group')\nexport class ObcToggleButtonVerticalGroup extends LitElement {\n /**\n * The value of the currently selected option.\n *\n * Setting this property programmatically updates the selection. If the value does not match any enabled option, the group selects the first available enabled option.\n */\n @property({type: String}) value = '';\n\n /**\n * Visual style for all options in the group.\n *\n * One of: \"flat\", \"regular\", \"normal\".\n */\n @property({type: String}) type = ObcToggleButtonVerticalOptionType.regular;\n\n /**\n * If true, the group shrinks to fit its content width instead of stretching to fill its container.\n *\n * Defaults to false.\n */\n @property({type: Boolean}) hugWidth = false;\n\n /**\n * If true, a `value` that does not match any enabled option leaves the group with no option selected\n * instead of defaulting to the first enabled option.\n *\n * This also applies when the currently selected option becomes disabled: the group clears its selection\n * rather than falling back to another option.\n *\n * Defaults to false (the first enabled option is selected when the value does not match).\n */\n @property({type: Boolean}) allowEmptySelection = false;\n\n /**\n * Disables the entire group and all contained options.\n *\n * When set to true, all options become non-interactive, regardless of their individual disabled state.\n *\n * Defaults to false.\n */\n @property({type: Boolean, reflect: true}) disabled = false;\n\n @queryAssignedElements({selector: 'obc-toggle-button-vertical-option'})\n private options!: NodeListOf<ObcToggleButtonVerticalOption>;\n\n private _originalDisabledStates = new Map<\n ObcToggleButtonVerticalOption,\n boolean\n >();\n\n private hasAnyEnabledOption(): boolean {\n if (this.disabled) return false;\n return Array.from(this.options).some((opt) => !opt.disabled);\n }\n\n private canSelectOption(value: string): boolean {\n if (this.disabled) return false;\n const option = this.getOptionByValue(value);\n return option !== null && !option.disabled;\n }\n\n private getOptionByValue(\n value: string\n ): ObcToggleButtonVerticalOption | null {\n return Array.from(this.options).find((opt) => opt.value === value) || null;\n }\n\n private getFirstSelectableOption(): ObcToggleButtonVerticalOption | null {\n if (this.disabled) return null;\n return Array.from(this.options).find((opt) => !opt.disabled) || null;\n }\n\n private updateSelection(newValue: string, emitEvent: boolean = true) {\n const oldValue = this.value;\n\n if (!this.hasAnyEnabledOption()) {\n this.options.forEach((option) => {\n option.selected = option.value === this.value;\n });\n this.updateDividers();\n return;\n }\n\n if (!this.canSelectOption(newValue)) {\n if (this.value && this.getOptionByValue(this.value)) {\n this.options.forEach((option) => {\n option.selected = option.value === this.value;\n });\n this.updateDividers();\n return;\n }\n if (this.allowEmptySelection) {\n newValue = '';\n } else {\n const fallback = this.getFirstSelectableOption();\n newValue = fallback?.value || '';\n }\n }\n\n this.value = newValue;\n\n this.options.forEach((option) => {\n option.selected = option.value === newValue;\n });\n\n this.updateDividers();\n\n if (emitEvent && oldValue !== newValue) {\n /**\n * Fired when the selected option changes.\n *\n * The event detail contains the new value and the previous value:\n * `{ value: string, previousValue: string }`\n *\n * @event value\n */\n this.dispatchEvent(\n new CustomEvent('value', {\n detail: {value: newValue, previousValue: oldValue},\n })\n );\n }\n }\n\n protected override firstUpdated(changed: PropertyValues) {\n super.firstUpdated(changed);\n\n const values = Array.from(this.options).map((opt) => opt.value);\n const uniqueValues = new Set(values);\n if (values.length !== uniqueValues.size) {\n console.warn(\n 'Toggle button vertical group has duplicate values. This may cause unexpected behavior.'\n );\n }\n\n this.options.forEach((opt) => {\n this._originalDisabledStates.set(opt, opt.disabled);\n\n opt.addEventListener('selected', (e) => this.onOptionSelected(e));\n\n const observer = new MutationObserver((mutations) => {\n mutations.forEach((mutation) => {\n if (\n mutation.attributeName === 'disabled' &&\n !opt.hasAttribute('data-group-disabled')\n ) {\n this._originalDisabledStates.set(opt, opt.disabled);\n this.handleOptionDisabledChange();\n }\n });\n });\n observer.observe(opt, {attributes: true, attributeFilter: ['disabled']});\n\n opt.type = this.type;\n\n if (this.disabled) {\n opt.setAttribute('data-group-disabled', 'true');\n opt.disabled = true;\n }\n });\n\n if (!this.value || !this.getOptionByValue(this.value)) {\n if (this.allowEmptySelection) {\n this.updateSelection('', false);\n } else {\n const firstSelectable = this.getFirstSelectableOption();\n if (firstSelectable) {\n this.updateSelection(firstSelectable.value, false);\n }\n }\n } else {\n this.updateSelection(this.value, false);\n }\n }\n\n private handleOptionDisabledChange() {\n const currentOption = this.getOptionByValue(this.value);\n if (currentOption?.disabled && this.hasAnyEnabledOption()) {\n if (this.allowEmptySelection) {\n this.updateSelection('');\n return;\n }\n const firstSelectable = this.getFirstSelectableOption();\n if (firstSelectable) {\n this.updateSelection(firstSelectable.value);\n }\n }\n }\n\n override willUpdate(changed: PropertyValues): void {\n if (changed.has('value')) {\n this.updateSelection(this.value);\n }\n\n if (changed.has('type')) {\n this.options.forEach((opt) => {\n opt.type = this.type;\n });\n }\n\n if (changed.has('disabled')) {\n this.options.forEach((option) => {\n if (this.disabled) {\n option.setAttribute('data-group-disabled', 'true');\n option.disabled = true;\n } else {\n option.removeAttribute('data-group-disabled');\n const originalState =\n this._originalDisabledStates.get(option) || false;\n option.disabled = originalState;\n }\n });\n }\n }\n\n override updated(changedProperties: PropertyValues) {\n super.updated(changedProperties);\n\n const currentOption = this.getOptionByValue(this.value);\n if (currentOption?.disabled && this.hasAnyEnabledOption()) {\n if (this.allowEmptySelection) {\n this.updateSelection('');\n return;\n }\n const firstSelectable = this.getFirstSelectableOption();\n if (firstSelectable) {\n this.updateSelection(firstSelectable.value);\n }\n }\n }\n\n private updateDividers(): void {\n const last = this.options.length - 1;\n this.options.forEach((opt, idx) => {\n opt.showDivider = idx !== last;\n });\n }\n\n private onOptionSelected(e: Event): void {\n const {value} = (e as CustomEvent).detail;\n this.updateSelection(value);\n }\n\n override render() {\n const classes = {\n 'outer-wrapper': true,\n flat: this.type === ObcToggleButtonVerticalOptionType.flat,\n regular: this.type === ObcToggleButtonVerticalOptionType.regular,\n normal: this.type === ObcToggleButtonVerticalOptionType.normal,\n 'hug-width': this.hugWidth,\n disabled: this.disabled,\n };\n\n return html`\n <div class=${classMap(classes)}>\n <div class=\"wrapper\"><slot></slot></div>\n </div>\n `;\n }\n\n static override styles = unsafeCSS(style);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-toggle-button-vertical-group': ObcToggleButtonVerticalGroup;\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"toggle-button-vertical-group.js","sources":["../../../src/components/toggle-button-vertical-group/toggle-button-vertical-group.ts"],"sourcesContent":["import {LitElement, html, unsafeCSS, PropertyValues} from 'lit';\nimport {property, queryAssignedElements} from 'lit/decorators.js';\nimport {customElement} from '../../decorator.js';\nimport {classMap} from 'lit/directives/class-map.js';\n\nimport {\n ObcToggleButtonVerticalOption,\n ObcToggleButtonVerticalOptionType,\n} from '../toggle-button-vertical-option/toggle-button-vertical-option.js';\n\nimport style from './toggle-button-vertical-group.css?inline';\n\nexport type ObcToggleButtonVerticalGroupValueChangeEvent = CustomEvent<{\n value: string;\n previousValue: string;\n}>;\n\nexport type ObcToggleButtonVerticalGroupChangeEvent = CustomEvent<{\n value: string;\n}>;\n\n/**\n * `<obc-toggle-button-vertical-group>` – A vertically oriented segmented control for selecting a single option from a set.\n *\n * Provides a vertical stack of connected toggle buttons where only one option can be selected at a time.\n * Each option is represented by an `<obc-toggle-button-vertical-option>` child element. The group manages selection\n * state automatically, deselecting the previous option when a new one is chosen.\n *\n * Appears as a visually unified vertical column of buttons with clear selection indicators. Commonly used for sidebar\n * navigation, vertical filter controls, or mode selection in vertical layouts. Ideal for scenarios where vertical\n * space is available and horizontal space is limited, such as side panels or navigation drawers.\n *\n * ### Features\n *\n * - **Single selection mode:** Only one option can be active at a time; selecting a new option automatically\n * deselects the previous one. Similar to radio button behavior but with a button-like vertical appearance.\n * - **Visual variants:**\n * - `regular` (default): Standard appearance with full background and border styling.\n * - `flat`: Minimal style with reduced visual weight, no prominent background or border.\n * - `normal`: **TODO(designer)** – Clarify the visual difference and intended use case for the `normal` variant compared to `regular` and `flat`.\n * - **Layout behavior:**\n * - By default, the group stretches to fill available container width, with options stacked vertically.\n * - When `hugWidth` is true, the group shrinks to fit its content width instead of expanding.\n * - **Empty selection mode:** When `allowEmptySelection` is true, a `value` that does not match any enabled\n * option leaves the group with no option selected, instead of defaulting to the first enabled option. Use\n * this when a selection may legitimately be absent (e.g. unset, loading, or error states) so the UI does not\n * imply a choice the user has not made.\n * - **Disabled state:** Setting `disabled` on the group disables all contained options at once. Individual\n * options can also be disabled independently while the group remains enabled.\n * - **Divider management:** Automatically shows visual dividers between options and hides the divider after\n * the last option for a clean, unified appearance.\n * - **Property propagation:** The group automatically synchronizes the `type` property to all child\n * `<obc-toggle-button-vertical-option>` elements for consistent styling.\n * - **Automatic fallback selection:** If the current value is set to a disabled or non-existent option, the\n * group automatically selects the first enabled option to ensure a valid state.\n *\n * ### Usage Guidelines\n *\n * Use `<obc-toggle-button-vertical-group>` when you need users to choose exactly one option from a small set of\n * mutually exclusive choices (typically 2-5 options) in a vertical layout. It provides a more compact and visually\n * integrated alternative to radio buttons for vertical navigation or control panels.\n *\n * **Ideal use cases:**\n * - Sidebar navigation toggles (e.g., dashboard/reports/settings views)\n * - Vertical filter controls (e.g., all/active/archived items)\n * - Mode selectors in vertical panels (e.g., edit/preview/code modes)\n * - View toggles in constrained horizontal spaces (e.g., mobile side panels)\n * - Control panels with vertical layout preference\n *\n * **When not to use:**\n * - For binary on/off choices, use a switch or checkbox instead.\n * - For multiple selections from a set, use checkboxes or chips.\n * - For many options (6+), consider a dropdown/select or radio button list for better scannability.\n * - For horizontal layouts with adequate space, use `<obc-toggle-button-group>` instead.\n * - For navigation between pages or sections, use tabs or a navigation menu.\n *\n * **Best Practices:**\n * - Each option must have a unique `value` property to prevent selection conflicts.\n * - Provide clear, concise labels for each option. Keep text short (1-2 words ideal).\n * - For icon-only buttons, ensure icons are universally recognizable or provide tooltips.\n * - Set an initial `value` to indicate the default selection, or the first enabled option will be selected automatically.\n * - Avoid disabling the currently selected option; if an option becomes unavailable, selection will shift to the first enabled option.\n * - Use `type=\"flat\"` in dense UIs or when the toggle is secondary to other content.\n * - Ensure adequate vertical space for the number of options to avoid excessive scrolling or cramped layouts.\n *\n * ### Slots\n *\n * | Slot Name | Renders When... | Purpose |\n * |-----------|-----------------|---------|\n * | (default) | Always | Place one or more `<obc-toggle-button-vertical-option>` elements here to define the selectable options in the group. Each option can include an icon via its own `icon` slot. |\n *\n * ### Events\n *\n * - `value` – Fired when the selected value changes, either through user interaction or programmatic change.\n * Event detail: `{ value: string, previousValue: string }`. Listen to this event to react to selection changes.\n *\n * ### Example\n *\n * ```html\n * <obc-toggle-button-vertical-group value=\"list\" type=\"regular\">\n * <obc-toggle-button-vertical-option value=\"list\" label=\"List\" hasIcon>\n * <obi-placeholder slot=\"icon\"></obi-placeholder>\n * </obc-toggle-button-vertical-option>\n * <obc-toggle-button-vertical-option value=\"grid\" label=\"Grid\" hasIcon>\n * <obi-placeholder slot=\"icon\"></obi-placeholder>\n * </obc-toggle-button-vertical-option>\n * <obc-toggle-button-vertical-option value=\"table\" label=\"Table\" hasIcon>\n * <obi-placeholder slot=\"icon\"></obi-placeholder>\n * </obc-toggle-button-vertical-option>\n * </obc-toggle-button-vertical-group>\n * ```\n *\n * @slot - Place one or more `<obc-toggle-button-vertical-option>` elements here to define the selectable options.\n * @fires value {CustomEvent<{value: string, previousValue: string}>} Fired when the selected value changes.\n * @fires change {CustomEvent<{value: string}>} Fired when the selected value changes by user interaction.\n */\n@customElement('obc-toggle-button-vertical-group')\nexport class ObcToggleButtonVerticalGroup extends LitElement {\n /**\n * The value of the currently selected option.\n *\n * Setting this property programmatically updates the selection. If the value does not match any enabled option, the group selects the first available enabled option.\n */\n @property({type: String}) value = '';\n\n /**\n * Visual style for all options in the group.\n *\n * One of: \"flat\", \"regular\", \"normal\".\n */\n @property({type: String}) type = ObcToggleButtonVerticalOptionType.regular;\n\n /**\n * If true, the group shrinks to fit its content width instead of stretching to fill its container.\n *\n * Defaults to false.\n */\n @property({type: Boolean}) hugWidth = false;\n\n /**\n * If true, a `value` that does not match any enabled option leaves the group with no option selected\n * instead of defaulting to the first enabled option.\n *\n * This also applies when the currently selected option becomes disabled: the group clears its selection\n * rather than falling back to another option.\n *\n * Defaults to false (the first enabled option is selected when the value does not match).\n */\n @property({type: Boolean}) allowEmptySelection = false;\n\n /**\n * Disables the entire group and all contained options.\n *\n * When set to true, all options become non-interactive, regardless of their individual disabled state.\n *\n * Defaults to false.\n */\n @property({type: Boolean, reflect: true}) disabled = false;\n\n @queryAssignedElements({selector: 'obc-toggle-button-vertical-option'})\n private options!: NodeListOf<ObcToggleButtonVerticalOption>;\n\n private _originalDisabledStates = new Map<\n ObcToggleButtonVerticalOption,\n boolean\n >();\n\n private hasAnyEnabledOption(): boolean {\n if (this.disabled) return false;\n return Array.from(this.options).some((opt) => !opt.disabled);\n }\n\n private canSelectOption(value: string): boolean {\n if (this.disabled) return false;\n const option = this.getOptionByValue(value);\n return option !== null && !option.disabled;\n }\n\n private getOptionByValue(\n value: string\n ): ObcToggleButtonVerticalOption | null {\n return Array.from(this.options).find((opt) => opt.value === value) || null;\n }\n\n private getFirstSelectableOption(): ObcToggleButtonVerticalOption | null {\n if (this.disabled) return null;\n return Array.from(this.options).find((opt) => !opt.disabled) || null;\n }\n\n private updateSelection(\n newValue: string,\n emitValueEvent: boolean = true,\n emitChangeEvent: boolean = false\n ) {\n const oldValue = this.value;\n\n if (!this.hasAnyEnabledOption()) {\n this.options.forEach((option) => {\n option.selected = option.value === this.value;\n });\n this.updateDividers();\n return;\n }\n\n if (!this.canSelectOption(newValue)) {\n if (this.value && this.getOptionByValue(this.value)) {\n this.options.forEach((option) => {\n option.selected = option.value === this.value;\n });\n this.updateDividers();\n return;\n }\n if (this.allowEmptySelection) {\n newValue = '';\n } else {\n const fallback = this.getFirstSelectableOption();\n newValue = fallback?.value || '';\n }\n }\n\n this.value = newValue;\n\n this.options.forEach((option) => {\n option.selected = option.value === newValue;\n });\n\n this.updateDividers();\n\n if (emitValueEvent && oldValue !== newValue) {\n /**\n * Fired when the selected option changes.\n *\n * The event detail contains the new value and the previous value:\n * `{ value: string, previousValue: string }`\n *\n * @event value\n */\n this.dispatchEvent(\n new CustomEvent('value', {\n detail: {value: newValue, previousValue: oldValue},\n })\n );\n }\n\n if (emitChangeEvent && oldValue !== newValue) {\n /**\n * Fired when the selected value changes by user interaction.\n *\n * The event detail contains the new value:\n * `{ value: string }`\n *\n * @event change\n */\n this.dispatchEvent(\n new CustomEvent('change', {\n detail: {value: newValue},\n })\n );\n }\n }\n\n protected override firstUpdated(changed: PropertyValues) {\n super.firstUpdated(changed);\n\n const values = Array.from(this.options).map((opt) => opt.value);\n const uniqueValues = new Set(values);\n if (values.length !== uniqueValues.size) {\n console.warn(\n 'Toggle button vertical group has duplicate values. This may cause unexpected behavior.'\n );\n }\n\n this.options.forEach((opt) => {\n this._originalDisabledStates.set(opt, opt.disabled);\n\n opt.addEventListener('selected', (e) => this.onOptionSelected(e));\n\n const observer = new MutationObserver((mutations) => {\n mutations.forEach((mutation) => {\n if (\n mutation.attributeName === 'disabled' &&\n !opt.hasAttribute('data-group-disabled')\n ) {\n this._originalDisabledStates.set(opt, opt.disabled);\n this.handleOptionDisabledChange();\n }\n });\n });\n observer.observe(opt, {attributes: true, attributeFilter: ['disabled']});\n\n opt.type = this.type;\n\n if (this.disabled) {\n opt.setAttribute('data-group-disabled', 'true');\n opt.disabled = true;\n }\n });\n\n if (!this.value || !this.getOptionByValue(this.value)) {\n if (this.allowEmptySelection) {\n this.updateSelection('', false);\n } else {\n const firstSelectable = this.getFirstSelectableOption();\n if (firstSelectable) {\n this.updateSelection(firstSelectable.value, false);\n }\n }\n } else {\n this.updateSelection(this.value, false);\n }\n }\n\n private handleOptionDisabledChange() {\n const currentOption = this.getOptionByValue(this.value);\n if (currentOption?.disabled && this.hasAnyEnabledOption()) {\n if (this.allowEmptySelection) {\n this.updateSelection('');\n return;\n }\n const firstSelectable = this.getFirstSelectableOption();\n if (firstSelectable) {\n this.updateSelection(firstSelectable.value);\n }\n }\n }\n\n override willUpdate(changed: PropertyValues): void {\n if (changed.has('value')) {\n this.updateSelection(this.value);\n }\n\n if (changed.has('type')) {\n this.options.forEach((opt) => {\n opt.type = this.type;\n });\n }\n\n if (changed.has('disabled')) {\n this.options.forEach((option) => {\n if (this.disabled) {\n option.setAttribute('data-group-disabled', 'true');\n option.disabled = true;\n } else {\n option.removeAttribute('data-group-disabled');\n const originalState =\n this._originalDisabledStates.get(option) || false;\n option.disabled = originalState;\n }\n });\n }\n }\n\n override updated(changedProperties: PropertyValues) {\n super.updated(changedProperties);\n\n const currentOption = this.getOptionByValue(this.value);\n if (currentOption?.disabled && this.hasAnyEnabledOption()) {\n if (this.allowEmptySelection) {\n this.updateSelection('');\n return;\n }\n const firstSelectable = this.getFirstSelectableOption();\n if (firstSelectable) {\n this.updateSelection(firstSelectable.value);\n }\n }\n }\n\n private updateDividers(): void {\n const last = this.options.length - 1;\n this.options.forEach((opt, idx) => {\n opt.showDivider = idx !== last;\n });\n }\n\n private onOptionSelected(e: Event): void {\n const {value} = (e as CustomEvent).detail;\n this.updateSelection(value, true, true);\n }\n\n override render() {\n const classes = {\n 'outer-wrapper': true,\n flat: this.type === ObcToggleButtonVerticalOptionType.flat,\n regular: this.type === ObcToggleButtonVerticalOptionType.regular,\n normal: this.type === ObcToggleButtonVerticalOptionType.normal,\n 'hug-width': this.hugWidth,\n disabled: this.disabled,\n };\n\n return html`\n <div class=${classMap(classes)}>\n <div class=\"wrapper\"><slot></slot></div>\n </div>\n `;\n }\n\n static override styles = unsafeCSS(style);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-toggle-button-vertical-group': ObcToggleButtonVerticalGroup;\n }\n}\n"],"names":[],"mappings":"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"}
@@ -79,6 +79,7 @@ export type ObcToggleSwitchInputEvent = CustomEvent<{
79
79
  *
80
80
  * @slot icon - Leading icon slot (shown when `hasIcon` is true)
81
81
  * @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
82
83
  */
83
84
  export declare class ObcToggleSwitch extends LitElement {
84
85
  /**
@@ -126,6 +127,7 @@ export declare class ObcToggleSwitch extends LitElement {
126
127
  * @fires input - Dispatched when the value of the input changes
127
128
  */
128
129
  private _tryChange;
130
+ private _fireChangeEvent;
129
131
  render(): import('lit-html').TemplateResult<1>;
130
132
  static styles: import('lit').CSSResult;
131
133
  }
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4EG;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;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IAsBT,MAAM;IAsCf,OAAgB,MAAM,0BAA6B;CACpD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,mBAAmB,EAAE,eAAe,CAAC;KACtC;CACF"}
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6EG;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;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IAsBlB,OAAO,CAAC,gBAAgB;IAQf,MAAM;IAuCf,OAAgB,MAAM,0BAA6B;CACpD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,mBAAmB,EAAE,eAAe,CAAC;KACtC;CACF"}
@@ -51,6 +51,13 @@ let ObcToggleSwitch = class extends LitElement {
51
51
  e.target.checked = this.checked;
52
52
  }
53
53
  }
54
+ _fireChangeEvent(e) {
55
+ if (this.disabled) {
56
+ e.preventDefault();
57
+ return;
58
+ }
59
+ this.dispatchEvent(new CustomEvent("change"));
60
+ }
54
61
  render() {
55
62
  return html`
56
63
  <label
@@ -75,6 +82,7 @@ let ObcToggleSwitch = class extends LitElement {
75
82
  .checked=${this.checked}
76
83
  ?disabled=${this.disabled}
77
84
  @input=${this._tryChange}
85
+ @change=${this._fireChangeEvent}
78
86
  />
79
87
  </div>
80
88
  </div>
@@ -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 */\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 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 />\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":";;;;;;;;;;;;;;;;AAyFO,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,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;AAAA;AAAA;AAAA,UAI5B,KAAK,mBACH,2CACA,OAAO;AAAA;AAAA;AAAA,EAGjB;AAGF;AAlHa,gBAiHK,SAAS,UAAU,cAAc;AA7GvB,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\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 */\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":";;;;;;;;;;;;;;;;AA0FO,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;"}
@@ -7,10 +7,36 @@ const compentStyle = css`
7
7
  .chart-container {
8
8
  width: 100%;
9
9
  height: 100%;
10
+ box-sizing: border-box;
10
11
  display: flex;
11
12
  align-items: center;
12
13
  justify-content: center;
13
14
  position: relative;
15
+
16
+ padding-bottom: 0.5px;
17
+
18
+ --dot-width: 6px;
19
+ --dot-radius: calc(var(--dot-width) / 2);
20
+ }
21
+
22
+ .chart-container.medium {
23
+ --dot-width: 8px;
24
+ }
25
+
26
+ .chart-container.large {
27
+ --dot-width: 10px;
28
+ }
29
+
30
+ .u-over {
31
+ position: absolute;
32
+ }
33
+
34
+ #chart {
35
+ position: absolute;
36
+ width: calc(100% - var(--dot-radius));
37
+ left: 0;
38
+ top: var(--dot-radius);
39
+ bottom: var(--dot-radius);
14
40
  }
15
41
 
16
42
  canvas {
@@ -22,11 +48,12 @@ canvas {
22
48
  }
23
49
 
24
50
  #dot {
51
+ box-sizing: border-box;
25
52
  position: absolute;
26
- width: 4px;
27
- height: 4px;
28
- right: -3px;
29
- bottom: -3px;
53
+ width: var(--dot-width);
54
+ height: var(--dot-width);
55
+ right: 0;
56
+ bottom: 0;
30
57
  border-radius: 50%;
31
58
  background: var(--element-neutral-color);
32
59
  border: 1px solid var(--border-silhouette-color);
@@ -37,25 +64,12 @@ canvas {
37
64
  background: var(--element-neutral-enhanced-color);
38
65
  }
39
66
 
40
- .medium #dot {
41
- width: 6px;
42
- height: 6px;
43
- right: -4px;
44
- bottom: -4px;
45
- }
46
-
47
- .large #dot {
48
- width: 8px;
49
- height: 8px;
50
- right: -5px;
51
- bottom: -5px;
52
- }
53
-
54
67
  #zero-line {
55
68
  position: absolute;
56
- width: 100%;
69
+ left: 0;
70
+ right: var(--dot-radius);
57
71
  height: 1px;
58
- bottom: -0.5px;
72
+ bottom: calc(var(--dot-radius) - 0.5px);
59
73
  background: var(--element-disabled-color);
60
74
  border-radius: 2px;
61
75
  }
@@ -1 +1 @@
1
- {"version":3,"file":"indicator-graph.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"indicator-graph.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"indicator-graph.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/indicator-graph/indicator-graph.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,cAAc,EAAkB,MAAM,KAAK,CAAC;AAMhE,oBAAY,qBAAqB;IAC/B,KAAK,UAAU;IACf,MAAM,WAAW;IACjB,KAAK,UAAU;CAChB;AAED,oBAAY,yBAAyB;IACnC,OAAO,YAAY;IACnB,QAAQ,aAAa;CACtB;AAGD,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,qBAAqB,CAAC;IAC7B,QAAQ,CAAC,EAAE,yBAAyB,CAAC;IACrC,CAAC,CAAC,EAAE;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,OAAO,CAAA;KAAC,CAAC;CAC1D;AAED;;;;;GAKG;AACH,qBACa,iBAAkB,SAAQ,UAAU;IAE/C,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAY;IAGtC,MAAM,EAAE,uBAAuB,CAAM;IAGrC,OAAO,CAAC,KAAK,CAAkB;IAG/B,OAAO,CAAC,CAAC,CAAiC;IAG1C,OAAO,CAAC,SAAS,CAAiC;IAElD,OAAO,CAAC,KAAK,CAAsB;IACnC,OAAO,CAAC,cAAc,CAA+B;IAErD,OAAO,CAAC,WAAW;IAKV,YAAY;IAmCZ,oBAAoB;IAQ7B,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,MAAM;IAed,OAAO,KAAK,cAAc,GAEzB;IAED,OAAO,KAAK,kBAAkB,GAE7B;IAED,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,eAAe;IASvB,aAAa;IAUb,OAAO,CAAC,OAAO;IAef,OAAO,CAAC,cAAc;IAab,OAAO,CAAC,iBAAiB,EAAE,cAAc;IAQzC,MAAM;IAsBf,OAAgB,MAAM,0BAA2B;CAClD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,qBAAqB,EAAE,iBAAiB,CAAC;KAC1C;CACF"}
1
+ {"version":3,"file":"indicator-graph.d.ts","sourceRoot":"","sources":["../../../src/navigation-instruments/indicator-graph/indicator-graph.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,cAAc,EAAkB,MAAM,KAAK,CAAC;AAMhE,oBAAY,qBAAqB;IAC/B,KAAK,UAAU;IACf,MAAM,WAAW;IACjB,KAAK,UAAU;CAChB;AAED,oBAAY,yBAAyB;IACnC,OAAO,YAAY;IACnB,QAAQ,aAAa;CACtB;AAGD,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,qBAAqB,CAAC;IAC7B,QAAQ,CAAC,EAAE,yBAAyB,CAAC;IACrC,CAAC,CAAC,EAAE;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,OAAO,CAAA;KAAC,CAAC;CAC1D;AAED;;;;;GAKG;AACH,qBACa,iBAAkB,SAAQ,UAAU;IAE/C,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAY;IAGtC,MAAM,EAAE,uBAAuB,CAAM;IAGrC,OAAO,CAAC,KAAK,CAAkB;IAG/B,OAAO,CAAC,CAAC,CAAiC;IAG1C,OAAO,CAAC,SAAS,CAAiC;IAElD,OAAO,CAAC,KAAK,CAAsB;IACnC,OAAO,CAAC,cAAc,CAA+B;IAErD,OAAO,CAAC,WAAW;IAKV,YAAY;IAmCZ,oBAAoB;IAQ7B,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,MAAM;IAed,OAAO,KAAK,cAAc,GAEzB;IAED,OAAO,KAAK,kBAAkB,GAE7B;IAED,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,eAAe;IASvB,aAAa;IAUb,OAAO,CAAC,OAAO;IAef,OAAO,CAAC,cAAc;IAab,OAAO,CAAC,iBAAiB,EAAE,cAAc;IAQzC,MAAM;IAuBf,OAAgB,MAAM,0BAA2B;CAClD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,qBAAqB,EAAE,iBAAiB,CAAC;KAC1C;CACF"}
@@ -165,6 +165,7 @@ let ObcIndicatorGraph = class extends LitElement {
165
165
  <div
166
166
  class="chart-container ${this._effectivePriority} ${this._effectiveSize}"
167
167
  >
168
+ <div id="chart"></div>
168
169
  <div
169
170
  id="zero-line"
170
171
  style="transform: translateY(${-(this.zeroLineY ?? 0)}px);
@@ -189,7 +190,7 @@ __decorateClass([
189
190
  property({ type: Object })
190
191
  ], ObcIndicatorGraph.prototype, "layout", 2);
191
192
  __decorateClass([
192
- query(".chart-container")
193
+ query("#chart")
193
194
  ], ObcIndicatorGraph.prototype, "chart", 2);
194
195
  __decorateClass([
195
196
  state()
@@ -1 +1 @@
1
- {"version":3,"file":"indicator-graph.js","sources":["../../../src/navigation-instruments/indicator-graph/indicator-graph.ts"],"sourcesContent":["import {LitElement, PropertyValues, html, unsafeCSS} from 'lit';\nimport {property, query, state} from 'lit/decorators.js';\nimport compentStyle from './indicator-graph.css?inline';\nimport uPlot from 'uplot';\nimport {customElement} from '../../decorator.js';\n\nexport enum ObcIndicatorGraphSize {\n small = 'small',\n medium = 'medium',\n large = 'large',\n}\n\nexport enum ObcIndicatorGraphPriority {\n regular = 'regular',\n enhanced = 'enhanced',\n}\n\n// showZeroLine is defaulted to true\nexport interface ObcIndicatorGraphLayout {\n size?: ObcIndicatorGraphSize;\n priority?: ObcIndicatorGraphPriority;\n y?: {min?: number; max?: number; showZeroLine?: boolean};\n}\n\n/**\n * @element obc-indicator-graph\n * @description A mini graph component\n *\n * @property {Array} data - The data to display in the graph, first array is the x values, second array is the y values\n */\n@customElement('obc-indicator-graph')\nexport class ObcIndicatorGraph extends LitElement {\n @property({type: Array})\n data: [number[], number[]] = [[], []];\n\n @property({type: Object})\n layout: ObcIndicatorGraphLayout = {};\n\n @query('.chart-container')\n private chart!: HTMLDivElement;\n\n @state()\n private y: number | undefined = undefined;\n\n @state()\n private zeroLineY: number | undefined = undefined;\n\n private uplot: uPlot | null = null;\n private resizeObserver: ResizeObserver | null = null;\n\n private getCssColor(name: string) {\n const color = getComputedStyle(this).getPropertyValue(name).trim();\n return color;\n }\n\n override firstUpdated() {\n const opts = {\n width: this.chart.clientWidth,\n height: this.chart.clientHeight,\n scales: {\n x: {time: false, show: false},\n y: {\n auto: true,\n show: false,\n range: this._range.bind(this),\n },\n },\n series: [\n {},\n {\n stroke: this._getStrokeColor(),\n width: this._getStrokeWidth(),\n points: {show: false},\n },\n ],\n axes: [\n {show: false},\n {ticks: {show: false}, show: false, grid: {show: false}},\n ],\n legend: {show: false},\n cursor: {show: false},\n };\n\n this.uplot = new uPlot(opts, this.data, this.chart);\n requestAnimationFrame(() => this.updateY());\n\n this.resizeObserver = new ResizeObserver(() => this.updateSize());\n this.resizeObserver.observe(this.chart);\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this.resizeObserver?.disconnect();\n this.resizeObserver = null;\n this.uplot?.destroy();\n this.uplot = null;\n }\n\n private updateSize() {\n if (!this.uplot) {\n return;\n }\n this.uplot.setSize({\n width: this.chart.clientWidth,\n height: this.chart.clientHeight,\n });\n this.updateY();\n }\n\n private _range(\n _self: uPlot,\n initMin: number,\n initMax: number,\n _scaleKey: string\n ): [number, number] {\n const {min: minY, max: maxY} = this.layout.y ?? {};\n const range = maxY ?? initMax - (minY ?? initMin);\n let min = minY ?? initMin - range * 0.1;\n if (minY === undefined && this.layout.y?.showZeroLine !== false) {\n min = Math.min(0, min);\n }\n return [min, maxY ?? initMax + range * 0.1] as [number, number];\n }\n\n private get _effectiveSize() {\n return this.layout.size ?? ObcIndicatorGraphSize.medium;\n }\n\n private get _effectivePriority() {\n return this.layout.priority ?? ObcIndicatorGraphPriority.regular;\n }\n\n private _getStrokeWidth() {\n switch (this._effectiveSize) {\n case ObcIndicatorGraphSize.small:\n return 1;\n case ObcIndicatorGraphSize.medium:\n return 1.5;\n case ObcIndicatorGraphSize.large:\n return 2;\n }\n }\n\n private _getStrokeColor() {\n switch (this._effectivePriority) {\n case ObcIndicatorGraphPriority.regular:\n return this.getCssColor('--element-neutral-color');\n case ObcIndicatorGraphPriority.enhanced:\n return this.getCssColor('--element-neutral-enhanced-color');\n }\n }\n\n updatePalette() {\n if (!this.uplot) {\n return;\n }\n const series = this.uplot.series[1];\n series.stroke = () => this._getStrokeColor();\n series.width = this._getStrokeWidth();\n this.uplot.redraw();\n }\n\n private updateY() {\n if (!this.uplot) {\n return;\n }\n const lastY = this.data[1][this.data[1].length - 1];\n // @ts-expect-error - valToPct is not a property of the Scale interface\n const yRatio = this.uplot.scales.y.valToPct(lastY);\n if (yRatio < 0 || yRatio > 1) {\n this.y = undefined;\n } else {\n this.y = yRatio * this.chart.clientHeight;\n }\n this.updateZeroLine();\n }\n\n private updateZeroLine() {\n if (!this.uplot) {\n return;\n }\n // @ts-expect-error - valToPct is not a property of the Scale interface\n const yRatio = this.uplot.scales.y.valToPct(0);\n if (yRatio < 0 || yRatio > 1) {\n this.zeroLineY = undefined;\n return;\n }\n this.zeroLineY = yRatio * this.chart.clientHeight;\n }\n\n override updated(changedProperties: PropertyValues) {\n if (changedProperties.has('data') || changedProperties.has('layout')) {\n this.updatePalette();\n this.uplot?.setData(this.data);\n requestAnimationFrame(() => this.updateY());\n }\n }\n\n override render() {\n return html`\n <div\n class=\"chart-container ${this._effectivePriority} ${this\n ._effectiveSize}\"\n >\n <div\n id=\"zero-line\"\n style=\"transform: translateY(${-(this.zeroLineY ?? 0)}px);\n display: ${this.zeroLineY !== undefined ? 'block' : 'none'};\n \"\n ></div>\n <div\n id=\"dot\"\n style=\"transform: translateY(${-(this.y ?? 0)}px);\n display: ${this.y !== undefined ? 'block' : 'none'};\n \"\n ></div>\n </div>\n `;\n }\n\n static override styles = unsafeCSS(compentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-indicator-graph': ObcIndicatorGraph;\n }\n}\n"],"names":["ObcIndicatorGraphSize","ObcIndicatorGraphPriority"],"mappings":"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"}
1
+ {"version":3,"file":"indicator-graph.js","sources":["../../../src/navigation-instruments/indicator-graph/indicator-graph.ts"],"sourcesContent":["import {LitElement, PropertyValues, html, unsafeCSS} from 'lit';\nimport {property, query, state} from 'lit/decorators.js';\nimport compentStyle from './indicator-graph.css?inline';\nimport uPlot from 'uplot';\nimport {customElement} from '../../decorator.js';\n\nexport enum ObcIndicatorGraphSize {\n small = 'small',\n medium = 'medium',\n large = 'large',\n}\n\nexport enum ObcIndicatorGraphPriority {\n regular = 'regular',\n enhanced = 'enhanced',\n}\n\n// showZeroLine is defaulted to true\nexport interface ObcIndicatorGraphLayout {\n size?: ObcIndicatorGraphSize;\n priority?: ObcIndicatorGraphPriority;\n y?: {min?: number; max?: number; showZeroLine?: boolean};\n}\n\n/**\n * @element obc-indicator-graph\n * @description A mini graph component\n *\n * @property {Array} data - The data to display in the graph, first array is the x values, second array is the y values\n */\n@customElement('obc-indicator-graph')\nexport class ObcIndicatorGraph extends LitElement {\n @property({type: Array})\n data: [number[], number[]] = [[], []];\n\n @property({type: Object})\n layout: ObcIndicatorGraphLayout = {};\n\n @query('#chart')\n private chart!: HTMLDivElement;\n\n @state()\n private y: number | undefined = undefined;\n\n @state()\n private zeroLineY: number | undefined = undefined;\n\n private uplot: uPlot | null = null;\n private resizeObserver: ResizeObserver | null = null;\n\n private getCssColor(name: string) {\n const color = getComputedStyle(this).getPropertyValue(name).trim();\n return color;\n }\n\n override firstUpdated() {\n const opts = {\n width: this.chart.clientWidth,\n height: this.chart.clientHeight,\n scales: {\n x: {time: false, show: false},\n y: {\n auto: true,\n show: false,\n range: this._range.bind(this),\n },\n },\n series: [\n {},\n {\n stroke: this._getStrokeColor(),\n width: this._getStrokeWidth(),\n points: {show: false},\n },\n ],\n axes: [\n {show: false},\n {ticks: {show: false}, show: false, grid: {show: false}},\n ],\n legend: {show: false},\n cursor: {show: false},\n };\n\n this.uplot = new uPlot(opts, this.data, this.chart);\n requestAnimationFrame(() => this.updateY());\n\n this.resizeObserver = new ResizeObserver(() => this.updateSize());\n this.resizeObserver.observe(this.chart);\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this.resizeObserver?.disconnect();\n this.resizeObserver = null;\n this.uplot?.destroy();\n this.uplot = null;\n }\n\n private updateSize() {\n if (!this.uplot) {\n return;\n }\n this.uplot.setSize({\n width: this.chart.clientWidth,\n height: this.chart.clientHeight,\n });\n this.updateY();\n }\n\n private _range(\n _self: uPlot,\n initMin: number,\n initMax: number,\n _scaleKey: string\n ): [number, number] {\n const {min: minY, max: maxY} = this.layout.y ?? {};\n const range = maxY ?? initMax - (minY ?? initMin);\n let min = minY ?? initMin - range * 0.1;\n if (minY === undefined && this.layout.y?.showZeroLine !== false) {\n min = Math.min(0, min);\n }\n return [min, maxY ?? initMax + range * 0.1] as [number, number];\n }\n\n private get _effectiveSize() {\n return this.layout.size ?? ObcIndicatorGraphSize.medium;\n }\n\n private get _effectivePriority() {\n return this.layout.priority ?? ObcIndicatorGraphPriority.regular;\n }\n\n private _getStrokeWidth() {\n switch (this._effectiveSize) {\n case ObcIndicatorGraphSize.small:\n return 1;\n case ObcIndicatorGraphSize.medium:\n return 1.5;\n case ObcIndicatorGraphSize.large:\n return 2;\n }\n }\n\n private _getStrokeColor() {\n switch (this._effectivePriority) {\n case ObcIndicatorGraphPriority.regular:\n return this.getCssColor('--element-neutral-color');\n case ObcIndicatorGraphPriority.enhanced:\n return this.getCssColor('--element-neutral-enhanced-color');\n }\n }\n\n updatePalette() {\n if (!this.uplot) {\n return;\n }\n const series = this.uplot.series[1];\n series.stroke = () => this._getStrokeColor();\n series.width = this._getStrokeWidth();\n this.uplot.redraw();\n }\n\n private updateY() {\n if (!this.uplot) {\n return;\n }\n const lastY = this.data[1][this.data[1].length - 1];\n // @ts-expect-error - valToPct is not a property of the Scale interface\n const yRatio = this.uplot.scales.y.valToPct(lastY);\n if (yRatio < 0 || yRatio > 1) {\n this.y = undefined;\n } else {\n this.y = yRatio * this.chart.clientHeight;\n }\n this.updateZeroLine();\n }\n\n private updateZeroLine() {\n if (!this.uplot) {\n return;\n }\n // @ts-expect-error - valToPct is not a property of the Scale interface\n const yRatio = this.uplot.scales.y.valToPct(0);\n if (yRatio < 0 || yRatio > 1) {\n this.zeroLineY = undefined;\n return;\n }\n this.zeroLineY = yRatio * this.chart.clientHeight;\n }\n\n override updated(changedProperties: PropertyValues) {\n if (changedProperties.has('data') || changedProperties.has('layout')) {\n this.updatePalette();\n this.uplot?.setData(this.data);\n requestAnimationFrame(() => this.updateY());\n }\n }\n\n override render() {\n return html`\n <div\n class=\"chart-container ${this._effectivePriority} ${this\n ._effectiveSize}\"\n >\n <div id=\"chart\"></div>\n <div\n id=\"zero-line\"\n style=\"transform: translateY(${-(this.zeroLineY ?? 0)}px);\n display: ${this.zeroLineY !== undefined ? 'block' : 'none'};\n \"\n ></div>\n <div\n id=\"dot\"\n style=\"transform: translateY(${-(this.y ?? 0)}px);\n display: ${this.y !== undefined ? 'block' : 'none'};\n \"\n ></div>\n </div>\n `;\n }\n\n static override styles = unsafeCSS(compentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-indicator-graph': ObcIndicatorGraph;\n }\n}\n"],"names":["ObcIndicatorGraphSize","ObcIndicatorGraphPriority"],"mappings":"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"}
@@ -8,6 +8,10 @@ const compentStyle = css`
8
8
  box-sizing: border-box;
9
9
  }
10
10
 
11
+ :host {
12
+ overflow: hidden;
13
+ }
14
+
11
15
  .label {
12
16
  font-family: var(--global-typography-font-family);
13
17
  font-weight: var(--global-typography-ui-body-font-weight);
@@ -1 +1 @@
1
- {"version":3,"file":"watch.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"watch.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oicl/openbridge-webcomponents-full-bundle",
3
- "version": "2.0.0-next.77",
3
+ "version": "2.0.0-next.79",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
File without changes
@@ -42,6 +42,14 @@ export type ObcPaginationNavigateEvent = CustomEvent<{
42
42
  currentPage: number;
43
43
  }>;
44
44
 
45
+ /**
46
+ * Event fired when a page is selected.
47
+ * @event
48
+ */
49
+ export type ObcPaginationSelectPageEvent = CustomEvent<{
50
+ page: number;
51
+ }>;
52
+
45
53
  /**
46
54
  * `obc-pagination` – page navigation component for traversing multi-page content.
47
55
  *
@@ -97,9 +105,11 @@ export type ObcPaginationNavigateEvent = CustomEvent<{
97
105
  *
98
106
  * - `value` – Fired when the current page changes (via user interaction).
99
107
  * - `navigate` – Fired when a navigation arrow (first, previous, next, last) is clicked.
108
+ * - `select-page` – Fired when a specific page is selected.
100
109
  *
101
110
  * @fires value {ObcPaginationValueChangeEvent} Emitted whenever the current page changes.
102
111
  * @fires navigate {ObcPaginationNavigateEvent} Emitted when a navigation arrow is clicked.
112
+ * @fires select-page {ObcPaginationSelectPageEvent} Emitted when a specific page is selected.
103
113
  */
104
114
  @customElement('obc-pagination')
105
115
  export class ObcPagination extends LitElement {
@@ -195,13 +205,18 @@ export class ObcPagination extends LitElement {
195
205
 
196
206
  private setCurrentPage(newPage: number) {
197
207
  const page = Math.max(1, Math.min(newPage, this.validatedPages));
198
- if (page === this.currentPage) return;
208
+ if (page === this.currentPage) {
209
+ return false;
210
+ }
211
+
199
212
  this.currentPage = page;
200
213
  this.dispatchEvent(
201
214
  new CustomEvent('value', {
202
215
  detail: {value: page},
203
216
  }) as ObcPaginationValueChangeEvent
204
217
  );
218
+
219
+ return true;
205
220
  }
206
221
 
207
222
  private dispatchNavigateEvent(
@@ -215,7 +230,15 @@ export class ObcPagination extends LitElement {
215
230
  }
216
231
 
217
232
  private handlePageChange = (event: CustomEvent<{value: string}>) => {
218
- this.setCurrentPage(Number(event.detail.value));
233
+ const success = this.setCurrentPage(Number(event.detail.value));
234
+
235
+ if (success) {
236
+ this.dispatchEvent(
237
+ new CustomEvent('select-page', {
238
+ detail: {page: Number(event.detail.value)},
239
+ }) as ObcPaginationSelectPageEvent
240
+ );
241
+ }
219
242
  };
220
243
 
221
244
  private handleFirstClick = () => {
@@ -26,6 +26,12 @@ export enum ObcSliderVariant {
26
26
  */
27
27
  export type ObcSliderValueEvent = CustomEvent<number>;
28
28
 
29
+ /**
30
+ * Custom event type for slider change event (fired after user interaction completes).
31
+ * The event detail contains the new numeric value.
32
+ */
33
+ export type ObcSliderChangeEvent = CustomEvent<number>;
34
+
29
35
  /**
30
36
  * `<obc-slider>` – A horizontal slider component for selecting a numeric value within a defined range.
31
37
  *
@@ -85,7 +91,8 @@ export type ObcSliderValueEvent = CustomEvent<number>;
85
91
  * ---
86
92
  *
87
93
  * ### Events
88
- * - `value` – Fired when the slider value changes, either by user interaction or programmatically. The event detail contains the new value as a number.
94
+ * - `value` – Fired continuously when the slider value changes during user interaction or programmatically. The event detail contains the new value as a number.
95
+ * - `change` – Fired only after user interaction completes (mouse/touch release or button click). The event detail contains the new value as a number.
89
96
  *
90
97
  * ---
91
98
  *
@@ -121,6 +128,7 @@ export type ObcSliderValueEvent = CustomEvent<number>;
121
128
  * @slot icon-right - Slot for the right icon button (shown when `hasRightIcon` is true)
122
129
  * @attr hugcontainer - If set, the slider will not have any spacing between the slider icons and the container
123
130
  * @fires value {ObcSliderValueEvent} - Fired when the value is changed
131
+ * @fires change {ObcSliderChangeEvent} - Fired when user interaction completes and value has changed
124
132
  */
125
133
  @customElement('obc-slider')
126
134
  export class ObcSlider extends LitElement {
@@ -233,12 +241,24 @@ export class ObcSlider extends LitElement {
233
241
  this.dispatchEvent(new CustomEvent('value', {detail: this.value}));
234
242
  }
235
243
 
244
+ /**
245
+ * Fires the `change` event with the current value.
246
+ *
247
+ * @fires change
248
+ */
249
+ private fireChangeEvent() {
250
+ this.dispatchEvent(
251
+ new CustomEvent('change', {detail: this.value}) as ObcSliderChangeEvent
252
+ );
253
+ }
254
+
236
255
  /**
237
256
  * Decrements the value by `stepClick` when the left icon button is clicked.
238
257
  */
239
258
  onReduceClick() {
240
259
  if (this.disabled) return;
241
260
  this.onInput(Math.max(this.value - this.stepClick, this.min));
261
+ this.fireChangeEvent();
242
262
  }
243
263
 
244
264
  /**
@@ -247,6 +267,7 @@ export class ObcSlider extends LitElement {
247
267
  onIncreaseClick() {
248
268
  if (this.disabled) return;
249
269
  this.onInput(Math.min(this.value + this.stepClick, this.max));
270
+ this.fireChangeEvent();
250
271
  }
251
272
 
252
273
  private get slider(): HTMLInputElement {
@@ -329,6 +350,7 @@ export class ObcSlider extends LitElement {
329
350
  window.removeEventListener('mousemove', this.onWindowMouseMove);
330
351
  window.removeEventListener('mouseup', this.onWindowMouseUp);
331
352
  this.stopAnimation();
353
+ this.fireChangeEvent();
332
354
  }
333
355
 
334
356
  private onTouchEnd() {
@@ -336,6 +358,7 @@ export class ObcSlider extends LitElement {
336
358
  window.removeEventListener('touchmove', this.onWindowTouchMove);
337
359
  window.removeEventListener('touchend', this.onWindowTouchEnd);
338
360
  this.stopAnimation();
361
+ this.fireChangeEvent();
339
362
  }
340
363
 
341
364
  private updateTargetValue(e: MouseEvent | TouchEvent) {
@@ -454,6 +477,9 @@ export class ObcSlider extends LitElement {
454
477
  this.value = Number((event.target as HTMLInputElement).value);
455
478
  this.dispatchEvent(new CustomEvent('value', {detail: this.value}));
456
479
  }}
480
+ @change=${() => {
481
+ this.fireChangeEvent();
482
+ }}
457
483
  @mousedown=${this.onMouseDown}
458
484
  @touchstart=${this.onTouchStart}
459
485
  @mousemove=${this.onMouseMove}