@oicl/openbridge-webcomponents 2.0.0-next.78 → 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 (32) hide show
  1. package/bundle/openbridge-webcomponents.bundle.js +77 -8
  2. package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
  3. package/custom-elements.json +77 -5
  4. package/dist/components/input/input.d.ts +1 -0
  5. package/dist/components/input/input.d.ts.map +1 -0
  6. package/dist/components/input/input.js +2 -0
  7. package/dist/components/input/input.js.map +1 -0
  8. package/dist/components/pagination/pagination.d.ts +9 -0
  9. package/dist/components/pagination/pagination.d.ts.map +1 -1
  10. package/dist/components/pagination/pagination.js +12 -2
  11. package/dist/components/pagination/pagination.js.map +1 -1
  12. package/dist/components/slider/slider.d.ts +14 -1
  13. package/dist/components/slider/slider.d.ts.map +1 -1
  14. package/dist/components/slider/slider.js +17 -0
  15. package/dist/components/slider/slider.js.map +1 -1
  16. package/dist/components/slider-double/slider-double.d.ts +17 -1
  17. package/dist/components/slider-double/slider-double.d.ts.map +1 -1
  18. package/dist/components/slider-double/slider-double.js +15 -0
  19. package/dist/components/slider-double/slider-double.js.map +1 -1
  20. package/dist/components/toggle-button-group/toggle-button-group.d.ts +4 -0
  21. package/dist/components/toggle-button-group/toggle-button-group.d.ts.map +1 -1
  22. package/dist/components/toggle-button-group/toggle-button-group.js +15 -3
  23. package/dist/components/toggle-button-group/toggle-button-group.js.map +1 -1
  24. package/dist/components/toggle-button-vertical-group/toggle-button-vertical-group.d.ts +4 -0
  25. package/dist/components/toggle-button-vertical-group/toggle-button-vertical-group.d.ts.map +1 -1
  26. package/dist/components/toggle-button-vertical-group/toggle-button-vertical-group.js +10 -3
  27. package/dist/components/toggle-button-vertical-group/toggle-button-vertical-group.js.map +1 -1
  28. package/dist/components/toggle-switch/toggle-switch.d.ts +2 -0
  29. package/dist/components/toggle-switch/toggle-switch.d.ts.map +1 -1
  30. package/dist/components/toggle-switch/toggle-switch.js +8 -0
  31. package/dist/components/toggle-switch/toggle-switch.js.map +1 -1
  32. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"slider.js","sources":["../../../src/components/slider/slider.ts"],"sourcesContent":["import {LitElement, html, unsafeCSS} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport {ifDefined} from 'lit/directives/if-defined.js';\nimport {styleMap} from 'lit/directives/style-map.js';\nimport componentStyle from './slider.css?inline';\nimport '../icon-button/icon-button.js';\nimport {classMap} from 'lit/directives/class-map.js';\nimport {customElement} from '../../decorator.js';\n\n/**\n * Enum of slider visual and interaction variants.\n *\n * - `normal`: Standard slider appearance and interaction.\n * - `enhanced`: Visually prominent slider with increased track and thumb size for easier manipulation.\n * - `no-input`: Read-only display; disables user input and interaction.\n */\nexport enum ObcSliderVariant {\n Normal = 'normal',\n Enhanced = 'enhanced',\n NoInput = 'no-input',\n}\n\n/**\n * Custom event type for slider value changes.\n * The event detail contains the new numeric value.\n */\nexport type ObcSliderValueEvent = CustomEvent<number>;\n\n/**\n * `<obc-slider>` – A horizontal slider component for selecting a numeric value within a defined range.\n *\n * Provides a visual and interactive way for users to adjust values such as volume, brightness, or other continuous settings. The slider supports optional step increments, left/right icon buttons for quick adjustments, and can be configured for read-only display or enhanced visual prominence.\n *\n * Appears as a horizontal track with a draggable thumb, and may include optional icon buttons on either side for increment/decrement actions. The component can be used for both direct manipulation (dragging the thumb) and discrete changes (via buttons).\n *\n * ---\n *\n * ### Features\n * - **Variants:**\n * - **Normal:** Standard slider with a slim track and thumb.\n * - **Enhanced:** Larger track and thumb for improved accessibility and visual emphasis.\n * - **No Input:** Read-only mode; disables all user interaction and presents the current value visually.\n * - **Value Range:** Supports configurable `min`, `max`, and `step` properties for precise control over allowed values.\n * - **Step Buttons:** Optional left and right icon buttons allow users to increment or decrement the value by a defined step (`stepClick`).\n * - **Icons:** Custom icons can be slotted into the left and right button positions for contextual meaning (e.g., `<obi-arrow></obi-arrow>, <obi-placeholder></obi-placeholder>`).\n * - **Seeking:** When `allowSeeking` is enabled, users can click or drag along the track to set the value, with smooth animated transitions based on `seekingSpeed`.\n * - **Hug Container:** The `hugcontainer` attribute removes spacing between the slider and its icon buttons, allowing for a compact layout.\n * - **Accessibility:** Underlying input is a native `<input type=\"range\">` for keyboard and screen reader support.\n *\n * ---\n *\n * ### Usage Guidelines\n * Use `obc-slider` when you need users to select or adjust a value within a continuous or stepped range, such as for volume, brightness, or similar controls. The enhanced variant is suitable for scenarios where the slider is a primary control or needs to be more visually prominent. The no-input variant is ideal for displaying a value without allowing user changes.\n *\n * - For discrete, step-based changes, provide `step` and/or `stepClick` values.\n * - Use left/right icons to clarify the meaning of the adjustment (e.g., low/high, decrease/increase).\n * - Enable `allowSeeking` for scenarios where users should be able to jump to a specific value by clicking the track.\n * - Use `hugcontainer` when the slider should visually connect tightly with its icon buttons.\n *\n * **TODO(designer):** Clarify recommended use cases for each variant and when to use `allowSeeking` vs. standard interaction.\n *\n * ---\n *\n * ### Slots\n *\n * | Slot Name | Renders When... | Purpose |\n * |-------------|---------------------------|--------------------------------------------|\n * | icon-left | `hasLeftIcon` is true | Icon/button for decrement action |\n * | icon-right | `hasRightIcon` is true | Icon/button for increment action |\n *\n * ---\n *\n * ### Properties and Attributes\n * - `value` (number): Current slider value. Updates as the user interacts.\n * - `min` (number): Minimum allowed value (default: 0).\n * - `max` (number): Maximum allowed value (default: 100).\n * - `step` (number): Step granularity for value changes (optional).\n * - `stepClick` (number): Amount to increment/decrement when clicking icon buttons (default: 10).\n * - `variant` (ObcSliderVariant): Visual/interaction style (`normal`, `enhanced`, `no-input`). Default: `normal`.\n * - `hasLeftIcon`/`hasRightIcon` (boolean): Show icon button on left/right.\n * - `allowSeeking` (boolean): Enables animated seeking to clicked value on the track.\n * - `seekingSpeed` (number): Animation speed for seeking (default: 1/3; higher is faster).\n * - `hugcontainer` (attribute): Removes spacing between slider and icon buttons for a compact layout.\n *\n * ---\n *\n * ### Events\n * - `value` – Fired when the slider value changes, either by user interaction or programmatically. The event detail contains the new value as a number.\n *\n * ---\n *\n * ### Best Practices & Constraints\n * - Only use `no-input` variant for read-only display; interactive controls should use `normal` or `enhanced`.\n * - For accessibility, ensure the slider has a visible label or context.\n * - Use step values that make sense for the range (e.g., avoid step=0.01 for a 0–10 range unless fine granularity is needed).\n * - When using icon buttons, provide icons that clearly indicate their function.\n * - The slider is horizontal only; for vertical sliders, use a different component.\n *\n * ---\n *\n * ### Example\n *\n * ```html\n * <obc-slider\n * value=\"40\"\n * min=\"0\"\n * max=\"100\"\n * step=\"10\"\n * haslefticon\n * hasrighticon\n * variant=\"enhanced\"\n * >\n * <obi-arrow slot=\"icon-left\"></obi-arrow>\n * <obi-arrow slot=\"icon-right\"></obi-arrow>\n * </obc-slider>\n * ```\n *\n * In this example, the slider allows selection from 0 to 100 in steps of 10, with left/right arrow icons for quick adjustments.\n *\n * @slot icon-left - Slot for the left icon button (shown when `hasLeftIcon` is true)\n * @slot icon-right - Slot for the right icon button (shown when `hasRightIcon` is true)\n * @attr hugcontainer - If set, the slider will not have any spacing between the slider icons and the container\n * @fires value {ObcSliderValueEvent} - Fired when the value is changed\n */\n@customElement('obc-slider')\nexport class ObcSlider extends LitElement {\n /**\n * The current value of the slider.\n *\n * Updates as the user drags the thumb, clicks the track (if `allowSeeking`), or uses the increment/decrement buttons.\n */\n @property({type: Number}) value = 50;\n\n /**\n * The minimum allowed value for the slider.\n *\n * Default is 0.\n */\n @property({type: Number}) min = 0;\n\n /**\n * The maximum allowed value for the slider.\n *\n * Default is 100.\n */\n @property({type: Number}) max = 100;\n\n /**\n * The step granularity for slider value changes.\n *\n * If set, the slider will snap to multiples of this value between min and max.\n * Optional; if not set, the slider is continuous.\n */\n @property({type: Number}) step: number | undefined;\n\n /**\n * The amount to increment or decrement the value when clicking the left/right icon buttons.\n *\n * Default is 10.\n * @availableWhen hasLeftIcon==true || hasRightIcon==true\n */\n @property({type: Number}) stepClick = 10;\n\n /**\n * The visual and interaction style of the slider.\n *\n * - `normal`: Standard appearance.\n * - `enhanced`: Larger track and thumb for emphasis.\n * - `no-input`: Read-only; disables all user input.\n *\n * Default is `normal`.\n */\n @property({type: String}) variant: ObcSliderVariant = ObcSliderVariant.Normal;\n\n /**\n * Whether to display a left icon button for decrementing the value.\n *\n * When true, the `icon-left` slot is rendered as a button.\n */\n @property({type: Boolean}) hasLeftIcon = false;\n\n /**\n * Whether to display a right icon button for incrementing the value.\n *\n * When true, the `icon-right` slot is rendered as a button.\n */\n @property({type: Boolean}) hasRightIcon = false;\n\n /**\n * Enables animated seeking: clicking or dragging along the track will set the value to the clicked position, animating smoothly.\n *\n * Default is false.\n * @availableWhen variant!=no-input && disabled==false\n */\n @property({type: Boolean}) allowSeeking = false;\n\n /**\n * The speed of the smooth animation that moves the value to the clicked position (used when `allowSeeking` is false).\n *\n * Expressed as the inverse of seconds to go from min to max (e.g., 1/3 means 3 seconds for full range).\n * Default is 1/3.\n * @availableWhen allowSeeking==false && variant!=no-input && disabled==false\n */\n @property({type: Number}) seekingSpeed = 1 / 3;\n\n @property({type: Boolean}) disabled = false;\n\n private get ratio(): number {\n const range = this.max - this.min;\n if (!Number.isFinite(range) || range <= 0) return 0;\n const ratio = (this.value - this.min) / range;\n if (!Number.isFinite(ratio)) return 0;\n return Math.max(0, Math.min(1, ratio));\n }\n\n private animationFrame: number | null = null;\n private isMouseDown = false;\n private isTouchActive = false;\n private targetValue = 0;\n private isDragging = false;\n private animationStartTime: number | null = null;\n private animationStartValue: number = 0;\n\n /**\n * Handles input changes from the slider or buttons.\n * Fires the `value` event with the new value.\n *\n * @param value - The new value to set.\n * @fires value\n */\n onInput(value: number) {\n this.value = value;\n this.dispatchEvent(new CustomEvent('value', {detail: this.value}));\n }\n\n /**\n * Decrements the value by `stepClick` when the left icon button is clicked.\n */\n onReduceClick() {\n if (this.disabled) return;\n this.onInput(Math.max(this.value - this.stepClick, this.min));\n }\n\n /**\n * Increments the value by `stepClick` when the right icon button is clicked.\n */\n onIncreaseClick() {\n if (this.disabled) return;\n this.onInput(Math.min(this.value + this.stepClick, this.max));\n }\n\n private get slider(): HTMLInputElement {\n return this.renderRoot.querySelector('input[type=\"range\"]')!;\n }\n\n private isClickingThumb(e: MouseEvent | TouchEvent) {\n const rect = this.slider.getBoundingClientRect();\n const left = rect.left + 24;\n const width = rect.width - 48;\n const thumbWidth = 48;\n const ratioValue = this.ratio;\n const thumbCenter = left + width * ratioValue;\n\n let clientX: number;\n if ('touches' in e) {\n clientX = e.touches[0].clientX;\n } else {\n clientX = e.clientX;\n }\n\n const isNearThumb = Math.abs(clientX - thumbCenter) <= thumbWidth / 2;\n return isNearThumb;\n }\n\n private onMouseDown(e: MouseEvent) {\n if (this.variant === ObcSliderVariant.NoInput || this.disabled) return;\n if (this.isClickingThumb(e)) return;\n this.isMouseDown = true;\n this.updateTargetValue(e);\n e.preventDefault();\n window.addEventListener('mousemove', this.onWindowMouseMove);\n window.addEventListener('mouseup', this.onWindowMouseUp);\n this.startAnimation();\n }\n\n private onTouchStart(e: TouchEvent) {\n if (this.variant === ObcSliderVariant.NoInput || this.disabled) return;\n if (this.isClickingThumb(e)) return;\n this.isTouchActive = true;\n this.updateTargetValue(e);\n e.preventDefault();\n window.addEventListener('touchmove', this.onWindowTouchMove, {\n passive: false,\n });\n window.addEventListener('touchend', this.onWindowTouchEnd);\n this.startAnimation();\n }\n\n private onWindowMouseMove = (e: MouseEvent) => {\n this.onMouseMove(e);\n };\n\n private onWindowMouseUp = () => {\n this.onMouseUp();\n };\n\n private onWindowTouchMove = (e: TouchEvent) => {\n this.onTouchMove(e);\n };\n\n private onWindowTouchEnd = () => {\n this.onTouchEnd();\n };\n\n private onMouseMove(e: MouseEvent) {\n if (this.isMouseDown) {\n this.updateTargetValue(e);\n }\n }\n\n private onTouchMove(e: TouchEvent) {\n if (this.isTouchActive) {\n this.updateTargetValue(e);\n }\n }\n\n private onMouseUp() {\n this.isMouseDown = false;\n window.removeEventListener('mousemove', this.onWindowMouseMove);\n window.removeEventListener('mouseup', this.onWindowMouseUp);\n this.stopAnimation();\n }\n\n private onTouchEnd() {\n this.isTouchActive = false;\n window.removeEventListener('touchmove', this.onWindowTouchMove);\n window.removeEventListener('touchend', this.onWindowTouchEnd);\n this.stopAnimation();\n }\n\n private updateTargetValue(e: MouseEvent | TouchEvent) {\n const rect = this.slider.getBoundingClientRect();\n const left = rect.left + 24;\n const width = rect.width - 48;\n const x = e instanceof MouseEvent ? e.clientX : e.touches[0].clientX;\n const percent = (x - left) / width;\n const min = parseFloat(this.slider.min);\n const max = parseFloat(this.slider.max);\n const unroundedValue = min + (max - min) * percent;\n if (this.step) {\n this.targetValue = Math.round(unroundedValue / this.step) * this.step;\n } else {\n this.targetValue = unroundedValue;\n }\n }\n\n private startAnimation() {\n this.isDragging = this.allowSeeking;\n this.animationStartTime = performance.now();\n this.animationStartValue = parseFloat(this.slider.value);\n const min = parseFloat(this.slider.min);\n const max = parseFloat(this.slider.max);\n const step = this.step;\n const duration = (1 / this.seekingSpeed) * 1000; // ms\n const direction = this.targetValue > this.animationStartValue ? 1 : -1;\n\n const animate = () => {\n let nextValue = this.targetValue;\n if (!this.isDragging) {\n const now = performance.now();\n const elapsed = now - (this.animationStartTime ?? now);\n const range = Math.abs(max - min);\n // How much of the range should be covered by now\n const expectedProgress = Math.min(elapsed / duration, 1);\n const expectedValue =\n this.animationStartValue + direction * range * expectedProgress;\n // Snap to step\n if (direction > 0) {\n nextValue =\n step === undefined\n ? expectedValue\n : Math.ceil((expectedValue - min) / step) * step + min;\n nextValue = Math.min(this.targetValue, nextValue);\n } else {\n nextValue =\n step === undefined\n ? expectedValue\n : Math.floor((expectedValue - min) / step) * step + min;\n nextValue = Math.max(this.targetValue, nextValue);\n }\n }\n // Only update if value actually changes\n if (parseFloat(this.slider.value) !== nextValue) {\n this.slider.value = String(nextValue);\n this.slider.dispatchEvent(new Event('input'));\n }\n // Continue animating if not at target\n if (\n (direction > 0 && nextValue < this.targetValue) ||\n (direction < 0 && nextValue > this.targetValue)\n ) {\n this.animationFrame = requestAnimationFrame(animate);\n } else if (this.isMouseDown || this.isTouchActive) {\n // If mouse or touch is still active, wait for new target\n this.animationStartTime = performance.now();\n this.animationStartValue = parseFloat(this.slider.value);\n this.animationFrame = requestAnimationFrame(animate);\n this.isDragging = true;\n }\n };\n\n this.animationFrame = requestAnimationFrame(animate);\n }\n\n private stopAnimation() {\n if (this.animationFrame !== null) {\n cancelAnimationFrame(this.animationFrame);\n this.animationFrame = null;\n }\n }\n\n override render() {\n return html`\n ${this.hasLeftIcon\n ? html` <obc-icon-button\n ?disabled=${this.disabled}\n @click=${this.onReduceClick}\n variant=\"normal\"\n >\n <slot name=\"icon-left\"></slot>\n </obc-icon-button>`\n : null}\n <div\n class=${classMap({\n wrapper: true,\n [this.variant]: true,\n disabled: this.disabled,\n })}\n style=${styleMap({\n '--_ratio': String(this.ratio),\n })}\n >\n <div class=\"track\"></div>\n <input\n type=\"range\"\n min=${this.min}\n max=${this.max}\n step=${ifDefined(this.step)}\n .value=${this.value.toString()}\n ?disabled=${this.variant === ObcSliderVariant.NoInput ||\n this.disabled}\n class=\"slider\"\n @input=${(event: Event) => {\n this.value = Number((event.target as HTMLInputElement).value);\n this.dispatchEvent(new CustomEvent('value', {detail: this.value}));\n }}\n @mousedown=${this.onMouseDown}\n @touchstart=${this.onTouchStart}\n @mousemove=${this.onMouseMove}\n @touchmove=${this.onTouchMove}\n @mouseup=${this.onMouseUp}\n @touchend=${this.onTouchEnd}\n />\n <div\n class=\"interactive-track-hover\"\n @mousedown=${this.onMouseDown}\n @touchstart=${this.onTouchStart}\n @mousemove=${this.onMouseMove}\n @touchmove=${this.onTouchMove}\n @mouseup=${this.onMouseUp}\n @touchend=${this.onTouchEnd}\n ></div>\n <div\n class=\"container-hover\"\n @mousedown=${this.onMouseDown}\n @touchstart=${this.onTouchStart}\n @mousemove=${this.onMouseMove}\n @touchmove=${this.onTouchMove}\n @mouseup=${this.onMouseUp}\n @touchend=${this.onTouchEnd}\n ></div>\n <div class=\"interactive-track\"></div>\n <div class=\"thumb\"></div>\n </div>\n ${this.hasRightIcon\n ? html`<obc-icon-button\n ?disabled=${this.disabled}\n @click=${this.onIncreaseClick}\n variant=\"normal\"\n >\n <slot name=\"icon-right\"></slot>\n </obc-icon-button>`\n : null}\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-slider': ObcSlider;\n }\n}\n"],"names":["ObcSliderVariant"],"mappings":"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"}
1
+ {"version":3,"file":"slider.js","sources":["../../../src/components/slider/slider.ts"],"sourcesContent":["import {LitElement, html, unsafeCSS} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport {ifDefined} from 'lit/directives/if-defined.js';\nimport {styleMap} from 'lit/directives/style-map.js';\nimport componentStyle from './slider.css?inline';\nimport '../icon-button/icon-button.js';\nimport {classMap} from 'lit/directives/class-map.js';\nimport {customElement} from '../../decorator.js';\n\n/**\n * Enum of slider visual and interaction variants.\n *\n * - `normal`: Standard slider appearance and interaction.\n * - `enhanced`: Visually prominent slider with increased track and thumb size for easier manipulation.\n * - `no-input`: Read-only display; disables user input and interaction.\n */\nexport enum ObcSliderVariant {\n Normal = 'normal',\n Enhanced = 'enhanced',\n NoInput = 'no-input',\n}\n\n/**\n * Custom event type for slider value changes.\n * The event detail contains the new numeric value.\n */\nexport type ObcSliderValueEvent = CustomEvent<number>;\n\n/**\n * Custom event type for slider change event (fired after user interaction completes).\n * The event detail contains the new numeric value.\n */\nexport type ObcSliderChangeEvent = CustomEvent<number>;\n\n/**\n * `<obc-slider>` – A horizontal slider component for selecting a numeric value within a defined range.\n *\n * Provides a visual and interactive way for users to adjust values such as volume, brightness, or other continuous settings. The slider supports optional step increments, left/right icon buttons for quick adjustments, and can be configured for read-only display or enhanced visual prominence.\n *\n * Appears as a horizontal track with a draggable thumb, and may include optional icon buttons on either side for increment/decrement actions. The component can be used for both direct manipulation (dragging the thumb) and discrete changes (via buttons).\n *\n * ---\n *\n * ### Features\n * - **Variants:**\n * - **Normal:** Standard slider with a slim track and thumb.\n * - **Enhanced:** Larger track and thumb for improved accessibility and visual emphasis.\n * - **No Input:** Read-only mode; disables all user interaction and presents the current value visually.\n * - **Value Range:** Supports configurable `min`, `max`, and `step` properties for precise control over allowed values.\n * - **Step Buttons:** Optional left and right icon buttons allow users to increment or decrement the value by a defined step (`stepClick`).\n * - **Icons:** Custom icons can be slotted into the left and right button positions for contextual meaning (e.g., `<obi-arrow></obi-arrow>, <obi-placeholder></obi-placeholder>`).\n * - **Seeking:** When `allowSeeking` is enabled, users can click or drag along the track to set the value, with smooth animated transitions based on `seekingSpeed`.\n * - **Hug Container:** The `hugcontainer` attribute removes spacing between the slider and its icon buttons, allowing for a compact layout.\n * - **Accessibility:** Underlying input is a native `<input type=\"range\">` for keyboard and screen reader support.\n *\n * ---\n *\n * ### Usage Guidelines\n * Use `obc-slider` when you need users to select or adjust a value within a continuous or stepped range, such as for volume, brightness, or similar controls. The enhanced variant is suitable for scenarios where the slider is a primary control or needs to be more visually prominent. The no-input variant is ideal for displaying a value without allowing user changes.\n *\n * - For discrete, step-based changes, provide `step` and/or `stepClick` values.\n * - Use left/right icons to clarify the meaning of the adjustment (e.g., low/high, decrease/increase).\n * - Enable `allowSeeking` for scenarios where users should be able to jump to a specific value by clicking the track.\n * - Use `hugcontainer` when the slider should visually connect tightly with its icon buttons.\n *\n * **TODO(designer):** Clarify recommended use cases for each variant and when to use `allowSeeking` vs. standard interaction.\n *\n * ---\n *\n * ### Slots\n *\n * | Slot Name | Renders When... | Purpose |\n * |-------------|---------------------------|--------------------------------------------|\n * | icon-left | `hasLeftIcon` is true | Icon/button for decrement action |\n * | icon-right | `hasRightIcon` is true | Icon/button for increment action |\n *\n * ---\n *\n * ### Properties and Attributes\n * - `value` (number): Current slider value. Updates as the user interacts.\n * - `min` (number): Minimum allowed value (default: 0).\n * - `max` (number): Maximum allowed value (default: 100).\n * - `step` (number): Step granularity for value changes (optional).\n * - `stepClick` (number): Amount to increment/decrement when clicking icon buttons (default: 10).\n * - `variant` (ObcSliderVariant): Visual/interaction style (`normal`, `enhanced`, `no-input`). Default: `normal`.\n * - `hasLeftIcon`/`hasRightIcon` (boolean): Show icon button on left/right.\n * - `allowSeeking` (boolean): Enables animated seeking to clicked value on the track.\n * - `seekingSpeed` (number): Animation speed for seeking (default: 1/3; higher is faster).\n * - `hugcontainer` (attribute): Removes spacing between slider and icon buttons for a compact layout.\n *\n * ---\n *\n * ### Events\n * - `value` – Fired continuously when the slider value changes during user interaction or programmatically. The event detail contains the new value as a number.\n * - `change` – Fired only after user interaction completes (mouse/touch release or button click). The event detail contains the new value as a number.\n *\n * ---\n *\n * ### Best Practices & Constraints\n * - Only use `no-input` variant for read-only display; interactive controls should use `normal` or `enhanced`.\n * - For accessibility, ensure the slider has a visible label or context.\n * - Use step values that make sense for the range (e.g., avoid step=0.01 for a 0–10 range unless fine granularity is needed).\n * - When using icon buttons, provide icons that clearly indicate their function.\n * - The slider is horizontal only; for vertical sliders, use a different component.\n *\n * ---\n *\n * ### Example\n *\n * ```html\n * <obc-slider\n * value=\"40\"\n * min=\"0\"\n * max=\"100\"\n * step=\"10\"\n * haslefticon\n * hasrighticon\n * variant=\"enhanced\"\n * >\n * <obi-arrow slot=\"icon-left\"></obi-arrow>\n * <obi-arrow slot=\"icon-right\"></obi-arrow>\n * </obc-slider>\n * ```\n *\n * In this example, the slider allows selection from 0 to 100 in steps of 10, with left/right arrow icons for quick adjustments.\n *\n * @slot icon-left - Slot for the left icon button (shown when `hasLeftIcon` is true)\n * @slot icon-right - Slot for the right icon button (shown when `hasRightIcon` is true)\n * @attr hugcontainer - If set, the slider will not have any spacing between the slider icons and the container\n * @fires value {ObcSliderValueEvent} - Fired when the value is changed\n * @fires change {ObcSliderChangeEvent} - Fired when user interaction completes and value has changed\n */\n@customElement('obc-slider')\nexport class ObcSlider extends LitElement {\n /**\n * The current value of the slider.\n *\n * Updates as the user drags the thumb, clicks the track (if `allowSeeking`), or uses the increment/decrement buttons.\n */\n @property({type: Number}) value = 50;\n\n /**\n * The minimum allowed value for the slider.\n *\n * Default is 0.\n */\n @property({type: Number}) min = 0;\n\n /**\n * The maximum allowed value for the slider.\n *\n * Default is 100.\n */\n @property({type: Number}) max = 100;\n\n /**\n * The step granularity for slider value changes.\n *\n * If set, the slider will snap to multiples of this value between min and max.\n * Optional; if not set, the slider is continuous.\n */\n @property({type: Number}) step: number | undefined;\n\n /**\n * The amount to increment or decrement the value when clicking the left/right icon buttons.\n *\n * Default is 10.\n * @availableWhen hasLeftIcon==true || hasRightIcon==true\n */\n @property({type: Number}) stepClick = 10;\n\n /**\n * The visual and interaction style of the slider.\n *\n * - `normal`: Standard appearance.\n * - `enhanced`: Larger track and thumb for emphasis.\n * - `no-input`: Read-only; disables all user input.\n *\n * Default is `normal`.\n */\n @property({type: String}) variant: ObcSliderVariant = ObcSliderVariant.Normal;\n\n /**\n * Whether to display a left icon button for decrementing the value.\n *\n * When true, the `icon-left` slot is rendered as a button.\n */\n @property({type: Boolean}) hasLeftIcon = false;\n\n /**\n * Whether to display a right icon button for incrementing the value.\n *\n * When true, the `icon-right` slot is rendered as a button.\n */\n @property({type: Boolean}) hasRightIcon = false;\n\n /**\n * Enables animated seeking: clicking or dragging along the track will set the value to the clicked position, animating smoothly.\n *\n * Default is false.\n * @availableWhen variant!=no-input && disabled==false\n */\n @property({type: Boolean}) allowSeeking = false;\n\n /**\n * The speed of the smooth animation that moves the value to the clicked position (used when `allowSeeking` is false).\n *\n * Expressed as the inverse of seconds to go from min to max (e.g., 1/3 means 3 seconds for full range).\n * Default is 1/3.\n * @availableWhen allowSeeking==false && variant!=no-input && disabled==false\n */\n @property({type: Number}) seekingSpeed = 1 / 3;\n\n @property({type: Boolean}) disabled = false;\n\n private get ratio(): number {\n const range = this.max - this.min;\n if (!Number.isFinite(range) || range <= 0) return 0;\n const ratio = (this.value - this.min) / range;\n if (!Number.isFinite(ratio)) return 0;\n return Math.max(0, Math.min(1, ratio));\n }\n\n private animationFrame: number | null = null;\n private isMouseDown = false;\n private isTouchActive = false;\n private targetValue = 0;\n private isDragging = false;\n private animationStartTime: number | null = null;\n private animationStartValue: number = 0;\n\n /**\n * Handles input changes from the slider or buttons.\n * Fires the `value` event with the new value.\n *\n * @param value - The new value to set.\n * @fires value\n */\n onInput(value: number) {\n this.value = value;\n this.dispatchEvent(new CustomEvent('value', {detail: this.value}));\n }\n\n /**\n * Fires the `change` event with the current value.\n *\n * @fires change\n */\n private fireChangeEvent() {\n this.dispatchEvent(\n new CustomEvent('change', {detail: this.value}) as ObcSliderChangeEvent\n );\n }\n\n /**\n * Decrements the value by `stepClick` when the left icon button is clicked.\n */\n onReduceClick() {\n if (this.disabled) return;\n this.onInput(Math.max(this.value - this.stepClick, this.min));\n this.fireChangeEvent();\n }\n\n /**\n * Increments the value by `stepClick` when the right icon button is clicked.\n */\n onIncreaseClick() {\n if (this.disabled) return;\n this.onInput(Math.min(this.value + this.stepClick, this.max));\n this.fireChangeEvent();\n }\n\n private get slider(): HTMLInputElement {\n return this.renderRoot.querySelector('input[type=\"range\"]')!;\n }\n\n private isClickingThumb(e: MouseEvent | TouchEvent) {\n const rect = this.slider.getBoundingClientRect();\n const left = rect.left + 24;\n const width = rect.width - 48;\n const thumbWidth = 48;\n const ratioValue = this.ratio;\n const thumbCenter = left + width * ratioValue;\n\n let clientX: number;\n if ('touches' in e) {\n clientX = e.touches[0].clientX;\n } else {\n clientX = e.clientX;\n }\n\n const isNearThumb = Math.abs(clientX - thumbCenter) <= thumbWidth / 2;\n return isNearThumb;\n }\n\n private onMouseDown(e: MouseEvent) {\n if (this.variant === ObcSliderVariant.NoInput || this.disabled) return;\n if (this.isClickingThumb(e)) return;\n this.isMouseDown = true;\n this.updateTargetValue(e);\n e.preventDefault();\n window.addEventListener('mousemove', this.onWindowMouseMove);\n window.addEventListener('mouseup', this.onWindowMouseUp);\n this.startAnimation();\n }\n\n private onTouchStart(e: TouchEvent) {\n if (this.variant === ObcSliderVariant.NoInput || this.disabled) return;\n if (this.isClickingThumb(e)) return;\n this.isTouchActive = true;\n this.updateTargetValue(e);\n e.preventDefault();\n window.addEventListener('touchmove', this.onWindowTouchMove, {\n passive: false,\n });\n window.addEventListener('touchend', this.onWindowTouchEnd);\n this.startAnimation();\n }\n\n private onWindowMouseMove = (e: MouseEvent) => {\n this.onMouseMove(e);\n };\n\n private onWindowMouseUp = () => {\n this.onMouseUp();\n };\n\n private onWindowTouchMove = (e: TouchEvent) => {\n this.onTouchMove(e);\n };\n\n private onWindowTouchEnd = () => {\n this.onTouchEnd();\n };\n\n private onMouseMove(e: MouseEvent) {\n if (this.isMouseDown) {\n this.updateTargetValue(e);\n }\n }\n\n private onTouchMove(e: TouchEvent) {\n if (this.isTouchActive) {\n this.updateTargetValue(e);\n }\n }\n\n private onMouseUp() {\n this.isMouseDown = false;\n window.removeEventListener('mousemove', this.onWindowMouseMove);\n window.removeEventListener('mouseup', this.onWindowMouseUp);\n this.stopAnimation();\n this.fireChangeEvent();\n }\n\n private onTouchEnd() {\n this.isTouchActive = false;\n window.removeEventListener('touchmove', this.onWindowTouchMove);\n window.removeEventListener('touchend', this.onWindowTouchEnd);\n this.stopAnimation();\n this.fireChangeEvent();\n }\n\n private updateTargetValue(e: MouseEvent | TouchEvent) {\n const rect = this.slider.getBoundingClientRect();\n const left = rect.left + 24;\n const width = rect.width - 48;\n const x = e instanceof MouseEvent ? e.clientX : e.touches[0].clientX;\n const percent = (x - left) / width;\n const min = parseFloat(this.slider.min);\n const max = parseFloat(this.slider.max);\n const unroundedValue = min + (max - min) * percent;\n if (this.step) {\n this.targetValue = Math.round(unroundedValue / this.step) * this.step;\n } else {\n this.targetValue = unroundedValue;\n }\n }\n\n private startAnimation() {\n this.isDragging = this.allowSeeking;\n this.animationStartTime = performance.now();\n this.animationStartValue = parseFloat(this.slider.value);\n const min = parseFloat(this.slider.min);\n const max = parseFloat(this.slider.max);\n const step = this.step;\n const duration = (1 / this.seekingSpeed) * 1000; // ms\n const direction = this.targetValue > this.animationStartValue ? 1 : -1;\n\n const animate = () => {\n let nextValue = this.targetValue;\n if (!this.isDragging) {\n const now = performance.now();\n const elapsed = now - (this.animationStartTime ?? now);\n const range = Math.abs(max - min);\n // How much of the range should be covered by now\n const expectedProgress = Math.min(elapsed / duration, 1);\n const expectedValue =\n this.animationStartValue + direction * range * expectedProgress;\n // Snap to step\n if (direction > 0) {\n nextValue =\n step === undefined\n ? expectedValue\n : Math.ceil((expectedValue - min) / step) * step + min;\n nextValue = Math.min(this.targetValue, nextValue);\n } else {\n nextValue =\n step === undefined\n ? expectedValue\n : Math.floor((expectedValue - min) / step) * step + min;\n nextValue = Math.max(this.targetValue, nextValue);\n }\n }\n // Only update if value actually changes\n if (parseFloat(this.slider.value) !== nextValue) {\n this.slider.value = String(nextValue);\n this.slider.dispatchEvent(new Event('input'));\n }\n // Continue animating if not at target\n if (\n (direction > 0 && nextValue < this.targetValue) ||\n (direction < 0 && nextValue > this.targetValue)\n ) {\n this.animationFrame = requestAnimationFrame(animate);\n } else if (this.isMouseDown || this.isTouchActive) {\n // If mouse or touch is still active, wait for new target\n this.animationStartTime = performance.now();\n this.animationStartValue = parseFloat(this.slider.value);\n this.animationFrame = requestAnimationFrame(animate);\n this.isDragging = true;\n }\n };\n\n this.animationFrame = requestAnimationFrame(animate);\n }\n\n private stopAnimation() {\n if (this.animationFrame !== null) {\n cancelAnimationFrame(this.animationFrame);\n this.animationFrame = null;\n }\n }\n\n override render() {\n return html`\n ${this.hasLeftIcon\n ? html` <obc-icon-button\n ?disabled=${this.disabled}\n @click=${this.onReduceClick}\n variant=\"normal\"\n >\n <slot name=\"icon-left\"></slot>\n </obc-icon-button>`\n : null}\n <div\n class=${classMap({\n wrapper: true,\n [this.variant]: true,\n disabled: this.disabled,\n })}\n style=${styleMap({\n '--_ratio': String(this.ratio),\n })}\n >\n <div class=\"track\"></div>\n <input\n type=\"range\"\n min=${this.min}\n max=${this.max}\n step=${ifDefined(this.step)}\n .value=${this.value.toString()}\n ?disabled=${this.variant === ObcSliderVariant.NoInput ||\n this.disabled}\n class=\"slider\"\n @input=${(event: Event) => {\n this.value = Number((event.target as HTMLInputElement).value);\n this.dispatchEvent(new CustomEvent('value', {detail: this.value}));\n }}\n @change=${() => {\n this.fireChangeEvent();\n }}\n @mousedown=${this.onMouseDown}\n @touchstart=${this.onTouchStart}\n @mousemove=${this.onMouseMove}\n @touchmove=${this.onTouchMove}\n @mouseup=${this.onMouseUp}\n @touchend=${this.onTouchEnd}\n />\n <div\n class=\"interactive-track-hover\"\n @mousedown=${this.onMouseDown}\n @touchstart=${this.onTouchStart}\n @mousemove=${this.onMouseMove}\n @touchmove=${this.onTouchMove}\n @mouseup=${this.onMouseUp}\n @touchend=${this.onTouchEnd}\n ></div>\n <div\n class=\"container-hover\"\n @mousedown=${this.onMouseDown}\n @touchstart=${this.onTouchStart}\n @mousemove=${this.onMouseMove}\n @touchmove=${this.onTouchMove}\n @mouseup=${this.onMouseUp}\n @touchend=${this.onTouchEnd}\n ></div>\n <div class=\"interactive-track\"></div>\n <div class=\"thumb\"></div>\n </div>\n ${this.hasRightIcon\n ? html`<obc-icon-button\n ?disabled=${this.disabled}\n @click=${this.onIncreaseClick}\n variant=\"normal\"\n >\n <slot name=\"icon-right\"></slot>\n </obc-icon-button>`\n : null}\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-slider': ObcSlider;\n }\n}\n"],"names":["ObcSliderVariant"],"mappings":"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"}
@@ -20,6 +20,14 @@ export type ObcSliderDoubleValueEvent = CustomEvent<{
20
20
  low: number;
21
21
  high: number;
22
22
  }>;
23
+ /**
24
+ * Event type for change event in obc-slider-double (fired after user interaction completes).
25
+ * Contains the current low and high values of the slider.
26
+ */
27
+ export type ObcSliderDoubleChangeEvent = CustomEvent<{
28
+ low: number;
29
+ high: number;
30
+ }>;
23
31
  /**
24
32
  * `<obc-slider-double>` – A dual-thumb range slider for selecting a value interval within a defined range.
25
33
  *
@@ -77,7 +85,8 @@ export type ObcSliderDoubleValueEvent = CustomEvent<{
77
85
  * - `hugcontainer` (attribute): If present, removes spacing between slider and container edges.
78
86
  *
79
87
  * ## Events
80
- * - `value` – Fired whenever the low or high value changes. Event detail contains `{low, high}`.
88
+ * - `value` – Fired continuously whenever the low or high value changes during user interaction. Event detail contains `{low, high}`.
89
+ * - `change` – Fired only after user interaction completes (mouse release). Event detail contains `{low, high}`.
81
90
  *
82
91
  * ## Best Practices and Constraints
83
92
  * - Ensure `low` is always less than or equal to `high`; the component enforces this automatically.
@@ -112,6 +121,7 @@ export type ObcSliderDoubleValueEvent = CustomEvent<{
112
121
  * @slot left-readout - Custom content for the left (low) readout label (rendered when `showLeftReadout` is true)
113
122
  * @slot right-readout - Custom content for the right (high) readout label (rendered when `showRightReadout` is true)
114
123
  * @fires value {ObcSliderDoubleValueEvent} - Fires when the value is changed
124
+ * @fires change {ObcSliderDoubleChangeEvent} - Fires when user interaction completes
115
125
  */
116
126
  export declare class ObcSliderDouble extends LitElement {
117
127
  /**
@@ -218,6 +228,12 @@ export declare class ObcSliderDouble extends LitElement {
218
228
  * @fires value {ObcSliderDoubleValueEvent}
219
229
  */
220
230
  onInput(): void;
231
+ /**
232
+ * Fires the `change` event with the current low and high values.
233
+ *
234
+ * @fires change
235
+ */
236
+ private fireChangeEvent;
221
237
  private THUMB_WIDTH;
222
238
  private THUMB_VISIBLE_WIDTH;
223
239
  private lowClickValue;
@@ -1 +1 @@
1
- {"version":3,"file":"slider-double.d.ts","sourceRoot":"","sources":["../../../src/components/slider-double/slider-double.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAkB,MAAM,KAAK,CAAC;AAKhD,OAAO,+BAA+B,CAAC;AAIvC;;;;;;GAMG;AACH,oBAAY,sBAAsB;IAChC,MAAM,WAAW;IACjB,QAAQ,aAAa;IACrB,OAAO,aAAa;CACrB;AAED;;;GAGG;AACH,MAAM,MAAM,yBAAyB,GAAG,WAAW,CAAC;IAClD,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4FG;AACH,qBACa,eAAgB,SAAQ,UAAU;IAC7C;;;OAGG;IACuB,GAAG,SAAK;IAElC;;;OAGG;IACuB,IAAI,SAAO;IAErC;;;OAGG;IACuB,GAAG,SAAK;IAElC;;;OAGG;IACuB,GAAG,SAAO;IAEpC;;;OAGG;IACuB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAEnD;;;OAGG;IACuB,SAAS,SAAM;IAEzC;;;;;;OAMG;IACuB,OAAO,EAAE,sBAAsB,CACzB;IAEhC;;;OAGG;IACwB,YAAY,UAAS;IAErB,QAAQ,UAAS;IAE5C;;;;OAIG;IACuB,YAAY,SAAS;IAE/C;;OAEG;IACuB,SAAS,SAAM;IAEzC;;OAEG;IACuB,aAAa,SAAK;IAE5C;;OAEG;IACuB,UAAU,SAAU;IAE9C;;;;;;;OAOG;IAC0C,eAAe,UAAQ;IAEpE;;;;;;;OAOG;IAC0C,gBAAgB,UAAQ;IAErE;;;OAGG;IAEH,YAAY,UAAS;IAErB,OAAO,KAAK,QAAQ,GAEnB;IAED,OAAO,KAAK,SAAS,GAEpB;IAED,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,kBAAkB,CAAuB;IACjD,OAAO,CAAC,mBAAmB,CAAa;IAGxC,OAAO,CAAC,QAAQ,CAAoB;IAGpC,OAAO,CAAC,QAAQ,CAAoB;IAEpC;;;;;OAKG;IACH,OAAO;IAkBP,OAAO,CAAC,WAAW,CAAM;IACzB,OAAO,CAAC,mBAAmB,CAAM;IAEjC,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,kBAAkB;IAK1B,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,mBAAmB;IAM3B,OAAO,CAAC,WAAW;IA8BnB,OAAO,CAAC,iBAAiB,CAEvB;IAEF,OAAO,CAAC,eAAe,CAErB;IAEF,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,iBAAiB;IAsBzB,OAAO,CAAC,cAAc;IAmEtB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,WAAW;IAIV,MAAM;IA4Ef,OAAgB,MAAM,0BAA6B;CACpD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,mBAAmB,EAAE,eAAe,CAAC;KACtC;CACF"}
1
+ {"version":3,"file":"slider-double.d.ts","sourceRoot":"","sources":["../../../src/components/slider-double/slider-double.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAkB,MAAM,KAAK,CAAC;AAKhD,OAAO,+BAA+B,CAAC;AAIvC;;;;;;GAMG;AACH,oBAAY,sBAAsB;IAChC,MAAM,WAAW;IACjB,QAAQ,aAAa;IACrB,OAAO,aAAa;CACrB;AAED;;;GAGG;AACH,MAAM,MAAM,yBAAyB,GAAG,WAAW,CAAC;IAClD,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,MAAM,0BAA0B,GAAG,WAAW,CAAC;IACnD,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8FG;AACH,qBACa,eAAgB,SAAQ,UAAU;IAC7C;;;OAGG;IACuB,GAAG,SAAK;IAElC;;;OAGG;IACuB,IAAI,SAAO;IAErC;;;OAGG;IACuB,GAAG,SAAK;IAElC;;;OAGG;IACuB,GAAG,SAAO;IAEpC;;;OAGG;IACuB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAEnD;;;OAGG;IACuB,SAAS,SAAM;IAEzC;;;;;;OAMG;IACuB,OAAO,EAAE,sBAAsB,CACzB;IAEhC;;;OAGG;IACwB,YAAY,UAAS;IAErB,QAAQ,UAAS;IAE5C;;;;OAIG;IACuB,YAAY,SAAS;IAE/C;;OAEG;IACuB,SAAS,SAAM;IAEzC;;OAEG;IACuB,aAAa,SAAK;IAE5C;;OAEG;IACuB,UAAU,SAAU;IAE9C;;;;;;;OAOG;IAC0C,eAAe,UAAQ;IAEpE;;;;;;;OAOG;IAC0C,gBAAgB,UAAQ;IAErE;;;OAGG;IAEH,YAAY,UAAS;IAErB,OAAO,KAAK,QAAQ,GAEnB;IAED,OAAO,KAAK,SAAS,GAEpB;IAED,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,kBAAkB,CAAuB;IACjD,OAAO,CAAC,mBAAmB,CAAa;IAGxC,OAAO,CAAC,QAAQ,CAAoB;IAGpC,OAAO,CAAC,QAAQ,CAAoB;IAEpC;;;;;OAKG;IACH,OAAO;IAkBP;;;;OAIG;IACH,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,WAAW,CAAM;IACzB,OAAO,CAAC,mBAAmB,CAAM;IAEjC,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,kBAAkB;IAK1B,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,mBAAmB;IAM3B,OAAO,CAAC,WAAW;IA8BnB,OAAO,CAAC,iBAAiB,CAEvB;IAEF,OAAO,CAAC,eAAe,CAErB;IAEF,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,SAAS;IASjB,OAAO,CAAC,iBAAiB;IAsBzB,OAAO,CAAC,cAAc;IAmEtB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,WAAW;IAIV,MAAM;IA8Ef,OAAgB,MAAM,0BAA6B;CACpD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,mBAAmB,EAAE,eAAe,CAAC;KACtC;CACF"}
@@ -92,6 +92,18 @@ let ObcSliderDouble = class extends LitElement {
92
92
  new CustomEvent("value", { detail: { low: this.low, high: this.high } })
93
93
  );
94
94
  }
95
+ /**
96
+ * Fires the `change` event with the current low and high values.
97
+ *
98
+ * @fires change
99
+ */
100
+ fireChangeEvent() {
101
+ this.dispatchEvent(
102
+ new CustomEvent("change", {
103
+ detail: { low: this.low, high: this.high }
104
+ })
105
+ );
106
+ }
95
107
  lowClickValue(e) {
96
108
  const rect = this.minInput.getBoundingClientRect();
97
109
  const left = rect.left + this.THUMB_WIDTH - this.THUMB_VISIBLE_WIDTH / 2;
@@ -179,6 +191,7 @@ let ObcSliderDouble = class extends LitElement {
179
191
  window.removeEventListener("mousemove", this.onWindowMouseMove);
180
192
  window.removeEventListener("mouseup", this.onWindowMouseUp);
181
193
  this.stopAnimation();
194
+ this.fireChangeEvent();
182
195
  }
183
196
  updateTargetValue(e) {
184
197
  const unroundedValue = this.isTargetingLow ? this.lowClickValue(e) : this.highClickValue(e);
@@ -295,6 +308,7 @@ let ObcSliderDouble = class extends LitElement {
295
308
  .value=${this.low.toString()}
296
309
  ?disabled=${this.variant === "no-input" || this.disabled}
297
310
  @input=${this.onInput}
311
+ @change=${() => this.fireChangeEvent()}
298
312
  />
299
313
  <input
300
314
  type="range"
@@ -305,6 +319,7 @@ let ObcSliderDouble = class extends LitElement {
305
319
  .value=${this.high.toString()}
306
320
  ?disabled=${this.variant === "no-input" || this.disabled}
307
321
  @input=${this.onInput}
322
+ @change=${() => this.fireChangeEvent()}
308
323
  />
309
324
  <div class="interactive-track"></div>
310
325
  <div class="thumb min"></div>
@@ -1 +1 @@
1
- {"version":3,"file":"slider-double.js","sources":["../../../src/components/slider-double/slider-double.ts"],"sourcesContent":["import {LitElement, html, unsafeCSS} from 'lit';\nimport {property, query} from 'lit/decorators.js';\nimport {ifDefined} from 'lit/directives/if-defined.js';\nimport {styleMap} from 'lit/directives/style-map.js';\nimport componentStyle from './slider-double.css?inline';\nimport '../icon-button/icon-button.js';\nimport {classMap} from 'lit/directives/class-map.js';\nimport {customElement} from '../../decorator.js';\n\n/**\n * Enum for slider double variants.\n *\n * - `normal`: Standard slider with default styling and interaction.\n * - `enhanced`: Visually enhanced slider with larger track and thumb, suitable for more prominent or touch-friendly UIs.\n * - `no-input`: Non-interactive display mode; disables all user input and presents the slider as read-only.\n */\nexport enum ObcSliderDoubleVariant {\n Normal = 'normal',\n Enhanced = 'enhanced',\n NoInput = 'no-input',\n}\n\n/**\n * Event type for value changes in obc-slider-double.\n * Contains the current low and high values of the slider.\n */\nexport type ObcSliderDoubleValueEvent = CustomEvent<{\n low: number;\n high: number;\n}>;\n\n/**\n * `<obc-slider-double>` – A dual-thumb range slider for selecting a value interval within a defined range.\n *\n * This component allows users to select a minimum and maximum value by dragging two thumbs along a horizontal track. It is commonly used for filtering or specifying ranges (such as price, speed, or time intervals) in forms and dashboards. The slider supports both interactive and read-only display modes, as well as visual variants for different UI needs.\n *\n * Appears with two draggable handles (thumbs) and labels showing the current low and high values. Optionally, icons can be placed at each end of the slider via slots.\n *\n * ## Features\n * - **Dual-thumb range selection:** Users can adjust both the lower and upper bounds of a numeric interval.\n * - **Variants:**\n * - **Normal:** Standard slider with compact styling.\n * - **Enhanced:** Larger track and thumb for increased prominence or touch accessibility.\n * - **NoInput:** Read-only mode; disables all user interaction and presents the current range as static.\n * - **Configurable range:** Set minimum (`min`), maximum (`max`), and step size (`step`) for precise control.\n * - **Step click adjustment:** Use `stepClick` to define increment/decrement amount for keyboard or button-based changes.\n * - **Seeking mode:** Enable `allowSeeking` to let users jump to a value by clicking on the track, with smooth animated transitions controlled by `seekingSpeed`.\n * - **Custom labels:** Display formatted value labels with unit (`labelUnit`), decimal precision (`labelDecimals`), and adjustable label width (`labelWidth`).\n * - **Hug container option:** Remove spacing between slider and container edges with the `hugcontainer` attribute for seamless layout integration.\n * - **Icon slots:** Add icons to the left and right ends of the slider using `icon-left` and `icon-right` slots.\n *\n * ## Usage Guidelines\n * Use `obc-slider-double` when you need users to specify a numeric range, such as filtering results by minimum and maximum values. Ideal for scenarios like:\n * - Filtering items by price, speed, or other continuous values.\n * - Selecting a time interval or threshold range.\n * - Any UI where a bounded numeric interval is required.\n *\n * For single-value selection, use a standard slider component instead. In read-only or summary views, use the `no-input` variant to display the selected range without allowing changes.\n *\n * **TODO(designer):** Confirm if there are recommended minimum thumb separation or constraints for usability, and if there are best practices for using the enhanced variant.\n *\n * ## Slots\n *\n * | Slot Name | Renders When... | Purpose |\n * |---------------|-------------------------------|------------------------------------------------------------------------------------------------------------------|\n * | icon-left | Always | Icon or content at the left end of the slider. Example: `<obi-placeholder slot=\"icon-left\"></obi-placeholder>` |\n * | icon-right | Always | Icon or content at the right end of the slider. Example: `<obi-placeholder slot=\"icon-right\"></obi-placeholder>` |\n * | left-readout | `showLeftReadout` is true | Custom content for the left (low) readout label. Falls back to the formatted `low` value. |\n * | right-readout | `showRightReadout` is true | Custom content for the right (high) readout label. Falls back to the formatted `high` value. |\n *\n * ## Properties and Attributes\n * - `low` (number): The current lower bound of the selected range.\n * - `high` (number): The current upper bound of the selected range.\n * - `min` (number): The minimum allowed value (default: 0).\n * - `max` (number): The maximum allowed value (default: 100).\n * - `step` (number): The increment for value changes (default: 1).\n * - `stepClick` (number): Step size for keyboard or button-based changes (default: 10).\n * - `variant` (`normal` | `enhanced` | `no-input`): Visual and interaction style (default: `normal`).\n * - `allowSeeking` (boolean): If true, clicking the track animates the thumb to the clicked position.\n * - `seekingSpeed` (number): Animation speed for seeking (default: 1/3, i.e., full range in 3 seconds).\n * - `labelUnit` (string): Unit label appended to value labels (e.g., `\"%\"`, `\"kn\"`).\n * - `labelDecimals` (number): Number of decimal places for value labels.\n * - `labelWidth` (string): CSS width for value labels (e.g., `\"5ch\"`, `\"60px\"`).\n * - `showLeftReadout` (boolean, property only): Show the left (low) readout label. Default `true`.\n * - `showRightReadout` (boolean, property only): Show the right (high) readout label. Default `true`.\n * - `hugcontainer` (attribute): If present, removes spacing between slider and container edges.\n *\n * ## Events\n * - `value` – Fired whenever the low or high value changes. Event detail contains `{low, high}`.\n *\n * ## Best Practices and Constraints\n * - Ensure `low` is always less than or equal to `high`; the component enforces this automatically.\n * - For accessibility, provide clear labels and units so users understand the meaning of the range.\n * - Use the `no-input` variant for summary or review screens where editing is not allowed.\n * - When using `allowSeeking`, set an appropriate `seekingSpeed` for smooth but responsive thumb movement.\n * - Avoid setting `step` too small for large ranges, as this may make precise selection difficult.\n *\n * ## Example\n *\n * ```html\n * <obc-slider-double\n * min=\"0\"\n * max=\"100\"\n * low=\"20\"\n * high=\"80\"\n * step=\"5\"\n * label-unit=\"%\"\n * label-decimals=\"0\"\n * variant=\"enhanced\"\n * allowSeeking\n * >\n * <obi-placeholder slot=\"icon-left\"></obi-placeholder>\n * <obi-placeholder slot=\"icon-right\"></obi-placeholder>\n * </obc-slider-double>\n * ```\n *\n * In this example, the slider allows selection of a percentage range from 0 to 100, with 5% increments, enhanced styling, and seeking enabled.\n *\n * @slot icon-left - Slot for the left icon\n * @slot icon-right - Slot for the right icon\n * @slot left-readout - Custom content for the left (low) readout label (rendered when `showLeftReadout` is true)\n * @slot right-readout - Custom content for the right (high) readout label (rendered when `showRightReadout` is true)\n * @fires value {ObcSliderDoubleValueEvent} - Fires when the value is changed\n */\n@customElement('obc-slider-double')\nexport class ObcSliderDouble extends LitElement {\n /**\n * The current lower bound of the selected range.\n * Must be greater than or equal to `min` and less than or equal to `high`.\n */\n @property({type: Number}) low = 0;\n\n /**\n * The current upper bound of the selected range.\n * Must be less than or equal to `max` and greater than or equal to `low`.\n */\n @property({type: Number}) high = 100;\n\n /**\n * The minimum allowed value for the slider.\n * Default is 0.\n */\n @property({type: Number}) min = 0;\n\n /**\n * The maximum allowed value for the slider.\n * Default is 100.\n */\n @property({type: Number}) max = 100;\n\n /**\n * The increment for value changes.\n * If not set, defaults to 1.\n */\n @property({type: Number}) step: number | undefined;\n\n /**\n * Step size for keyboard or button-based changes.\n * Default is 10.\n */\n @property({type: Number}) stepClick = 10;\n\n /**\n * Visual and interaction style of the slider.\n * - `normal`: Standard appearance.\n * - `enhanced`: Larger track and thumb.\n * - `no-input`: Read-only, disables user interaction.\n * Default is `normal`.\n */\n @property({type: String}) variant: ObcSliderDoubleVariant =\n ObcSliderDoubleVariant.Normal;\n\n /**\n * If true, clicking the slider track animates the thumb to the clicked position.\n * Enables seeking mode for rapid value changes.\n */\n @property({type: Boolean}) allowSeeking = false;\n\n @property({type: Boolean}) disabled = false;\n\n /**\n * Animation speed for seeking, in inverse seconds.\n * The value will go from min to max in 1 / seekingSpeed seconds.\n * Default is 1/3 (i.e., 3 seconds for full range).\n */\n @property({type: Number}) seekingSpeed = 1 / 3;\n\n /**\n * Unit label appended to value labels (e.g., \"%\", \"kn\").\n */\n @property({type: String}) labelUnit = '';\n\n /**\n * Number of decimal places to display in value labels.\n */\n @property({type: Number}) labelDecimals = 0;\n\n /**\n * CSS width for value labels (e.g., \"5ch\", \"60px\").\n */\n @property({type: String}) labelWidth = '60px';\n\n /**\n * Whether to show the left (low) readout label.\n *\n * When false, the left readout is hidden entirely. When true, the readout\n * renders the formatted `low` value or the content slotted into `left-readout`.\n *\n * Default is true. Set via JavaScript property (no HTML attribute).\n */\n @property({type: Boolean, attribute: false}) showLeftReadout = true;\n\n /**\n * Whether to show the right (high) readout label.\n *\n * When false, the right readout is hidden entirely. When true, the readout\n * renders the formatted `high` value or the content slotted into `right-readout`.\n *\n * Default is true. Set via JavaScript property (no HTML attribute).\n */\n @property({type: Boolean, attribute: false}) showRightReadout = true;\n\n /**\n * Removes spacing between the slider and its container edges for seamless\n * layout integration. Reflected to the `hugcontainer` HTML attribute.\n */\n @property({type: Boolean, reflect: true, attribute: 'hugcontainer'})\n hugContainer = false;\n\n private get lowRatio(): number {\n return this.computeRatio(this.low);\n }\n\n private get highRatio(): number {\n return this.computeRatio(this.high);\n }\n\n private computeRatio(value: number): number {\n const range = this.max - this.min;\n if (!Number.isFinite(range) || range <= 0) return 0;\n const ratio = (value - this.min) / range;\n if (!Number.isFinite(ratio)) return 0;\n return Math.max(0, Math.min(1, ratio));\n }\n\n private animationFrame: number | null = null;\n private isMouseDown = false;\n private targetValue = 0;\n private isDragging = false;\n private isTargetingLow = false;\n private animationStartTime: number | null = null;\n private animationStartValue: number = 0;\n\n @query('input[type=\"range\"].min')\n private minInput!: HTMLInputElement;\n\n @query('input[type=\"range\"].max')\n private maxInput!: HTMLInputElement;\n\n /**\n * Handles input changes from the slider thumbs.\n * Updates the low and high values and emits the `value` event.\n *\n * @fires value {ObcSliderDoubleValueEvent}\n */\n onInput() {\n let newLow = parseFloat(this.minInput.value);\n let newHigh = parseFloat(this.maxInput.value);\n if (newLow > this.high) {\n newLow = this.high;\n this.minInput.value = this.high.toString();\n }\n if (newHigh < this.low) {\n newHigh = this.low;\n this.maxInput.value = this.low.toString();\n }\n this.low = newLow;\n this.high = newHigh;\n this.dispatchEvent(\n new CustomEvent('value', {detail: {low: this.low, high: this.high}})\n );\n }\n\n private THUMB_WIDTH = 48;\n private THUMB_VISIBLE_WIDTH = 12;\n\n private lowClickValue(e: MouseEvent) {\n const rect = this.minInput.getBoundingClientRect();\n const left = rect.left + this.THUMB_WIDTH - this.THUMB_VISIBLE_WIDTH / 2;\n const width = rect.width - this.THUMB_WIDTH;\n const percent = (e.clientX - left) / width;\n return this.min + (this.max - this.min) * percent;\n }\n\n private highClickValue(e: MouseEvent) {\n const rect = this.maxInput.getBoundingClientRect();\n const left = rect.left + this.THUMB_VISIBLE_WIDTH / 2;\n const width = rect.width - this.THUMB_WIDTH;\n const percent = (e.clientX - left) / width;\n return this.min + (this.max - this.min) * percent;\n }\n\n private thumbRange() {\n const rect = this.minInput.getBoundingClientRect();\n const valueRange = this.max - this.min;\n const percentageRange = this.THUMB_WIDTH / rect.width;\n return valueRange * percentageRange;\n }\n\n private isClickingMinThumb(e: MouseEvent) {\n const value = this.lowClickValue(e);\n if (value > this.low) {\n return false;\n }\n return value >= this.low - this.thumbRange();\n }\n\n private isClickingMaxThumb(e: MouseEvent) {\n const value = this.highClickValue(e);\n if (value < this.high) {\n return false;\n }\n return value <= this.high + this.thumbRange();\n }\n\n private isClickingLowTrack(e: MouseEvent) {\n const value = this.lowClickValue(e);\n return value <= this.low - this.thumbRange() / 2;\n }\n\n private isClickingHighTrack(e: MouseEvent) {\n const value = this.highClickValue(e);\n return value >= this.high + this.thumbRange() / 2;\n }\n\n private isClosestToLowThumb(e: MouseEvent) {\n const lowValue = this.lowClickValue(e);\n const highValue = this.highClickValue(e);\n return Math.abs(lowValue - this.low) <= Math.abs(highValue - this.high);\n }\n\n private onMouseDown(e: MouseEvent) {\n if (this.variant === ObcSliderDoubleVariant.NoInput || this.disabled)\n return;\n if (this.isClickingMinThumb(e)) {\n this.isTargetingLow = true;\n this.isDragging = true;\n } else if (this.isClickingMaxThumb(e)) {\n this.isTargetingLow = false;\n this.isDragging = true;\n } else if (this.isClickingLowTrack(e)) {\n this.isTargetingLow = true;\n this.isDragging = false;\n } else if (this.isClickingHighTrack(e)) {\n this.isTargetingLow = false;\n this.isDragging = false;\n } else if (this.isClosestToLowThumb(e)) {\n this.isTargetingLow = true;\n this.isDragging = false;\n } else {\n this.isTargetingLow = false;\n this.isDragging = false;\n }\n this.isMouseDown = true;\n this.updateTargetValue(e);\n e.preventDefault();\n window.addEventListener('mousemove', this.onWindowMouseMove);\n window.addEventListener('mouseup', this.onWindowMouseUp);\n this.startAnimation();\n }\n\n private onWindowMouseMove = (e: MouseEvent) => {\n this.onMouseMove(e);\n };\n\n private onWindowMouseUp = () => {\n this.onMouseUp();\n };\n\n private onMouseMove(e: MouseEvent) {\n if (this.isMouseDown) {\n this.updateTargetValue(e);\n }\n }\n\n private onMouseUp() {\n this.isMouseDown = false;\n this.isDragging = false;\n window.removeEventListener('mousemove', this.onWindowMouseMove);\n window.removeEventListener('mouseup', this.onWindowMouseUp);\n this.stopAnimation();\n }\n\n private updateTargetValue(e: MouseEvent) {\n const unroundedValue = this.isTargetingLow\n ? this.lowClickValue(e)\n : this.highClickValue(e);\n if (this.step) {\n this.targetValue = Math.round(unroundedValue / this.step) * this.step;\n } else {\n this.targetValue = unroundedValue;\n }\n if (this.isTargetingLow) {\n this.targetValue = Math.max(\n this.min,\n Math.min(this.targetValue, this.high)\n );\n } else {\n this.targetValue = Math.min(\n this.max,\n Math.max(this.targetValue, this.low)\n );\n }\n }\n\n private startAnimation() {\n this.isDragging = this.allowSeeking;\n this.animationStartTime = performance.now();\n this.animationStartValue = this.isTargetingLow ? this.low : this.high;\n const min = this.min;\n const max = this.max;\n const step = this.step;\n const duration = (1 / this.seekingSpeed) * 1000; // ms\n const direction = this.targetValue > this.animationStartValue ? 1 : -1;\n\n const animate = () => {\n let nextValue = this.targetValue;\n if (!this.isDragging) {\n const now = performance.now();\n const elapsed = now - (this.animationStartTime ?? now);\n const range = Math.abs(max - min);\n // How much of the range should be covered by now\n const expectedProgress = Math.min(elapsed / duration, 1);\n const expectedValue =\n this.animationStartValue + direction * range * expectedProgress;\n // Snap to step\n if (direction > 0) {\n nextValue =\n step === undefined\n ? expectedValue\n : Math.ceil(expectedValue - min / step) * step + min;\n nextValue = Math.min(this.targetValue, nextValue);\n } else {\n nextValue =\n step === undefined\n ? expectedValue\n : Math.floor((expectedValue - min) / step) * step + min;\n nextValue = Math.max(this.targetValue, nextValue);\n }\n }\n // Only update if value actually changes\n const isValueChanged = this.isTargetingLow\n ? this.low !== nextValue\n : this.high !== nextValue;\n if (isValueChanged) {\n if (this.isTargetingLow) {\n this.low = nextValue;\n } else {\n this.high = nextValue;\n }\n this.dispatchEvent(\n new CustomEvent('value', {detail: {low: this.low, high: this.high}})\n );\n }\n // Continue animating if not at target\n if (\n (direction > 0 && nextValue < this.targetValue) ||\n (direction < 0 && nextValue > this.targetValue)\n ) {\n this.animationFrame = requestAnimationFrame(animate);\n } else if (this.isMouseDown) {\n // If mouse is still down, wait for new target\n this.animationStartTime = performance.now();\n this.animationStartValue = this.isTargetingLow ? this.low : this.high;\n this.animationFrame = requestAnimationFrame(animate);\n this.isDragging = true;\n }\n };\n\n this.animationFrame = requestAnimationFrame(animate);\n }\n\n private stopAnimation() {\n if (this.animationFrame !== null) {\n cancelAnimationFrame(this.animationFrame);\n this.animationFrame = null;\n }\n }\n\n private formatLabel(value: number) {\n return value.toFixed(this.labelDecimals) + this.labelUnit;\n }\n\n override render() {\n return html`\n ${this.showLeftReadout\n ? html`\n <div\n class=${classMap({\n label: true,\n min: true,\n disabled: this.disabled,\n })}\n style=\"width: ${this.labelWidth};\"\n >\n <slot name=\"left-readout\">${this.formatLabel(this.low)}</slot>\n </div>\n `\n : null}\n <div\n class=${classMap({\n wrapper: true,\n [this.variant]: true,\n mouseDown: this.isMouseDown,\n dragging: this.isDragging,\n disabled: this.disabled,\n })}\n style=${styleMap({\n '--_low-ratio': String(this.lowRatio),\n '--_high-ratio': String(this.highRatio),\n })}\n @mousedown=${this.onMouseDown}\n @mouseup=${this.onMouseUp}\n @mousemove=${this.onMouseMove}\n >\n <div class=\"track\"></div>\n <input\n type=\"range\"\n min=${this.min}\n max=${this.max}\n class=\"slider min\"\n step=${ifDefined(this.step)}\n .value=${this.low.toString()}\n ?disabled=${this.variant === ObcSliderDoubleVariant.NoInput ||\n this.disabled}\n @input=${this.onInput}\n />\n <input\n type=\"range\"\n class=\"slider max\"\n min=${this.min}\n max=${this.max}\n step=${ifDefined(this.step)}\n .value=${this.high.toString()}\n ?disabled=${this.variant === ObcSliderDoubleVariant.NoInput ||\n this.disabled}\n @input=${this.onInput}\n />\n <div class=\"interactive-track\"></div>\n <div class=\"thumb min\"></div>\n <div class=\"thumb max\"></div>\n </div>\n ${this.showRightReadout\n ? html`\n <div\n class=${classMap({\n label: true,\n max: true,\n disabled: this.disabled,\n })}\n style=\"width: ${this.labelWidth};\"\n >\n <slot name=\"right-readout\">${this.formatLabel(this.high)}</slot>\n </div>\n `\n : null}\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-slider-double': ObcSliderDouble;\n }\n}\n"],"names":["ObcSliderDoubleVariant"],"mappings":"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"}
1
+ {"version":3,"file":"slider-double.js","sources":["../../../src/components/slider-double/slider-double.ts"],"sourcesContent":["import {LitElement, html, unsafeCSS} from 'lit';\nimport {property, query} from 'lit/decorators.js';\nimport {ifDefined} from 'lit/directives/if-defined.js';\nimport {styleMap} from 'lit/directives/style-map.js';\nimport componentStyle from './slider-double.css?inline';\nimport '../icon-button/icon-button.js';\nimport {classMap} from 'lit/directives/class-map.js';\nimport {customElement} from '../../decorator.js';\n\n/**\n * Enum for slider double variants.\n *\n * - `normal`: Standard slider with default styling and interaction.\n * - `enhanced`: Visually enhanced slider with larger track and thumb, suitable for more prominent or touch-friendly UIs.\n * - `no-input`: Non-interactive display mode; disables all user input and presents the slider as read-only.\n */\nexport enum ObcSliderDoubleVariant {\n Normal = 'normal',\n Enhanced = 'enhanced',\n NoInput = 'no-input',\n}\n\n/**\n * Event type for value changes in obc-slider-double.\n * Contains the current low and high values of the slider.\n */\nexport type ObcSliderDoubleValueEvent = CustomEvent<{\n low: number;\n high: number;\n}>;\n\n/**\n * Event type for change event in obc-slider-double (fired after user interaction completes).\n * Contains the current low and high values of the slider.\n */\nexport type ObcSliderDoubleChangeEvent = CustomEvent<{\n low: number;\n high: number;\n}>;\n\n/**\n * `<obc-slider-double>` – A dual-thumb range slider for selecting a value interval within a defined range.\n *\n * This component allows users to select a minimum and maximum value by dragging two thumbs along a horizontal track. It is commonly used for filtering or specifying ranges (such as price, speed, or time intervals) in forms and dashboards. The slider supports both interactive and read-only display modes, as well as visual variants for different UI needs.\n *\n * Appears with two draggable handles (thumbs) and labels showing the current low and high values. Optionally, icons can be placed at each end of the slider via slots.\n *\n * ## Features\n * - **Dual-thumb range selection:** Users can adjust both the lower and upper bounds of a numeric interval.\n * - **Variants:**\n * - **Normal:** Standard slider with compact styling.\n * - **Enhanced:** Larger track and thumb for increased prominence or touch accessibility.\n * - **NoInput:** Read-only mode; disables all user interaction and presents the current range as static.\n * - **Configurable range:** Set minimum (`min`), maximum (`max`), and step size (`step`) for precise control.\n * - **Step click adjustment:** Use `stepClick` to define increment/decrement amount for keyboard or button-based changes.\n * - **Seeking mode:** Enable `allowSeeking` to let users jump to a value by clicking on the track, with smooth animated transitions controlled by `seekingSpeed`.\n * - **Custom labels:** Display formatted value labels with unit (`labelUnit`), decimal precision (`labelDecimals`), and adjustable label width (`labelWidth`).\n * - **Hug container option:** Remove spacing between slider and container edges with the `hugcontainer` attribute for seamless layout integration.\n * - **Icon slots:** Add icons to the left and right ends of the slider using `icon-left` and `icon-right` slots.\n *\n * ## Usage Guidelines\n * Use `obc-slider-double` when you need users to specify a numeric range, such as filtering results by minimum and maximum values. Ideal for scenarios like:\n * - Filtering items by price, speed, or other continuous values.\n * - Selecting a time interval or threshold range.\n * - Any UI where a bounded numeric interval is required.\n *\n * For single-value selection, use a standard slider component instead. In read-only or summary views, use the `no-input` variant to display the selected range without allowing changes.\n *\n * **TODO(designer):** Confirm if there are recommended minimum thumb separation or constraints for usability, and if there are best practices for using the enhanced variant.\n *\n * ## Slots\n *\n * | Slot Name | Renders When... | Purpose |\n * |---------------|-------------------------------|------------------------------------------------------------------------------------------------------------------|\n * | icon-left | Always | Icon or content at the left end of the slider. Example: `<obi-placeholder slot=\"icon-left\"></obi-placeholder>` |\n * | icon-right | Always | Icon or content at the right end of the slider. Example: `<obi-placeholder slot=\"icon-right\"></obi-placeholder>` |\n * | left-readout | `showLeftReadout` is true | Custom content for the left (low) readout label. Falls back to the formatted `low` value. |\n * | right-readout | `showRightReadout` is true | Custom content for the right (high) readout label. Falls back to the formatted `high` value. |\n *\n * ## Properties and Attributes\n * - `low` (number): The current lower bound of the selected range.\n * - `high` (number): The current upper bound of the selected range.\n * - `min` (number): The minimum allowed value (default: 0).\n * - `max` (number): The maximum allowed value (default: 100).\n * - `step` (number): The increment for value changes (default: 1).\n * - `stepClick` (number): Step size for keyboard or button-based changes (default: 10).\n * - `variant` (`normal` | `enhanced` | `no-input`): Visual and interaction style (default: `normal`).\n * - `allowSeeking` (boolean): If true, clicking the track animates the thumb to the clicked position.\n * - `seekingSpeed` (number): Animation speed for seeking (default: 1/3, i.e., full range in 3 seconds).\n * - `labelUnit` (string): Unit label appended to value labels (e.g., `\"%\"`, `\"kn\"`).\n * - `labelDecimals` (number): Number of decimal places for value labels.\n * - `labelWidth` (string): CSS width for value labels (e.g., `\"5ch\"`, `\"60px\"`).\n * - `showLeftReadout` (boolean, property only): Show the left (low) readout label. Default `true`.\n * - `showRightReadout` (boolean, property only): Show the right (high) readout label. Default `true`.\n * - `hugcontainer` (attribute): If present, removes spacing between slider and container edges.\n *\n * ## Events\n * - `value` – Fired continuously whenever the low or high value changes during user interaction. Event detail contains `{low, high}`.\n * - `change` – Fired only after user interaction completes (mouse release). Event detail contains `{low, high}`.\n *\n * ## Best Practices and Constraints\n * - Ensure `low` is always less than or equal to `high`; the component enforces this automatically.\n * - For accessibility, provide clear labels and units so users understand the meaning of the range.\n * - Use the `no-input` variant for summary or review screens where editing is not allowed.\n * - When using `allowSeeking`, set an appropriate `seekingSpeed` for smooth but responsive thumb movement.\n * - Avoid setting `step` too small for large ranges, as this may make precise selection difficult.\n *\n * ## Example\n *\n * ```html\n * <obc-slider-double\n * min=\"0\"\n * max=\"100\"\n * low=\"20\"\n * high=\"80\"\n * step=\"5\"\n * label-unit=\"%\"\n * label-decimals=\"0\"\n * variant=\"enhanced\"\n * allowSeeking\n * >\n * <obi-placeholder slot=\"icon-left\"></obi-placeholder>\n * <obi-placeholder slot=\"icon-right\"></obi-placeholder>\n * </obc-slider-double>\n * ```\n *\n * In this example, the slider allows selection of a percentage range from 0 to 100, with 5% increments, enhanced styling, and seeking enabled.\n *\n * @slot icon-left - Slot for the left icon\n * @slot icon-right - Slot for the right icon\n * @slot left-readout - Custom content for the left (low) readout label (rendered when `showLeftReadout` is true)\n * @slot right-readout - Custom content for the right (high) readout label (rendered when `showRightReadout` is true)\n * @fires value {ObcSliderDoubleValueEvent} - Fires when the value is changed\n * @fires change {ObcSliderDoubleChangeEvent} - Fires when user interaction completes\n */\n@customElement('obc-slider-double')\nexport class ObcSliderDouble extends LitElement {\n /**\n * The current lower bound of the selected range.\n * Must be greater than or equal to `min` and less than or equal to `high`.\n */\n @property({type: Number}) low = 0;\n\n /**\n * The current upper bound of the selected range.\n * Must be less than or equal to `max` and greater than or equal to `low`.\n */\n @property({type: Number}) high = 100;\n\n /**\n * The minimum allowed value for the slider.\n * Default is 0.\n */\n @property({type: Number}) min = 0;\n\n /**\n * The maximum allowed value for the slider.\n * Default is 100.\n */\n @property({type: Number}) max = 100;\n\n /**\n * The increment for value changes.\n * If not set, defaults to 1.\n */\n @property({type: Number}) step: number | undefined;\n\n /**\n * Step size for keyboard or button-based changes.\n * Default is 10.\n */\n @property({type: Number}) stepClick = 10;\n\n /**\n * Visual and interaction style of the slider.\n * - `normal`: Standard appearance.\n * - `enhanced`: Larger track and thumb.\n * - `no-input`: Read-only, disables user interaction.\n * Default is `normal`.\n */\n @property({type: String}) variant: ObcSliderDoubleVariant =\n ObcSliderDoubleVariant.Normal;\n\n /**\n * If true, clicking the slider track animates the thumb to the clicked position.\n * Enables seeking mode for rapid value changes.\n */\n @property({type: Boolean}) allowSeeking = false;\n\n @property({type: Boolean}) disabled = false;\n\n /**\n * Animation speed for seeking, in inverse seconds.\n * The value will go from min to max in 1 / seekingSpeed seconds.\n * Default is 1/3 (i.e., 3 seconds for full range).\n */\n @property({type: Number}) seekingSpeed = 1 / 3;\n\n /**\n * Unit label appended to value labels (e.g., \"%\", \"kn\").\n */\n @property({type: String}) labelUnit = '';\n\n /**\n * Number of decimal places to display in value labels.\n */\n @property({type: Number}) labelDecimals = 0;\n\n /**\n * CSS width for value labels (e.g., \"5ch\", \"60px\").\n */\n @property({type: String}) labelWidth = '60px';\n\n /**\n * Whether to show the left (low) readout label.\n *\n * When false, the left readout is hidden entirely. When true, the readout\n * renders the formatted `low` value or the content slotted into `left-readout`.\n *\n * Default is true. Set via JavaScript property (no HTML attribute).\n */\n @property({type: Boolean, attribute: false}) showLeftReadout = true;\n\n /**\n * Whether to show the right (high) readout label.\n *\n * When false, the right readout is hidden entirely. When true, the readout\n * renders the formatted `high` value or the content slotted into `right-readout`.\n *\n * Default is true. Set via JavaScript property (no HTML attribute).\n */\n @property({type: Boolean, attribute: false}) showRightReadout = true;\n\n /**\n * Removes spacing between the slider and its container edges for seamless\n * layout integration. Reflected to the `hugcontainer` HTML attribute.\n */\n @property({type: Boolean, reflect: true, attribute: 'hugcontainer'})\n hugContainer = false;\n\n private get lowRatio(): number {\n return this.computeRatio(this.low);\n }\n\n private get highRatio(): number {\n return this.computeRatio(this.high);\n }\n\n private computeRatio(value: number): number {\n const range = this.max - this.min;\n if (!Number.isFinite(range) || range <= 0) return 0;\n const ratio = (value - this.min) / range;\n if (!Number.isFinite(ratio)) return 0;\n return Math.max(0, Math.min(1, ratio));\n }\n\n private animationFrame: number | null = null;\n private isMouseDown = false;\n private targetValue = 0;\n private isDragging = false;\n private isTargetingLow = false;\n private animationStartTime: number | null = null;\n private animationStartValue: number = 0;\n\n @query('input[type=\"range\"].min')\n private minInput!: HTMLInputElement;\n\n @query('input[type=\"range\"].max')\n private maxInput!: HTMLInputElement;\n\n /**\n * Handles input changes from the slider thumbs.\n * Updates the low and high values and emits the `value` event.\n *\n * @fires value {ObcSliderDoubleValueEvent}\n */\n onInput() {\n let newLow = parseFloat(this.minInput.value);\n let newHigh = parseFloat(this.maxInput.value);\n if (newLow > this.high) {\n newLow = this.high;\n this.minInput.value = this.high.toString();\n }\n if (newHigh < this.low) {\n newHigh = this.low;\n this.maxInput.value = this.low.toString();\n }\n this.low = newLow;\n this.high = newHigh;\n this.dispatchEvent(\n new CustomEvent('value', {detail: {low: this.low, high: this.high}})\n );\n }\n\n /**\n * Fires the `change` event with the current low and high values.\n *\n * @fires change\n */\n private fireChangeEvent() {\n this.dispatchEvent(\n new CustomEvent('change', {\n detail: {low: this.low, high: this.high},\n }) as ObcSliderDoubleChangeEvent\n );\n }\n\n private THUMB_WIDTH = 48;\n private THUMB_VISIBLE_WIDTH = 12;\n\n private lowClickValue(e: MouseEvent) {\n const rect = this.minInput.getBoundingClientRect();\n const left = rect.left + this.THUMB_WIDTH - this.THUMB_VISIBLE_WIDTH / 2;\n const width = rect.width - this.THUMB_WIDTH;\n const percent = (e.clientX - left) / width;\n return this.min + (this.max - this.min) * percent;\n }\n\n private highClickValue(e: MouseEvent) {\n const rect = this.maxInput.getBoundingClientRect();\n const left = rect.left + this.THUMB_VISIBLE_WIDTH / 2;\n const width = rect.width - this.THUMB_WIDTH;\n const percent = (e.clientX - left) / width;\n return this.min + (this.max - this.min) * percent;\n }\n\n private thumbRange() {\n const rect = this.minInput.getBoundingClientRect();\n const valueRange = this.max - this.min;\n const percentageRange = this.THUMB_WIDTH / rect.width;\n return valueRange * percentageRange;\n }\n\n private isClickingMinThumb(e: MouseEvent) {\n const value = this.lowClickValue(e);\n if (value > this.low) {\n return false;\n }\n return value >= this.low - this.thumbRange();\n }\n\n private isClickingMaxThumb(e: MouseEvent) {\n const value = this.highClickValue(e);\n if (value < this.high) {\n return false;\n }\n return value <= this.high + this.thumbRange();\n }\n\n private isClickingLowTrack(e: MouseEvent) {\n const value = this.lowClickValue(e);\n return value <= this.low - this.thumbRange() / 2;\n }\n\n private isClickingHighTrack(e: MouseEvent) {\n const value = this.highClickValue(e);\n return value >= this.high + this.thumbRange() / 2;\n }\n\n private isClosestToLowThumb(e: MouseEvent) {\n const lowValue = this.lowClickValue(e);\n const highValue = this.highClickValue(e);\n return Math.abs(lowValue - this.low) <= Math.abs(highValue - this.high);\n }\n\n private onMouseDown(e: MouseEvent) {\n if (this.variant === ObcSliderDoubleVariant.NoInput || this.disabled)\n return;\n if (this.isClickingMinThumb(e)) {\n this.isTargetingLow = true;\n this.isDragging = true;\n } else if (this.isClickingMaxThumb(e)) {\n this.isTargetingLow = false;\n this.isDragging = true;\n } else if (this.isClickingLowTrack(e)) {\n this.isTargetingLow = true;\n this.isDragging = false;\n } else if (this.isClickingHighTrack(e)) {\n this.isTargetingLow = false;\n this.isDragging = false;\n } else if (this.isClosestToLowThumb(e)) {\n this.isTargetingLow = true;\n this.isDragging = false;\n } else {\n this.isTargetingLow = false;\n this.isDragging = false;\n }\n this.isMouseDown = true;\n this.updateTargetValue(e);\n e.preventDefault();\n window.addEventListener('mousemove', this.onWindowMouseMove);\n window.addEventListener('mouseup', this.onWindowMouseUp);\n this.startAnimation();\n }\n\n private onWindowMouseMove = (e: MouseEvent) => {\n this.onMouseMove(e);\n };\n\n private onWindowMouseUp = () => {\n this.onMouseUp();\n };\n\n private onMouseMove(e: MouseEvent) {\n if (this.isMouseDown) {\n this.updateTargetValue(e);\n }\n }\n\n private onMouseUp() {\n this.isMouseDown = false;\n this.isDragging = false;\n window.removeEventListener('mousemove', this.onWindowMouseMove);\n window.removeEventListener('mouseup', this.onWindowMouseUp);\n this.stopAnimation();\n this.fireChangeEvent();\n }\n\n private updateTargetValue(e: MouseEvent) {\n const unroundedValue = this.isTargetingLow\n ? this.lowClickValue(e)\n : this.highClickValue(e);\n if (this.step) {\n this.targetValue = Math.round(unroundedValue / this.step) * this.step;\n } else {\n this.targetValue = unroundedValue;\n }\n if (this.isTargetingLow) {\n this.targetValue = Math.max(\n this.min,\n Math.min(this.targetValue, this.high)\n );\n } else {\n this.targetValue = Math.min(\n this.max,\n Math.max(this.targetValue, this.low)\n );\n }\n }\n\n private startAnimation() {\n this.isDragging = this.allowSeeking;\n this.animationStartTime = performance.now();\n this.animationStartValue = this.isTargetingLow ? this.low : this.high;\n const min = this.min;\n const max = this.max;\n const step = this.step;\n const duration = (1 / this.seekingSpeed) * 1000; // ms\n const direction = this.targetValue > this.animationStartValue ? 1 : -1;\n\n const animate = () => {\n let nextValue = this.targetValue;\n if (!this.isDragging) {\n const now = performance.now();\n const elapsed = now - (this.animationStartTime ?? now);\n const range = Math.abs(max - min);\n // How much of the range should be covered by now\n const expectedProgress = Math.min(elapsed / duration, 1);\n const expectedValue =\n this.animationStartValue + direction * range * expectedProgress;\n // Snap to step\n if (direction > 0) {\n nextValue =\n step === undefined\n ? expectedValue\n : Math.ceil(expectedValue - min / step) * step + min;\n nextValue = Math.min(this.targetValue, nextValue);\n } else {\n nextValue =\n step === undefined\n ? expectedValue\n : Math.floor((expectedValue - min) / step) * step + min;\n nextValue = Math.max(this.targetValue, nextValue);\n }\n }\n // Only update if value actually changes\n const isValueChanged = this.isTargetingLow\n ? this.low !== nextValue\n : this.high !== nextValue;\n if (isValueChanged) {\n if (this.isTargetingLow) {\n this.low = nextValue;\n } else {\n this.high = nextValue;\n }\n this.dispatchEvent(\n new CustomEvent('value', {detail: {low: this.low, high: this.high}})\n );\n }\n // Continue animating if not at target\n if (\n (direction > 0 && nextValue < this.targetValue) ||\n (direction < 0 && nextValue > this.targetValue)\n ) {\n this.animationFrame = requestAnimationFrame(animate);\n } else if (this.isMouseDown) {\n // If mouse is still down, wait for new target\n this.animationStartTime = performance.now();\n this.animationStartValue = this.isTargetingLow ? this.low : this.high;\n this.animationFrame = requestAnimationFrame(animate);\n this.isDragging = true;\n }\n };\n\n this.animationFrame = requestAnimationFrame(animate);\n }\n\n private stopAnimation() {\n if (this.animationFrame !== null) {\n cancelAnimationFrame(this.animationFrame);\n this.animationFrame = null;\n }\n }\n\n private formatLabel(value: number) {\n return value.toFixed(this.labelDecimals) + this.labelUnit;\n }\n\n override render() {\n return html`\n ${this.showLeftReadout\n ? html`\n <div\n class=${classMap({\n label: true,\n min: true,\n disabled: this.disabled,\n })}\n style=\"width: ${this.labelWidth};\"\n >\n <slot name=\"left-readout\">${this.formatLabel(this.low)}</slot>\n </div>\n `\n : null}\n <div\n class=${classMap({\n wrapper: true,\n [this.variant]: true,\n mouseDown: this.isMouseDown,\n dragging: this.isDragging,\n disabled: this.disabled,\n })}\n style=${styleMap({\n '--_low-ratio': String(this.lowRatio),\n '--_high-ratio': String(this.highRatio),\n })}\n @mousedown=${this.onMouseDown}\n @mouseup=${this.onMouseUp}\n @mousemove=${this.onMouseMove}\n >\n <div class=\"track\"></div>\n <input\n type=\"range\"\n min=${this.min}\n max=${this.max}\n class=\"slider min\"\n step=${ifDefined(this.step)}\n .value=${this.low.toString()}\n ?disabled=${this.variant === ObcSliderDoubleVariant.NoInput ||\n this.disabled}\n @input=${this.onInput}\n @change=${() => this.fireChangeEvent()}\n />\n <input\n type=\"range\"\n class=\"slider max\"\n min=${this.min}\n max=${this.max}\n step=${ifDefined(this.step)}\n .value=${this.high.toString()}\n ?disabled=${this.variant === ObcSliderDoubleVariant.NoInput ||\n this.disabled}\n @input=${this.onInput}\n @change=${() => this.fireChangeEvent()}\n />\n <div class=\"interactive-track\"></div>\n <div class=\"thumb min\"></div>\n <div class=\"thumb max\"></div>\n </div>\n ${this.showRightReadout\n ? html`\n <div\n class=${classMap({\n label: true,\n max: true,\n disabled: this.disabled,\n })}\n style=\"width: ${this.labelWidth};\"\n >\n <slot name=\"right-readout\">${this.formatLabel(this.high)}</slot>\n </div>\n `\n : null}\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-slider-double': ObcSliderDouble;\n }\n}\n"],"names":["ObcSliderDoubleVariant"],"mappings":";;;;;;;;;;;;;;;;;;AAgBO,IAAK,2CAAAA,4BAAL;AACLA,0BAAA,QAAA,IAAS;AACTA,0BAAA,UAAA,IAAW;AACXA,0BAAA,SAAA,IAAU;AAHA,SAAAA;AAAA,GAAA,0BAAA,CAAA,CAAA;AAwHL,IAAM,kBAAN,cAA8B,WAAW;AAAA,EAAzC,cAAA;AAAA,UAAA,GAAA,SAAA;AAKqB,SAAA,MAAM;AAMN,SAAA,OAAO;AAMP,SAAA,MAAM;AAMN,SAAA,MAAM;AAYN,SAAA,YAAY;AASZ,SAAA,UACxB;AAMyB,SAAA,eAAe;AAEf,SAAA,WAAW;AAOZ,SAAA,eAAe,IAAI;AAKnB,SAAA,YAAY;AAKZ,SAAA,gBAAgB;AAKhB,SAAA,aAAa;AAUM,SAAA,kBAAkB;AAUlB,SAAA,mBAAmB;AAOhE,SAAA,eAAe;AAkBf,SAAQ,iBAAgC;AACxC,SAAQ,cAAc;AACtB,SAAQ,cAAc;AACtB,SAAQ,aAAa;AACrB,SAAQ,iBAAiB;AACzB,SAAQ,qBAAoC;AAC5C,SAAQ,sBAA8B;AA6CtC,SAAQ,cAAc;AACtB,SAAQ,sBAAsB;AAuF9B,SAAQ,oBAAoB,CAAC,MAAkB;AAC7C,WAAK,YAAY,CAAC;AAAA,IACpB;AAEA,SAAQ,kBAAkB,MAAM;AAC9B,WAAK,UAAA;AAAA,IACP;AAAA,EAAA;AAAA,EAjKA,IAAY,WAAmB;AAC7B,WAAO,KAAK,aAAa,KAAK,GAAG;AAAA,EACnC;AAAA,EAEA,IAAY,YAAoB;AAC9B,WAAO,KAAK,aAAa,KAAK,IAAI;AAAA,EACpC;AAAA,EAEQ,aAAa,OAAuB;AAC1C,UAAM,QAAQ,KAAK,MAAM,KAAK;AAC9B,QAAI,CAAC,OAAO,SAAS,KAAK,KAAK,SAAS,EAAG,QAAO;AAClD,UAAM,SAAS,QAAQ,KAAK,OAAO;AACnC,QAAI,CAAC,OAAO,SAAS,KAAK,EAAG,QAAO;AACpC,WAAO,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,CAAC;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,UAAU;AACR,QAAI,SAAS,WAAW,KAAK,SAAS,KAAK;AAC3C,QAAI,UAAU,WAAW,KAAK,SAAS,KAAK;AAC5C,QAAI,SAAS,KAAK,MAAM;AACtB,eAAS,KAAK;AACd,WAAK,SAAS,QAAQ,KAAK,KAAK,SAAA;AAAA,IAClC;AACA,QAAI,UAAU,KAAK,KAAK;AACtB,gBAAU,KAAK;AACf,WAAK,SAAS,QAAQ,KAAK,IAAI,SAAA;AAAA,IACjC;AACA,SAAK,MAAM;AACX,SAAK,OAAO;AACZ,SAAK;AAAA,MACH,IAAI,YAAY,SAAS,EAAC,QAAQ,EAAC,KAAK,KAAK,KAAK,MAAM,KAAK,KAAA,GAAM;AAAA,IAAA;AAAA,EAEvE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,kBAAkB;AACxB,SAAK;AAAA,MACH,IAAI,YAAY,UAAU;AAAA,QACxB,QAAQ,EAAC,KAAK,KAAK,KAAK,MAAM,KAAK,KAAA;AAAA,MAAI,CACxC;AAAA,IAAA;AAAA,EAEL;AAAA,EAKQ,cAAc,GAAe;AACnC,UAAM,OAAO,KAAK,SAAS,sBAAA;AAC3B,UAAM,OAAO,KAAK,OAAO,KAAK,cAAc,KAAK,sBAAsB;AACvE,UAAM,QAAQ,KAAK,QAAQ,KAAK;AAChC,UAAM,WAAW,EAAE,UAAU,QAAQ;AACrC,WAAO,KAAK,OAAO,KAAK,MAAM,KAAK,OAAO;AAAA,EAC5C;AAAA,EAEQ,eAAe,GAAe;AACpC,UAAM,OAAO,KAAK,SAAS,sBAAA;AAC3B,UAAM,OAAO,KAAK,OAAO,KAAK,sBAAsB;AACpD,UAAM,QAAQ,KAAK,QAAQ,KAAK;AAChC,UAAM,WAAW,EAAE,UAAU,QAAQ;AACrC,WAAO,KAAK,OAAO,KAAK,MAAM,KAAK,OAAO;AAAA,EAC5C;AAAA,EAEQ,aAAa;AACnB,UAAM,OAAO,KAAK,SAAS,sBAAA;AAC3B,UAAM,aAAa,KAAK,MAAM,KAAK;AACnC,UAAM,kBAAkB,KAAK,cAAc,KAAK;AAChD,WAAO,aAAa;AAAA,EACtB;AAAA,EAEQ,mBAAmB,GAAe;AACxC,UAAM,QAAQ,KAAK,cAAc,CAAC;AAClC,QAAI,QAAQ,KAAK,KAAK;AACpB,aAAO;AAAA,IACT;AACA,WAAO,SAAS,KAAK,MAAM,KAAK,WAAA;AAAA,EAClC;AAAA,EAEQ,mBAAmB,GAAe;AACxC,UAAM,QAAQ,KAAK,eAAe,CAAC;AACnC,QAAI,QAAQ,KAAK,MAAM;AACrB,aAAO;AAAA,IACT;AACA,WAAO,SAAS,KAAK,OAAO,KAAK,WAAA;AAAA,EACnC;AAAA,EAEQ,mBAAmB,GAAe;AACxC,UAAM,QAAQ,KAAK,cAAc,CAAC;AAClC,WAAO,SAAS,KAAK,MAAM,KAAK,eAAe;AAAA,EACjD;AAAA,EAEQ,oBAAoB,GAAe;AACzC,UAAM,QAAQ,KAAK,eAAe,CAAC;AACnC,WAAO,SAAS,KAAK,OAAO,KAAK,eAAe;AAAA,EAClD;AAAA,EAEQ,oBAAoB,GAAe;AACzC,UAAM,WAAW,KAAK,cAAc,CAAC;AACrC,UAAM,YAAY,KAAK,eAAe,CAAC;AACvC,WAAO,KAAK,IAAI,WAAW,KAAK,GAAG,KAAK,KAAK,IAAI,YAAY,KAAK,IAAI;AAAA,EACxE;AAAA,EAEQ,YAAY,GAAe;AACjC,QAAI,KAAK,YAAY,cAAkC,KAAK;AAC1D;AACF,QAAI,KAAK,mBAAmB,CAAC,GAAG;AAC9B,WAAK,iBAAiB;AACtB,WAAK,aAAa;AAAA,IACpB,WAAW,KAAK,mBAAmB,CAAC,GAAG;AACrC,WAAK,iBAAiB;AACtB,WAAK,aAAa;AAAA,IACpB,WAAW,KAAK,mBAAmB,CAAC,GAAG;AACrC,WAAK,iBAAiB;AACtB,WAAK,aAAa;AAAA,IACpB,WAAW,KAAK,oBAAoB,CAAC,GAAG;AACtC,WAAK,iBAAiB;AACtB,WAAK,aAAa;AAAA,IACpB,WAAW,KAAK,oBAAoB,CAAC,GAAG;AACtC,WAAK,iBAAiB;AACtB,WAAK,aAAa;AAAA,IACpB,OAAO;AACL,WAAK,iBAAiB;AACtB,WAAK,aAAa;AAAA,IACpB;AACA,SAAK,cAAc;AACnB,SAAK,kBAAkB,CAAC;AACxB,MAAE,eAAA;AACF,WAAO,iBAAiB,aAAa,KAAK,iBAAiB;AAC3D,WAAO,iBAAiB,WAAW,KAAK,eAAe;AACvD,SAAK,eAAA;AAAA,EACP;AAAA,EAUQ,YAAY,GAAe;AACjC,QAAI,KAAK,aAAa;AACpB,WAAK,kBAAkB,CAAC;AAAA,IAC1B;AAAA,EACF;AAAA,EAEQ,YAAY;AAClB,SAAK,cAAc;AACnB,SAAK,aAAa;AAClB,WAAO,oBAAoB,aAAa,KAAK,iBAAiB;AAC9D,WAAO,oBAAoB,WAAW,KAAK,eAAe;AAC1D,SAAK,cAAA;AACL,SAAK,gBAAA;AAAA,EACP;AAAA,EAEQ,kBAAkB,GAAe;AACvC,UAAM,iBAAiB,KAAK,iBACxB,KAAK,cAAc,CAAC,IACpB,KAAK,eAAe,CAAC;AACzB,QAAI,KAAK,MAAM;AACb,WAAK,cAAc,KAAK,MAAM,iBAAiB,KAAK,IAAI,IAAI,KAAK;AAAA,IACnE,OAAO;AACL,WAAK,cAAc;AAAA,IACrB;AACA,QAAI,KAAK,gBAAgB;AACvB,WAAK,cAAc,KAAK;AAAA,QACtB,KAAK;AAAA,QACL,KAAK,IAAI,KAAK,aAAa,KAAK,IAAI;AAAA,MAAA;AAAA,IAExC,OAAO;AACL,WAAK,cAAc,KAAK;AAAA,QACtB,KAAK;AAAA,QACL,KAAK,IAAI,KAAK,aAAa,KAAK,GAAG;AAAA,MAAA;AAAA,IAEvC;AAAA,EACF;AAAA,EAEQ,iBAAiB;AACvB,SAAK,aAAa,KAAK;AACvB,SAAK,qBAAqB,YAAY,IAAA;AACtC,SAAK,sBAAsB,KAAK,iBAAiB,KAAK,MAAM,KAAK;AACjE,UAAM,MAAM,KAAK;AACjB,UAAM,MAAM,KAAK;AACjB,UAAM,OAAO,KAAK;AAClB,UAAM,WAAY,IAAI,KAAK,eAAgB;AAC3C,UAAM,YAAY,KAAK,cAAc,KAAK,sBAAsB,IAAI;AAEpE,UAAM,UAAU,MAAM;AACpB,UAAI,YAAY,KAAK;AACrB,UAAI,CAAC,KAAK,YAAY;AACpB,cAAM,MAAM,YAAY,IAAA;AACxB,cAAM,UAAU,OAAO,KAAK,sBAAsB;AAClD,cAAM,QAAQ,KAAK,IAAI,MAAM,GAAG;AAEhC,cAAM,mBAAmB,KAAK,IAAI,UAAU,UAAU,CAAC;AACvD,cAAM,gBACJ,KAAK,sBAAsB,YAAY,QAAQ;AAEjD,YAAI,YAAY,GAAG;AACjB,sBACE,SAAS,SACL,gBACA,KAAK,KAAK,gBAAgB,MAAM,IAAI,IAAI,OAAO;AACrD,sBAAY,KAAK,IAAI,KAAK,aAAa,SAAS;AAAA,QAClD,OAAO;AACL,sBACE,SAAS,SACL,gBACA,KAAK,OAAO,gBAAgB,OAAO,IAAI,IAAI,OAAO;AACxD,sBAAY,KAAK,IAAI,KAAK,aAAa,SAAS;AAAA,QAClD;AAAA,MACF;AAEA,YAAM,iBAAiB,KAAK,iBACxB,KAAK,QAAQ,YACb,KAAK,SAAS;AAClB,UAAI,gBAAgB;AAClB,YAAI,KAAK,gBAAgB;AACvB,eAAK,MAAM;AAAA,QACb,OAAO;AACL,eAAK,OAAO;AAAA,QACd;AACA,aAAK;AAAA,UACH,IAAI,YAAY,SAAS,EAAC,QAAQ,EAAC,KAAK,KAAK,KAAK,MAAM,KAAK,KAAA,GAAM;AAAA,QAAA;AAAA,MAEvE;AAEA,UACG,YAAY,KAAK,YAAY,KAAK,eAClC,YAAY,KAAK,YAAY,KAAK,aACnC;AACA,aAAK,iBAAiB,sBAAsB,OAAO;AAAA,MACrD,WAAW,KAAK,aAAa;AAE3B,aAAK,qBAAqB,YAAY,IAAA;AACtC,aAAK,sBAAsB,KAAK,iBAAiB,KAAK,MAAM,KAAK;AACjE,aAAK,iBAAiB,sBAAsB,OAAO;AACnD,aAAK,aAAa;AAAA,MACpB;AAAA,IACF;AAEA,SAAK,iBAAiB,sBAAsB,OAAO;AAAA,EACrD;AAAA,EAEQ,gBAAgB;AACtB,QAAI,KAAK,mBAAmB,MAAM;AAChC,2BAAqB,KAAK,cAAc;AACxC,WAAK,iBAAiB;AAAA,IACxB;AAAA,EACF;AAAA,EAEQ,YAAY,OAAe;AACjC,WAAO,MAAM,QAAQ,KAAK,aAAa,IAAI,KAAK;AAAA,EAClD;AAAA,EAES,SAAS;AAChB,WAAO;AAAA,QACH,KAAK,kBACH;AAAA;AAAA,sBAEY,SAAS;AAAA,MACf,OAAO;AAAA,MACP,KAAK;AAAA,MACL,UAAU,KAAK;AAAA,IAAA,CAChB,CAAC;AAAA,8BACc,KAAK,UAAU;AAAA;AAAA,0CAEH,KAAK,YAAY,KAAK,GAAG,CAAC;AAAA;AAAA,cAG1D,IAAI;AAAA;AAAA,gBAEE,SAAS;AAAA,MACf,SAAS;AAAA,MACT,CAAC,KAAK,OAAO,GAAG;AAAA,MAChB,WAAW,KAAK;AAAA,MAChB,UAAU,KAAK;AAAA,MACf,UAAU,KAAK;AAAA,IAAA,CAChB,CAAC;AAAA,gBACM,SAAS;AAAA,MACf,gBAAgB,OAAO,KAAK,QAAQ;AAAA,MACpC,iBAAiB,OAAO,KAAK,SAAS;AAAA,IAAA,CACvC,CAAC;AAAA,qBACW,KAAK,WAAW;AAAA,mBAClB,KAAK,SAAS;AAAA,qBACZ,KAAK,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA,gBAKrB,KAAK,GAAG;AAAA,gBACR,KAAK,GAAG;AAAA;AAAA,iBAEP,UAAU,KAAK,IAAI,CAAC;AAAA,mBAClB,KAAK,IAAI,SAAA,CAAU;AAAA,sBAChB,KAAK,YAAY,cAC7B,KAAK,QAAQ;AAAA,mBACJ,KAAK,OAAO;AAAA,oBACX,MAAM,KAAK,gBAAA,CAAiB;AAAA;AAAA;AAAA;AAAA;AAAA,gBAKhC,KAAK,GAAG;AAAA,gBACR,KAAK,GAAG;AAAA,iBACP,UAAU,KAAK,IAAI,CAAC;AAAA,mBAClB,KAAK,KAAK,SAAA,CAAU;AAAA,sBACjB,KAAK,YAAY,cAC7B,KAAK,QAAQ;AAAA,mBACJ,KAAK,OAAO;AAAA,oBACX,MAAM,KAAK,gBAAA,CAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMxC,KAAK,mBACH;AAAA;AAAA,sBAEY,SAAS;AAAA,MACf,OAAO;AAAA,MACP,KAAK;AAAA,MACL,UAAU,KAAK;AAAA,IAAA,CAChB,CAAC;AAAA,8BACc,KAAK,UAAU;AAAA;AAAA,2CAEF,KAAK,YAAY,KAAK,IAAI,CAAC;AAAA;AAAA,cAG5D,IAAI;AAAA;AAAA,EAEZ;AAGF;AA7ca,gBA4cK,SAAS,UAAU,cAAc;AAvcvB,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GALb,gBAKe,WAAA,OAAA,CAAA;AAMA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAXb,gBAWe,WAAA,QAAA,CAAA;AAMA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAjBb,gBAiBe,WAAA,OAAA,CAAA;AAMA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAvBb,gBAuBe,WAAA,OAAA,CAAA;AAMA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GA7Bb,gBA6Be,WAAA,QAAA,CAAA;AAMA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAnCb,gBAmCe,WAAA,aAAA,CAAA;AASA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GA5Cb,gBA4Ce,WAAA,WAAA,CAAA;AAOC,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAnDd,gBAmDgB,WAAA,gBAAA,CAAA;AAEA,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GArDd,gBAqDgB,WAAA,YAAA,CAAA;AAOD,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GA5Db,gBA4De,WAAA,gBAAA,CAAA;AAKA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAjEb,gBAiEe,WAAA,aAAA,CAAA;AAKA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAtEb,gBAsEe,WAAA,iBAAA,CAAA;AAKA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GA3Eb,gBA2Ee,WAAA,cAAA,CAAA;AAUmB,gBAAA;AAAA,EAA5C,SAAS,EAAC,MAAM,SAAS,WAAW,OAAM;AAAA,GArFhC,gBAqFkC,WAAA,mBAAA,CAAA;AAUA,gBAAA;AAAA,EAA5C,SAAS,EAAC,MAAM,SAAS,WAAW,OAAM;AAAA,GA/FhC,gBA+FkC,WAAA,oBAAA,CAAA;AAO7C,gBAAA;AAAA,EADC,SAAS,EAAC,MAAM,SAAS,SAAS,MAAM,WAAW,gBAAe;AAAA,GArGxD,gBAsGX,WAAA,gBAAA,CAAA;AA2BQ,gBAAA;AAAA,EADP,MAAM,yBAAyB;AAAA,GAhIrB,gBAiIH,WAAA,YAAA,CAAA;AAGA,gBAAA;AAAA,EADP,MAAM,yBAAyB;AAAA,GAnIrB,gBAoIH,WAAA,YAAA,CAAA;AApIG,kBAAN,gBAAA;AAAA,EADN,cAAc,mBAAmB;AAAA,GACrB,eAAA;"}
@@ -4,6 +4,9 @@ export type ObcToggleButtonGroupValueChangeEvent = CustomEvent<{
4
4
  value: string;
5
5
  previousValue: string;
6
6
  }>;
7
+ export type ObcToggleButtonGroupChangeEvent = CustomEvent<{
8
+ value: string;
9
+ }>;
7
10
  /**
8
11
  * `<obc-toggle-button-group>` – A segmented control for selecting a single option from a set (also known as a button group or segmented button).
9
12
  *
@@ -112,6 +115,7 @@ export type ObcToggleButtonGroupValueChangeEvent = CustomEvent<{
112
115
  *
113
116
  * @slot - Place one or more `<obc-toggle-button-option>` elements here to define the selectable options.
114
117
  * @fires value {CustomEvent<{value: string, previousValue: string}>} Fired when the selected value changes.
118
+ * @fires change {CustomEvent<{value: string}>} Fired when the selected value changes by user interaction.
115
119
  */
116
120
  export declare class ObcToggleButtonGroup extends LitElement {
117
121
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"toggle-button-group.d.ts","sourceRoot":"","sources":["../../../src/components/toggle-button-group/toggle-button-group.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,cAAc,EAAkB,MAAM,KAAK,CAAC;AAEhE,OAAO,EACL,qBAAqB,EACrB,4BAA4B,EAC5B,yBAAyB,EAC1B,MAAM,iDAAiD,CAAC;AAKzD,MAAM,MAAM,oCAAoC,GAAG,WAAW,CAAC;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4GG;AACH,qBACa,oBAAqB,SAAQ,UAAU;IAClD;;;;;;OAMG;IACuB,KAAK,SAAM;IAErC;;;;;OAKG;IACuB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAExD;;;;;;;;;OASG;IACuB,IAAI,4BAAkC;IAEhE;;;;;;;;OAQG;IACuB,OAAO,+BAAwC;IAEzE;;;;OAIG;IACwB,OAAO,UAAS;IAE3C;;;;;;OAMG;IACwB,eAAe,UAAS;IAEnD;;;;;;;;OAQG;IACwB,mBAAmB,UAAS;IAEvD;;;;OAIG;IACuC,QAAQ,UAAS;IAE3D;;;;OAIG;IACuC,KAAK,UAAS;IAGxD,OAAO,EAAG,UAAU,CAAC,qBAAqB,CAAC,CAAC;IAE5C,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,wBAAwB;IAKhC,OAAO,CAAC,eAAe;IA4CvB,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,YAAY;IAgBpB,OAAO,CAAC,uBAAuB,CAA6C;cAEzD,YAAY,CAC7B,kBAAkB,EAAE,cAAc,CAAC,OAAO,CAAC,GAAG,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,GACtE,IAAI;IAgEP,OAAO,CAAC,0BAA0B;IAclC,iBAAiB,CAAC,KAAK,EAAE,KAAK;IAarB,UAAU,CAAC,iBAAiB,EAAE,cAAc;IAsC5C,OAAO,CAAC,iBAAiB,EAAE,cAAc;IAgBzC,MAAM;IAoBf,OAAgB,MAAM,0BAA6B;CACpD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,yBAAyB,EAAE,oBAAoB,CAAC;KACjD;CACF"}
1
+ {"version":3,"file":"toggle-button-group.d.ts","sourceRoot":"","sources":["../../../src/components/toggle-button-group/toggle-button-group.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,cAAc,EAAkB,MAAM,KAAK,CAAC;AAEhE,OAAO,EACL,qBAAqB,EACrB,4BAA4B,EAC5B,yBAAyB,EAC1B,MAAM,iDAAiD,CAAC;AAKzD,MAAM,MAAM,oCAAoC,GAAG,WAAW,CAAC;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC,CAAC;AAEH,MAAM,MAAM,+BAA+B,GAAG,WAAW,CAAC;IACxD,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6GG;AACH,qBACa,oBAAqB,SAAQ,UAAU;IAClD;;;;;;OAMG;IACuB,KAAK,SAAM;IAErC;;;;;OAKG;IACuB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAExD;;;;;;;;;OASG;IACuB,IAAI,4BAAkC;IAEhE;;;;;;;;OAQG;IACuB,OAAO,+BAAwC;IAEzE;;;;OAIG;IACwB,OAAO,UAAS;IAE3C;;;;;;OAMG;IACwB,eAAe,UAAS;IAEnD;;;;;;;;OAQG;IACwB,mBAAmB,UAAS;IAEvD;;;;OAIG;IACuC,QAAQ,UAAS;IAE3D;;;;OAIG;IACuC,KAAK,UAAS;IAGxD,OAAO,EAAG,UAAU,CAAC,qBAAqB,CAAC,CAAC;IAE5C,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,wBAAwB;IAKhC,OAAO,CAAC,eAAe;IAwDvB,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,YAAY;IAgBpB,OAAO,CAAC,uBAAuB,CAA6C;cAEzD,YAAY,CAC7B,kBAAkB,EAAE,cAAc,CAAC,OAAO,CAAC,GAAG,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,GACtE,IAAI;IAgEP,OAAO,CAAC,0BAA0B;IAclC,iBAAiB,CAAC,KAAK,EAAE,KAAK;IAmBrB,UAAU,CAAC,iBAAiB,EAAE,cAAc;IAsC5C,OAAO,CAAC,iBAAiB,EAAE,cAAc;IAgBzC,MAAM;IAoBf,OAAgB,MAAM,0BAA6B;CACpD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,yBAAyB,EAAE,oBAAoB,CAAC;KACjD;CACF"}
@@ -43,7 +43,7 @@ let ObcToggleButtonGroup = class extends LitElement {
43
43
  if (this.disabled) return null;
44
44
  return Array.from(this.options).find((opt) => !opt.disabled) || null;
45
45
  }
46
- updateSelection(newValue, emitEvent = true) {
46
+ updateSelection(newValue, emitValueEvent = true, emitChangeEvent = false) {
47
47
  const oldValue = this.value;
48
48
  if (!this.hasAnyEnabledOption()) {
49
49
  this.options.forEach((option) => {
@@ -72,13 +72,20 @@ let ObcToggleButtonGroup = class extends LitElement {
72
72
  option.selected = option.value === newValue;
73
73
  });
74
74
  this.setNoDivider();
75
- if (emitEvent && oldValue !== newValue) {
75
+ if (emitValueEvent && oldValue !== newValue) {
76
76
  this.dispatchEvent(
77
77
  new CustomEvent("value", {
78
78
  detail: { value: newValue, previousValue: oldValue }
79
79
  })
80
80
  );
81
81
  }
82
+ if (emitChangeEvent && oldValue !== newValue) {
83
+ this.dispatchEvent(
84
+ new CustomEvent("change", {
85
+ detail: { value: newValue }
86
+ })
87
+ );
88
+ }
82
89
  }
83
90
  updateActivated(newValue) {
84
91
  if (newValue) {
@@ -179,8 +186,13 @@ let ObcToggleButtonGroup = class extends LitElement {
179
186
  detail: { value, previousValue: this.value }
180
187
  })
181
188
  );
189
+ this.dispatchEvent(
190
+ new CustomEvent("change", {
191
+ detail: { value }
192
+ })
193
+ );
182
194
  } else {
183
- this.updateSelection(value);
195
+ this.updateSelection(value, true, true);
184
196
  }
185
197
  }
186
198
  willUpdate(changedProperties) {
@@ -1 +1 @@
1
- {"version":3,"file":"toggle-button-group.js","sources":["../../../src/components/toggle-button-group/toggle-button-group.ts"],"sourcesContent":["import {LitElement, PropertyValues, html, unsafeCSS} from 'lit';\nimport {property, queryAssignedElements} from 'lit/decorators.js';\nimport {\n ObcToggleButtonOption,\n ObcToggleButtonOptionVariant,\n ObcToggleButtonOptionType,\n} from '../toggle-button-option/toggle-button-option.js';\nimport componentStyle from './toggle-button-group.css?inline';\nimport {customElement} from '../../decorator.js';\nimport {classMap} from 'lit/directives/class-map.js';\n\nexport type ObcToggleButtonGroupValueChangeEvent = CustomEvent<{\n value: string;\n previousValue: string;\n}>;\n\n/**\n * `<obc-toggle-button-group>` – A segmented control for selecting a single option from a set (also known as a button group or segmented button).\n *\n * Provides a horizontal group of connected toggle buttons where only one option can be selected at a time.\n * Each option is represented by an `<obc-toggle-button-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 set of buttons with clear selection indicators. Commonly used for switching\n * between views, modes, or categories in a compact, space-efficient way. Ideal for toolbar controls,\n * filtering options, or layout toggles (e.g., list vs. grid view).\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 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 * - **Content type options:**\n * - `text` (default): Options display text labels only.\n * - `icon`: Options display only an icon (compact, suitable for limited space).\n * - `iconText`: Options display an icon and text side-by-side.\n * - `iconTextUnder`: Options display an icon above the text label (vertical layout within each button).\n * - **Size control:**\n * - Standard size (default): Regular button dimensions.\n * - Large size (`large`): Increased touch target and visual prominence for accessibility or emphasis.\n * - **Layout behavior:**\n * - By default, the group stretches to fill available container width, distributing space equally among options.\n * - When `hugText` is true, the group shrinks to fit its content width instead of expanding.\n * - **External control mode:** When `externalControl` is true, the group emits selection events but does not\n * update its own `value` property, allowing parent components to manage state (useful for form libraries or\n * custom state management).\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 selected option for a seamless, unified appearance.\n * - **Property propagation:** The group automatically synchronizes `type`, `variant`, `hugText`, and `large`\n * properties to all child `<obc-toggle-button-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-group>` when you need users to choose exactly one option from a small set of\n * mutually exclusive choices (typically 2-5 options). It provides a more compact and visually integrated\n * alternative to radio buttons.\n *\n * **Ideal use cases:**\n * - View mode toggles (e.g., list vs. grid, map vs. chart)\n * - Filter options (e.g., all/active/completed tasks)\n * - Alignment or layout controls (e.g., left/center/right alignment)\n * - Time range selectors (e.g., day/week/month)\n * - Toolbar mode switches (e.g., edit/preview modes)\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 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 (`type=\"icon\"`), 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 `variant=\"flat\"` in dense UIs or when the toggle is secondary to other content.\n * - Use `large` size for touch interfaces or when the control is a primary interaction element.\n *\n * **TODO(designer):** Confirm if vertical orientation is supported or planned for future releases. Also clarify recommended maximum number of options for optimal usability (currently assumes 2-5 options).\n *\n * ### Slots\n *\n * | Slot Name | Renders When... | Purpose |\n * |-----------|-----------------|---------|\n * | (default) | Always | Place one or more `<obc-toggle-button-option>` elements here to define the selectable options in the group. |\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-group value=\"list\" type=\"iconText\">\n * <obc-toggle-button-option value=\"list\">\n * <obi-placeholder slot=\"icon\"></obi-placeholder>\n * List\n * </obc-toggle-button-option>\n * <obc-toggle-button-option value=\"grid\">\n * <obi-placeholder slot=\"icon\"></obi-placeholder>\n * Grid\n * </obc-toggle-button-option>\n * <obc-toggle-button-option value=\"table\">\n * <obi-placeholder slot=\"icon\"></obi-placeholder>\n * Table\n * </obc-toggle-button-option>\n * </obc-toggle-button-group>\n * ```\n *\n * @slot - Place one or more `<obc-toggle-button-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-group')\nexport class ObcToggleButtonGroup extends LitElement {\n /**\n * The currently selected option's value.\n *\n * Set this property to programmatically select an option. When the user selects a different option, this property updates and a `value` event is fired.\n *\n * If set to a value that does not match any enabled option, the first enabled option is selected by default.\n */\n @property({type: String}) value = '';\n\n /**\n * The value of the option that is activated.\n *\n * When the group is controlled by an external source, this property is used to set the value of the option that is activated.\n * This is a visual indication that the option is clicked but not yet stored.\n */\n @property({type: String}) activated: string | undefined;\n\n /**\n * The visual type of the toggle button options.\n *\n * - `text` (default): Options display text only.\n * - `icon`: Options display only an icon.\n * - `iconText`: Options display an icon and text side-by-side.\n * - `iconTextUnder`: Options display an icon above the text.\n *\n * This setting is propagated to all child `<obc-toggle-button-option>` elements.\n */\n @property({type: String}) type = ObcToggleButtonOptionType.text;\n\n /**\n * The visual variant of the toggle button group.\n *\n * - `regular` (default): Standard appearance with background and border.\n * - `flat`: Minimal style with no background or border.\n * - `normal`: Alternative style variant.\n *\n * This setting is propagated to all child `<obc-toggle-button-option>` elements.\n */\n @property({type: String}) variant = ObcToggleButtonOptionVariant.regular;\n\n /**\n * If true, the group shrinks to fit its content (\"hug\" the text) instead of stretching to fill the container.\n *\n * This setting is propagated to all child `<obc-toggle-button-option>` elements.\n */\n @property({type: Boolean}) hugText = false;\n\n /**\n * If true, the group is controlled by an external source.\n *\n * When true, the group will not update its selection when the `value` property changes.\n *\n * Defaults to false.\n */\n @property({type: Boolean}) externalControl = 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 toggle button group and all contained options when true.\n *\n * When disabled, no option can be selected or interacted with.\n */\n @property({type: Boolean, reflect: true}) disabled = false;\n\n /**\n * If true, the group and all contained options use a larger size.\n *\n * This setting is propagated to all child `<obc-toggle-button-option>` elements.\n */\n @property({type: Boolean, reflect: true}) large = false;\n\n @queryAssignedElements({selector: 'obc-toggle-button-option'})\n options!: NodeListOf<ObcToggleButtonOption>;\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(value: string): ObcToggleButtonOption | null {\n return Array.from(this.options).find((opt) => opt.value === value) || null;\n }\n\n private getFirstSelectableOption(): ObcToggleButtonOption | 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.setNoDivider();\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.setNoDivider();\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.setNoDivider();\n\n if (emitEvent && oldValue !== newValue) {\n this.dispatchEvent(\n new CustomEvent('value', {\n detail: {value: newValue, previousValue: oldValue},\n })\n );\n }\n }\n\n private updateActivated(newValue: string | undefined) {\n if (newValue) {\n this.options.forEach((option) => {\n option.activated = option.value === newValue;\n });\n } else {\n this.options.forEach((option) => {\n option.activated = false;\n });\n }\n }\n\n private setNoDivider() {\n const selectedOptionIndex = Array.from(this.options).findIndex(\n (option) => option.selected\n );\n this.options.forEach((option) => {\n option.showDivider = true;\n });\n if (selectedOptionIndex === -1) {\n return;\n }\n const nextOption = this.options[selectedOptionIndex + 1];\n if (nextOption) {\n nextOption.showDivider = false;\n }\n }\n\n private _originalDisabledStates = new Map<ObcToggleButtonOption, boolean>();\n\n protected override firstUpdated(\n _changedProperties: PropertyValues<unknown> | Map<PropertyKey, unknown>\n ): void {\n super.firstUpdated(_changedProperties);\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 group has duplicate values. This may cause unexpected behavior.'\n );\n }\n\n this.options.forEach((option) => {\n this._originalDisabledStates.set(option, option.hasAttribute('disabled'));\n\n option.addEventListener('selected', (e) => this.handleOptionClick(e));\n\n const observer = new MutationObserver((mutations) => {\n mutations.forEach((mutation) => {\n if (\n mutation.attributeName === 'disabled' &&\n !option.hasAttribute('data-group-disabled')\n ) {\n this._originalDisabledStates.set(\n option,\n option.hasAttribute('disabled')\n );\n this.handleOptionDisabledChange();\n }\n });\n });\n observer.observe(option, {\n attributes: true,\n attributeFilter: ['disabled'],\n });\n\n option.type = this.type;\n option.variant = this.variant;\n option.hugText = this.hugText;\n option.large = this.large;\n\n if (this.disabled) {\n option.setAttribute('data-group-disabled', 'true');\n option.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 if (this.activated) {\n this.updateActivated(this.activated);\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 handleOptionClick(event: Event) {\n const {value} = (event as CustomEvent).detail;\n if (this.externalControl) {\n this.dispatchEvent(\n new CustomEvent('value', {\n detail: {value, previousValue: this.value},\n })\n );\n } else {\n this.updateSelection(value);\n }\n }\n\n override willUpdate(changedProperties: PropertyValues) {\n if (changedProperties.has('value')) {\n this.updateSelection(this.value);\n }\n\n if (changedProperties.has('activated')) {\n this.updateActivated(this.activated);\n }\n\n if (\n changedProperties.has('type') ||\n changedProperties.has('variant') ||\n changedProperties.has('hugText') ||\n changedProperties.has('large')\n ) {\n this.options.forEach((option) => {\n option.type = this.type;\n option.variant = this.variant;\n option.hugText = this.hugText;\n option.large = this.large;\n });\n }\n\n if (changedProperties.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 override render() {\n const classes = {\n 'outer-wrapper': true,\n flat: this.variant === ObcToggleButtonOptionVariant.flat,\n regular: this.variant === ObcToggleButtonOptionVariant.regular,\n 'hug-text': this.hugText,\n 'icon-text-under': this.type === ObcToggleButtonOptionType.iconTextUnder,\n disabled: this.disabled,\n large: this.large,\n };\n\n return html`\n <div class=${classMap(classes)}>\n <div class=\"wrapper\">\n <slot></slot>\n </div>\n </div>\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-toggle-button-group': ObcToggleButtonGroup;\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"toggle-button-group.js","sources":["../../../src/components/toggle-button-group/toggle-button-group.ts"],"sourcesContent":["import {LitElement, PropertyValues, html, unsafeCSS} from 'lit';\nimport {property, queryAssignedElements} from 'lit/decorators.js';\nimport {\n ObcToggleButtonOption,\n ObcToggleButtonOptionVariant,\n ObcToggleButtonOptionType,\n} from '../toggle-button-option/toggle-button-option.js';\nimport componentStyle from './toggle-button-group.css?inline';\nimport {customElement} from '../../decorator.js';\nimport {classMap} from 'lit/directives/class-map.js';\n\nexport type ObcToggleButtonGroupValueChangeEvent = CustomEvent<{\n value: string;\n previousValue: string;\n}>;\n\nexport type ObcToggleButtonGroupChangeEvent = CustomEvent<{\n value: string;\n}>;\n\n/**\n * `<obc-toggle-button-group>` – A segmented control for selecting a single option from a set (also known as a button group or segmented button).\n *\n * Provides a horizontal group of connected toggle buttons where only one option can be selected at a time.\n * Each option is represented by an `<obc-toggle-button-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 set of buttons with clear selection indicators. Commonly used for switching\n * between views, modes, or categories in a compact, space-efficient way. Ideal for toolbar controls,\n * filtering options, or layout toggles (e.g., list vs. grid view).\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 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 * - **Content type options:**\n * - `text` (default): Options display text labels only.\n * - `icon`: Options display only an icon (compact, suitable for limited space).\n * - `iconText`: Options display an icon and text side-by-side.\n * - `iconTextUnder`: Options display an icon above the text label (vertical layout within each button).\n * - **Size control:**\n * - Standard size (default): Regular button dimensions.\n * - Large size (`large`): Increased touch target and visual prominence for accessibility or emphasis.\n * - **Layout behavior:**\n * - By default, the group stretches to fill available container width, distributing space equally among options.\n * - When `hugText` is true, the group shrinks to fit its content width instead of expanding.\n * - **External control mode:** When `externalControl` is true, the group emits selection events but does not\n * update its own `value` property, allowing parent components to manage state (useful for form libraries or\n * custom state management).\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 selected option for a seamless, unified appearance.\n * - **Property propagation:** The group automatically synchronizes `type`, `variant`, `hugText`, and `large`\n * properties to all child `<obc-toggle-button-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-group>` when you need users to choose exactly one option from a small set of\n * mutually exclusive choices (typically 2-5 options). It provides a more compact and visually integrated\n * alternative to radio buttons.\n *\n * **Ideal use cases:**\n * - View mode toggles (e.g., list vs. grid, map vs. chart)\n * - Filter options (e.g., all/active/completed tasks)\n * - Alignment or layout controls (e.g., left/center/right alignment)\n * - Time range selectors (e.g., day/week/month)\n * - Toolbar mode switches (e.g., edit/preview modes)\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 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 (`type=\"icon\"`), 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 `variant=\"flat\"` in dense UIs or when the toggle is secondary to other content.\n * - Use `large` size for touch interfaces or when the control is a primary interaction element.\n *\n * **TODO(designer):** Confirm if vertical orientation is supported or planned for future releases. Also clarify recommended maximum number of options for optimal usability (currently assumes 2-5 options).\n *\n * ### Slots\n *\n * | Slot Name | Renders When... | Purpose |\n * |-----------|-----------------|---------|\n * | (default) | Always | Place one or more `<obc-toggle-button-option>` elements here to define the selectable options in the group. |\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-group value=\"list\" type=\"iconText\">\n * <obc-toggle-button-option value=\"list\">\n * <obi-placeholder slot=\"icon\"></obi-placeholder>\n * List\n * </obc-toggle-button-option>\n * <obc-toggle-button-option value=\"grid\">\n * <obi-placeholder slot=\"icon\"></obi-placeholder>\n * Grid\n * </obc-toggle-button-option>\n * <obc-toggle-button-option value=\"table\">\n * <obi-placeholder slot=\"icon\"></obi-placeholder>\n * Table\n * </obc-toggle-button-option>\n * </obc-toggle-button-group>\n * ```\n *\n * @slot - Place one or more `<obc-toggle-button-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-group')\nexport class ObcToggleButtonGroup extends LitElement {\n /**\n * The currently selected option's value.\n *\n * Set this property to programmatically select an option. When the user selects a different option, this property updates and a `value` event is fired.\n *\n * If set to a value that does not match any enabled option, the first enabled option is selected by default.\n */\n @property({type: String}) value = '';\n\n /**\n * The value of the option that is activated.\n *\n * When the group is controlled by an external source, this property is used to set the value of the option that is activated.\n * This is a visual indication that the option is clicked but not yet stored.\n */\n @property({type: String}) activated: string | undefined;\n\n /**\n * The visual type of the toggle button options.\n *\n * - `text` (default): Options display text only.\n * - `icon`: Options display only an icon.\n * - `iconText`: Options display an icon and text side-by-side.\n * - `iconTextUnder`: Options display an icon above the text.\n *\n * This setting is propagated to all child `<obc-toggle-button-option>` elements.\n */\n @property({type: String}) type = ObcToggleButtonOptionType.text;\n\n /**\n * The visual variant of the toggle button group.\n *\n * - `regular` (default): Standard appearance with background and border.\n * - `flat`: Minimal style with no background or border.\n * - `normal`: Alternative style variant.\n *\n * This setting is propagated to all child `<obc-toggle-button-option>` elements.\n */\n @property({type: String}) variant = ObcToggleButtonOptionVariant.regular;\n\n /**\n * If true, the group shrinks to fit its content (\"hug\" the text) instead of stretching to fill the container.\n *\n * This setting is propagated to all child `<obc-toggle-button-option>` elements.\n */\n @property({type: Boolean}) hugText = false;\n\n /**\n * If true, the group is controlled by an external source.\n *\n * When true, the group will not update its selection when the `value` property changes.\n *\n * Defaults to false.\n */\n @property({type: Boolean}) externalControl = 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 toggle button group and all contained options when true.\n *\n * When disabled, no option can be selected or interacted with.\n */\n @property({type: Boolean, reflect: true}) disabled = false;\n\n /**\n * If true, the group and all contained options use a larger size.\n *\n * This setting is propagated to all child `<obc-toggle-button-option>` elements.\n */\n @property({type: Boolean, reflect: true}) large = false;\n\n @queryAssignedElements({selector: 'obc-toggle-button-option'})\n options!: NodeListOf<ObcToggleButtonOption>;\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(value: string): ObcToggleButtonOption | null {\n return Array.from(this.options).find((opt) => opt.value === value) || null;\n }\n\n private getFirstSelectableOption(): ObcToggleButtonOption | 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.setNoDivider();\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.setNoDivider();\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.setNoDivider();\n\n if (emitValueEvent && oldValue !== newValue) {\n this.dispatchEvent(\n new CustomEvent('value', {\n detail: {value: newValue, previousValue: oldValue},\n })\n );\n }\n\n if (emitChangeEvent && oldValue !== newValue) {\n this.dispatchEvent(\n new CustomEvent('change', {\n detail: {value: newValue},\n })\n );\n }\n }\n\n private updateActivated(newValue: string | undefined) {\n if (newValue) {\n this.options.forEach((option) => {\n option.activated = option.value === newValue;\n });\n } else {\n this.options.forEach((option) => {\n option.activated = false;\n });\n }\n }\n\n private setNoDivider() {\n const selectedOptionIndex = Array.from(this.options).findIndex(\n (option) => option.selected\n );\n this.options.forEach((option) => {\n option.showDivider = true;\n });\n if (selectedOptionIndex === -1) {\n return;\n }\n const nextOption = this.options[selectedOptionIndex + 1];\n if (nextOption) {\n nextOption.showDivider = false;\n }\n }\n\n private _originalDisabledStates = new Map<ObcToggleButtonOption, boolean>();\n\n protected override firstUpdated(\n _changedProperties: PropertyValues<unknown> | Map<PropertyKey, unknown>\n ): void {\n super.firstUpdated(_changedProperties);\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 group has duplicate values. This may cause unexpected behavior.'\n );\n }\n\n this.options.forEach((option) => {\n this._originalDisabledStates.set(option, option.hasAttribute('disabled'));\n\n option.addEventListener('selected', (e) => this.handleOptionClick(e));\n\n const observer = new MutationObserver((mutations) => {\n mutations.forEach((mutation) => {\n if (\n mutation.attributeName === 'disabled' &&\n !option.hasAttribute('data-group-disabled')\n ) {\n this._originalDisabledStates.set(\n option,\n option.hasAttribute('disabled')\n );\n this.handleOptionDisabledChange();\n }\n });\n });\n observer.observe(option, {\n attributes: true,\n attributeFilter: ['disabled'],\n });\n\n option.type = this.type;\n option.variant = this.variant;\n option.hugText = this.hugText;\n option.large = this.large;\n\n if (this.disabled) {\n option.setAttribute('data-group-disabled', 'true');\n option.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 if (this.activated) {\n this.updateActivated(this.activated);\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 handleOptionClick(event: Event) {\n const {value} = (event as CustomEvent).detail;\n if (this.externalControl) {\n this.dispatchEvent(\n new CustomEvent('value', {\n detail: {value, previousValue: this.value},\n })\n );\n\n this.dispatchEvent(\n new CustomEvent('change', {\n detail: {value},\n })\n );\n } else {\n this.updateSelection(value, true, true);\n }\n }\n\n override willUpdate(changedProperties: PropertyValues) {\n if (changedProperties.has('value')) {\n this.updateSelection(this.value);\n }\n\n if (changedProperties.has('activated')) {\n this.updateActivated(this.activated);\n }\n\n if (\n changedProperties.has('type') ||\n changedProperties.has('variant') ||\n changedProperties.has('hugText') ||\n changedProperties.has('large')\n ) {\n this.options.forEach((option) => {\n option.type = this.type;\n option.variant = this.variant;\n option.hugText = this.hugText;\n option.large = this.large;\n });\n }\n\n if (changedProperties.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 override render() {\n const classes = {\n 'outer-wrapper': true,\n flat: this.variant === ObcToggleButtonOptionVariant.flat,\n regular: this.variant === ObcToggleButtonOptionVariant.regular,\n 'hug-text': this.hugText,\n 'icon-text-under': this.type === ObcToggleButtonOptionType.iconTextUnder,\n disabled: this.disabled,\n large: this.large,\n };\n\n return html`\n <div class=${classMap(classes)}>\n <div class=\"wrapper\">\n <slot></slot>\n </div>\n </div>\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-toggle-button-group': ObcToggleButtonGroup;\n }\n}\n"],"names":[],"mappings":"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"}
@@ -4,6 +4,9 @@ export type ObcToggleButtonVerticalGroupValueChangeEvent = CustomEvent<{
4
4
  value: string;
5
5
  previousValue: string;
6
6
  }>;
7
+ export type ObcToggleButtonVerticalGroupChangeEvent = CustomEvent<{
8
+ value: string;
9
+ }>;
7
10
  /**
8
11
  * `<obc-toggle-button-vertical-group>` – A vertically oriented segmented control for selecting a single option from a set.
9
12
  *
@@ -97,6 +100,7 @@ export type ObcToggleButtonVerticalGroupValueChangeEvent = CustomEvent<{
97
100
  *
98
101
  * @slot - Place one or more `<obc-toggle-button-vertical-option>` elements here to define the selectable options.
99
102
  * @fires value {CustomEvent<{value: string, previousValue: string}>} Fired when the selected value changes.
103
+ * @fires change {CustomEvent<{value: string}>} Fired when the selected value changes by user interaction.
100
104
  */
101
105
  export declare class ObcToggleButtonVerticalGroup extends LitElement {
102
106
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"toggle-button-vertical-group.d.ts","sourceRoot":"","sources":["../../../src/components/toggle-button-vertical-group/toggle-button-vertical-group.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAmB,cAAc,EAAC,MAAM,KAAK,CAAC;AAKhE,OAAO,EAEL,iCAAiC,EAClC,MAAM,mEAAmE,CAAC;AAI3E,MAAM,MAAM,4CAA4C,GAAG,WAAW,CAAC;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6FG;AACH,qBACa,4BAA6B,SAAQ,UAAU;IAC1D;;;;OAIG;IACuB,KAAK,SAAM;IAErC;;;;OAIG;IACuB,IAAI,oCAA6C;IAE3E;;;;OAIG;IACwB,QAAQ,UAAS;IAE5C;;;;;;;;OAQG;IACwB,mBAAmB,UAAS;IAEvD;;;;;;OAMG;IACuC,QAAQ,UAAS;IAG3D,OAAO,CAAC,OAAO,CAA6C;IAE5D,OAAO,CAAC,uBAAuB,CAG3B;IAEJ,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,wBAAwB;IAKhC,OAAO,CAAC,eAAe;cAoDJ,YAAY,CAAC,OAAO,EAAE,cAAc;IAmDvD,OAAO,CAAC,0BAA0B;IAczB,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IA0BzC,OAAO,CAAC,iBAAiB,EAAE,cAAc;IAgBlD,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,gBAAgB;IAKf,MAAM;IAiBf,OAAgB,MAAM,0BAAoB;CAC3C;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,kCAAkC,EAAE,4BAA4B,CAAC;KAClE;CACF"}
1
+ {"version":3,"file":"toggle-button-vertical-group.d.ts","sourceRoot":"","sources":["../../../src/components/toggle-button-vertical-group/toggle-button-vertical-group.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAmB,cAAc,EAAC,MAAM,KAAK,CAAC;AAKhE,OAAO,EAEL,iCAAiC,EAClC,MAAM,mEAAmE,CAAC;AAI3E,MAAM,MAAM,4CAA4C,GAAG,WAAW,CAAC;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC,CAAC;AAEH,MAAM,MAAM,uCAAuC,GAAG,WAAW,CAAC;IAChE,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8FG;AACH,qBACa,4BAA6B,SAAQ,UAAU;IAC1D;;;;OAIG;IACuB,KAAK,SAAM;IAErC;;;;OAIG;IACuB,IAAI,oCAA6C;IAE3E;;;;OAIG;IACwB,QAAQ,UAAS;IAE5C;;;;;;;;OAQG;IACwB,mBAAmB,UAAS;IAEvD;;;;;;OAMG;IACuC,QAAQ,UAAS;IAG3D,OAAO,CAAC,OAAO,CAA6C;IAE5D,OAAO,CAAC,uBAAuB,CAG3B;IAEJ,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,wBAAwB;IAKhC,OAAO,CAAC,eAAe;cAwEJ,YAAY,CAAC,OAAO,EAAE,cAAc;IAmDvD,OAAO,CAAC,0BAA0B;IAczB,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IA0BzC,OAAO,CAAC,iBAAiB,EAAE,cAAc;IAgBlD,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,gBAAgB;IAKf,MAAM;IAiBf,OAAgB,MAAM,0BAAoB;CAC3C;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,kCAAkC,EAAE,4BAA4B,CAAC;KAClE;CACF"}