@oicl/openbridge-webcomponents-full-bundle 2.0.0-next.78 → 2.0.0-next.80
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.storybook/vitest.setup.ts +24 -0
- package/bundle/openbridge-webcomponents.bundle.js +95 -10
- package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
- package/custom-elements.json +97 -5
- package/dist/components/alert-frame/alert-frame.css.js +9 -0
- package/dist/components/alert-frame/alert-frame.css.js.map +1 -1
- package/dist/components/alert-frame/alert-frame.d.ts +6 -1
- package/dist/components/alert-frame/alert-frame.d.ts.map +1 -1
- package/dist/components/alert-frame/alert-frame.js +7 -1
- package/dist/components/alert-frame/alert-frame.js.map +1 -1
- package/dist/components/input/input.d.ts +1 -0
- package/dist/components/input/input.d.ts.map +1 -0
- package/dist/components/input/input.js +2 -0
- package/dist/components/input/input.js.map +1 -0
- package/dist/components/pagination/pagination.d.ts +9 -0
- package/dist/components/pagination/pagination.d.ts.map +1 -1
- package/dist/components/pagination/pagination.js +12 -2
- package/dist/components/pagination/pagination.js.map +1 -1
- package/dist/components/slider/slider.d.ts +14 -1
- package/dist/components/slider/slider.d.ts.map +1 -1
- package/dist/components/slider/slider.js +17 -0
- package/dist/components/slider/slider.js.map +1 -1
- package/dist/components/slider-double/slider-double.d.ts +17 -1
- package/dist/components/slider-double/slider-double.d.ts.map +1 -1
- package/dist/components/slider-double/slider-double.js +15 -0
- package/dist/components/slider-double/slider-double.js.map +1 -1
- package/dist/components/toggle-button-group/toggle-button-group.d.ts +4 -0
- package/dist/components/toggle-button-group/toggle-button-group.d.ts.map +1 -1
- package/dist/components/toggle-button-group/toggle-button-group.js +15 -3
- package/dist/components/toggle-button-group/toggle-button-group.js.map +1 -1
- package/dist/components/toggle-button-vertical-group/toggle-button-vertical-group.d.ts +4 -0
- package/dist/components/toggle-button-vertical-group/toggle-button-vertical-group.d.ts.map +1 -1
- package/dist/components/toggle-button-vertical-group/toggle-button-vertical-group.js +10 -3
- package/dist/components/toggle-button-vertical-group/toggle-button-vertical-group.js.map +1 -1
- package/dist/components/toggle-switch/toggle-switch.d.ts +2 -0
- package/dist/components/toggle-switch/toggle-switch.d.ts.map +1 -1
- package/dist/components/toggle-switch/toggle-switch.js +8 -0
- package/dist/components/toggle-switch/toggle-switch.js.map +1 -1
- package/dist/navigation-instruments/readout-list-item/readout-list-item.d.ts.map +1 -1
- package/dist/navigation-instruments/readout-list-item/readout-list-item.js +2 -1
- package/dist/navigation-instruments/readout-list-item/readout-list-item.js.map +1 -1
- package/package.json +1 -1
- package/src/components/alert-frame/alert-frame.css +9 -0
- package/src/components/alert-frame/alert-frame.ts +10 -1
- package/src/components/input/input.ts +0 -0
- package/src/components/pagination/pagination.ts +25 -2
- package/src/components/slider/slider.ts +27 -1
- package/src/components/slider-double/slider-double.ts +28 -1
- package/src/components/toggle-button-group/toggle-button-group.ts +26 -3
- package/src/components/toggle-button-vertical-group/toggle-button-vertical-group.ts +28 -3
- package/src/components/toggle-switch/toggle-switch.ts +10 -0
- package/src/navigation-instruments/readout-list-item/readout-list-item.ts +2 -1
- package/vitest.config.ts +6 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.js","sources":["../../../src/components/pagination/pagination.ts"],"sourcesContent":["import {LitElement, html, unsafeCSS} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport {customElement} from '../../decorator.js';\nimport {classMap} from 'lit/directives/class-map.js';\nimport compentStyle from './pagination.css?inline';\n\nimport '../toggle-button-option/toggle-button-option.js';\nimport '../toggle-button-group/toggle-button-group.js';\nimport '../icon-button/icon-button.js';\nimport '../progress-indicator-dots/progress-indicator-dots.js';\nimport '../../icons/icon-page-first-google.js';\nimport '../../icons/icon-chevron-left-google.js';\nimport '../../icons/icon-chevron-right-google.js';\nimport '../../icons/icon-page-last-google.js';\nimport {ObcToggleButtonOptionVariant} from '../toggle-button-option/toggle-button-option.js';\n\n/**\n * Enumerates the supported style variants for the Pagination component.\n *\n * - `regular`: Default pagination styling.\n * - `flat`: Borderless, flat appearance.\n * - `condensed`: More compact layout for tighter spacing.\n */\nexport enum PaginationVariant {\n regular = 'regular',\n flat = 'flat',\n condensed = 'condensed',\n}\n\n/**\n * Event fired when the current page changes.\n * @event\n */\nexport type ObcPaginationValueChangeEvent = CustomEvent<{value: number}>;\n\n/**\n * Event fired when a navigation arrow is clicked.\n * @event\n */\nexport type ObcPaginationNavigateEvent = CustomEvent<{\n action: 'first' | 'previous' | 'next' | 'last';\n currentPage: number;\n}>;\n\n/**\n * `obc-pagination` – page navigation component for traversing multi-page content.\n *\n * Provides accessible, keyboard-navigable controls for moving between pages of content, such as tables, lists, or document sets. Includes support for ARIA live region updates and multiple visual variants to fit different UI layouts.\n *\n * Appears as a horizontal set of navigation buttons (first, previous, next, last) and page indicators, adapting its layout based on the selected variant. Designed for scenarios where users need to move between discrete pages of content, such as paginated tables, search results, or step-based flows.\n *\n * ## Features\n *\n * - **Variants:**\n * - `regular` (default): Standard pagination with numbered page buttons and navigation arrows.\n * - `flat`: Minimalist style with reduced elevation and flat toggle buttons.\n * - `condensed`: Compact mode showing only progress indicator dots and navigation arrows, ideal for limited space.\n * - **Navigation Controls:**\n * - First, previous, next, and last page buttons, each with ARIA labels and disabled states when navigation is not possible.\n * - **Page Indicators:**\n * - Numbered toggle buttons for each page (regular/flat), or progress dots (condensed).\n * - **Full Width Option:**\n * - Expands the pagination controls to fill the container width for better alignment in wide layouts.\n * - **Accessibility:**\n * - ARIA live region announces current page for assistive technologies.\n * - All controls are keyboard accessible.\n * - **Responsive:**\n * - Condensed variant adapts to smaller containers with a simplified indicator.\n *\n * ## Usage Guidelines\n *\n * Use `obc-pagination` to allow users to navigate through paged content, such as tables, lists, or multi-step flows.\n * - Choose the `regular` or `flat` variant for standard pagination at the bottom of a page or section.\n * - Use the `condensed` variant when space is limited or when a minimal indicator is preferred.\n * - Set the `pages` property to the total number of pages, and `currentPage` to the active page (1-based index).\n * - The component disables navigation buttons automatically at the first and last page.\n *\n * **Best Practices:**\n * - Only use pagination when content is split into discrete, sequential pages.\n * - For infinite scroll or continuous loading, consider alternative navigation patterns.\n * - Keep the number of visible page buttons reasonable (Material Design recommends limiting to avoid overwhelming the user).\n * - Always provide clear feedback about the current page (the component announces this for screen readers).\n *\n * **TODO(designer):** Confirm if there are recommended maximums for number of pages, or if there are design guidelines for when to use condensed vs. flat vs. regular in specific contexts.\n *\n * ## Example\n *\n * ```html\n * <obc-pagination\n * variant=\"regular\"\n * pages=\"5\"\n * current-page=\"2\"\n * ></obc-pagination>\n * ```\n *\n * ## Events\n *\n * - `value` – Fired when the current page changes (via user interaction).\n * - `navigate` – Fired when a navigation arrow (first, previous, next, last) is clicked.\n *\n * @fires value {ObcPaginationValueChangeEvent} Emitted whenever the current page changes.\n * @fires navigate {ObcPaginationNavigateEvent} Emitted when a navigation arrow is clicked.\n */\n@customElement('obc-pagination')\nexport class ObcPagination extends LitElement {\n /**\n * Visual style variant of the pagination component.\n *\n * - `regular`: Standard pagination with numbered page buttons and navigation arrows.\n * - `flat`: Minimalist, low-elevation style with flat toggle buttons.\n * - `condensed`: Compact mode with progress indicator dots and navigation arrows only.\n *\n * Default: `regular`\n */\n @property({type: String}) variant: PaginationVariant =\n PaginationVariant.regular;\n\n /**\n * Total number of pages available for navigation.\n *\n * Must be a positive integer (minimum 1). If set below 1, defaults to 1.\n *\n * Default: `3`\n */\n @property({type: Number}) pages = 3;\n\n /**\n * The currently selected (active) page, 1-based index.\n *\n * If set below 1 or above the total number of pages, it is clamped to the valid range.\n *\n * Default: `1`\n */\n @property({type: Number, attribute: 'current-page'}) currentPage = 1;\n\n /**\n * Expands the pagination controls to fill the width of the container.\n *\n * When enabled, the page indicators (toggle button group or progress dots) stretch to align with the container.\n *\n * Default: `false`\n */\n @property({type: Boolean, attribute: 'full-width', reflect: true}) fullWidth =\n false;\n\n @property({type: Boolean}) disabled = false;\n\n private get isCondensed() {\n return this.variant === PaginationVariant.condensed;\n }\n\n private get toggleButtonVariant() {\n return this.variant === PaginationVariant.flat\n ? ObcToggleButtonOptionVariant.flat\n : ObcToggleButtonOptionVariant.regular;\n }\n\n private get validatedPages() {\n return Math.max(1, this.pages);\n }\n\n private get validatedCurrentPage() {\n return Math.max(1, Math.min(this.currentPage, this.validatedPages));\n }\n\n private get canNavigatePrevious() {\n return !this.disabled && this.validatedCurrentPage > 1;\n }\n\n private get canNavigateNext() {\n console.log(\n 'canNavigateNext',\n this.disabled,\n this.validatedCurrentPage,\n this.validatedPages\n );\n return !this.disabled && this.validatedCurrentPage < this.validatedPages;\n }\n\n private get canNavigateFirst() {\n return !this.disabled && this.canNavigatePrevious;\n }\n\n private get canNavigateLast() {\n return !this.disabled && this.canNavigateNext;\n }\n\n private get pageNumbers() {\n return Array.from({length: this.validatedPages}, (_, i) => i + 1);\n }\n\n private get announceMessage() {\n return `Page ${this.validatedCurrentPage} of ${this.validatedPages}`;\n }\n\n private setCurrentPage(newPage: number) {\n const page = Math.max(1, Math.min(newPage, this.validatedPages));\n if (page === this.currentPage) return;\n this.currentPage = page;\n this.dispatchEvent(\n new CustomEvent('value', {\n detail: {value: page},\n }) as ObcPaginationValueChangeEvent\n );\n }\n\n private dispatchNavigateEvent(\n action: 'first' | 'previous' | 'next' | 'last'\n ) {\n this.dispatchEvent(\n new CustomEvent('navigate', {\n detail: {action, currentPage: this.validatedCurrentPage},\n }) as ObcPaginationNavigateEvent\n );\n }\n\n private handlePageChange = (event: CustomEvent<{value: string}>) => {\n this.setCurrentPage(Number(event.detail.value));\n };\n\n private handleFirstClick = () => {\n if (!this.canNavigateFirst) return;\n this.setCurrentPage(1);\n this.dispatchNavigateEvent('first');\n };\n\n private handlePreviousClick = () => {\n if (!this.canNavigatePrevious) return;\n this.setCurrentPage(this.validatedCurrentPage - 1);\n this.dispatchNavigateEvent('previous');\n };\n\n private handleNextClick = () => {\n if (!this.canNavigateNext) return;\n this.setCurrentPage(this.validatedCurrentPage + 1);\n this.dispatchNavigateEvent('next');\n };\n\n private handleLastClick = () => {\n if (!this.canNavigateLast) return;\n this.setCurrentPage(this.validatedPages);\n this.dispatchNavigateEvent('last');\n };\n\n private renderToggleButtons() {\n return this.pageNumbers.map(\n (num) =>\n html`<obc-toggle-button-option\n .value=${num.toString()}\n .variant=${this.toggleButtonVariant}\n .selected=${num === this.validatedCurrentPage}\n .ariaLabel=${`Page ${num} of ${this.validatedPages}`}\n >\n ${num}\n </obc-toggle-button-option>`\n );\n }\n\n private renderProgressIndicatorDots() {\n return html`\n <obc-progress-indicator-dots\n .totalSteps=${this.validatedPages}\n .currentStep=${this.validatedCurrentPage}\n ></obc-progress-indicator-dots>\n `;\n }\n\n private renderNavigation() {\n return html`\n <div\n class=${classMap({'navigation-wrapper': true, disabled: this.disabled})}\n role=\"navigation\"\n aria-label=\"Pagination\"\n >\n <obc-icon-button\n variant=\"flat\"\n aria-label=\"First page\"\n aria-disabled=${this.canNavigateFirst}\n ?disabled=${!this.canNavigateFirst}\n @click=${this.handleFirstClick}\n >\n <obi-page-first-google></obi-page-first-google>\n </obc-icon-button>\n\n <obc-icon-button\n variant=\"flat\"\n aria-label=\"Previous page\"\n aria-disabled=${this.canNavigatePrevious}\n ?disabled=${!this.canNavigatePrevious}\n @click=${this.handlePreviousClick}\n >\n <obi-chevron-left-google></obi-chevron-left-google>\n </obc-icon-button>\n\n ${this.isCondensed\n ? this.renderProgressIndicatorDots()\n : html`<obc-toggle-button-group\n .value=${this.validatedCurrentPage.toString()}\n .variant=${this.toggleButtonVariant}\n ?disabled=${this.disabled}\n @value=${this.handlePageChange}\n >\n ${this.renderToggleButtons()}\n </obc-toggle-button-group>`}\n\n <obc-icon-button\n variant=\"flat\"\n aria-label=\"Next page\"\n aria-disabled=${this.canNavigateNext}\n ?disabled=${!this.canNavigateNext}\n @click=${this.handleNextClick}\n >\n <obi-chevron-right-google></obi-chevron-right-google>\n </obc-icon-button>\n\n <obc-icon-button\n variant=\"flat\"\n aria-label=\"Last page\"\n aria-disabled=${this.canNavigateLast}\n ?disabled=${!this.canNavigateLast}\n @click=${this.handleLastClick}\n >\n <obi-page-last-google></obi-page-last-google>\n </obc-icon-button>\n </div>\n `;\n }\n\n override render() {\n return html`\n <div\n class=${classMap({\n wrapper: true,\n 'type-regular': this.variant === PaginationVariant.regular,\n 'type-flat': this.variant === PaginationVariant.flat,\n 'type-condensed': this.variant === PaginationVariant.condensed,\n disabled: this.disabled,\n })}\n >\n <div class=\"content-container\">${this.renderNavigation()}</div>\n <span\n aria-live=\"polite\"\n aria-atomic=\"true\"\n style=\"position:absolute;width:1px;height:1px;margin:-1px;clip:rect(0 0 0 0);overflow:hidden;\"\n >\n ${this.announceMessage}\n </span>\n </div>\n `;\n }\n\n static override styles = unsafeCSS(compentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-pagination': ObcPagination;\n }\n}\n"],"names":["PaginationVariant"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAuBO,IAAK,sCAAAA,uBAAL;AACLA,qBAAA,SAAA,IAAU;AACVA,qBAAA,MAAA,IAAO;AACPA,qBAAA,WAAA,IAAY;AAHF,SAAAA;AAAA,GAAA,qBAAA,CAAA,CAAA;AAiFL,IAAM,gBAAN,cAA4B,WAAW;AAAA,EAAvC,cAAA;AAAA,UAAA,GAAA,SAAA;AAUqB,SAAA,UACxB;AASwB,SAAA,QAAQ;AASmB,SAAA,cAAc;AASA,SAAA,YACjE;AAEyB,SAAA,WAAW;AAuEtC,SAAQ,mBAAmB,CAAC,UAAwC;AAClE,WAAK,eAAe,OAAO,MAAM,OAAO,KAAK,CAAC;AAAA,IAChD;AAEA,SAAQ,mBAAmB,MAAM;AAC/B,UAAI,CAAC,KAAK,iBAAkB;AAC5B,WAAK,eAAe,CAAC;AACrB,WAAK,sBAAsB,OAAO;AAAA,IACpC;AAEA,SAAQ,sBAAsB,MAAM;AAClC,UAAI,CAAC,KAAK,oBAAqB;AAC/B,WAAK,eAAe,KAAK,uBAAuB,CAAC;AACjD,WAAK,sBAAsB,UAAU;AAAA,IACvC;AAEA,SAAQ,kBAAkB,MAAM;AAC9B,UAAI,CAAC,KAAK,gBAAiB;AAC3B,WAAK,eAAe,KAAK,uBAAuB,CAAC;AACjD,WAAK,sBAAsB,MAAM;AAAA,IACnC;AAEA,SAAQ,kBAAkB,MAAM;AAC9B,UAAI,CAAC,KAAK,gBAAiB;AAC3B,WAAK,eAAe,KAAK,cAAc;AACvC,WAAK,sBAAsB,MAAM;AAAA,IACnC;AAAA,EAAA;AAAA,EA/FA,IAAY,cAAc;AACxB,WAAO,KAAK,YAAY;AAAA,EAC1B;AAAA,EAEA,IAAY,sBAAsB;AAChC,WAAO,KAAK,YAAY,SACpB,6BAA6B,OAC7B,6BAA6B;AAAA,EACnC;AAAA,EAEA,IAAY,iBAAiB;AAC3B,WAAO,KAAK,IAAI,GAAG,KAAK,KAAK;AAAA,EAC/B;AAAA,EAEA,IAAY,uBAAuB;AACjC,WAAO,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,aAAa,KAAK,cAAc,CAAC;AAAA,EACpE;AAAA,EAEA,IAAY,sBAAsB;AAChC,WAAO,CAAC,KAAK,YAAY,KAAK,uBAAuB;AAAA,EACvD;AAAA,EAEA,IAAY,kBAAkB;AAC5B,YAAQ;AAAA,MACN;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IAAA;AAEP,WAAO,CAAC,KAAK,YAAY,KAAK,uBAAuB,KAAK;AAAA,EAC5D;AAAA,EAEA,IAAY,mBAAmB;AAC7B,WAAO,CAAC,KAAK,YAAY,KAAK;AAAA,EAChC;AAAA,EAEA,IAAY,kBAAkB;AAC5B,WAAO,CAAC,KAAK,YAAY,KAAK;AAAA,EAChC;AAAA,EAEA,IAAY,cAAc;AACxB,WAAO,MAAM,KAAK,EAAC,QAAQ,KAAK,eAAA,GAAiB,CAAC,GAAG,MAAM,IAAI,CAAC;AAAA,EAClE;AAAA,EAEA,IAAY,kBAAkB;AAC5B,WAAO,QAAQ,KAAK,oBAAoB,OAAO,KAAK,cAAc;AAAA,EACpE;AAAA,EAEQ,eAAe,SAAiB;AACtC,UAAM,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,SAAS,KAAK,cAAc,CAAC;AAC/D,QAAI,SAAS,KAAK,YAAa;AAC/B,SAAK,cAAc;AACnB,SAAK;AAAA,MACH,IAAI,YAAY,SAAS;AAAA,QACvB,QAAQ,EAAC,OAAO,KAAA;AAAA,MAAI,CACrB;AAAA,IAAA;AAAA,EAEL;AAAA,EAEQ,sBACN,QACA;AACA,SAAK;AAAA,MACH,IAAI,YAAY,YAAY;AAAA,QAC1B,QAAQ,EAAC,QAAQ,aAAa,KAAK,qBAAA;AAAA,MAAoB,CACxD;AAAA,IAAA;AAAA,EAEL;AAAA,EA8BQ,sBAAsB;AAC5B,WAAO,KAAK,YAAY;AAAA,MACtB,CAAC,QACC;AAAA,mBACW,IAAI,UAAU;AAAA,qBACZ,KAAK,mBAAmB;AAAA,sBACvB,QAAQ,KAAK,oBAAoB;AAAA,uBAChC,QAAQ,GAAG,OAAO,KAAK,cAAc,EAAE;AAAA;AAAA,YAElD,GAAG;AAAA;AAAA,IAAA;AAAA,EAGb;AAAA,EAEQ,8BAA8B;AACpC,WAAO;AAAA;AAAA,sBAEW,KAAK,cAAc;AAAA,uBAClB,KAAK,oBAAoB;AAAA;AAAA;AAAA,EAG9C;AAAA,EAEQ,mBAAmB;AACzB,WAAO;AAAA;AAAA,gBAEK,SAAS,EAAC,sBAAsB,MAAM,UAAU,KAAK,UAAS,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAOrD,KAAK,gBAAgB;AAAA,sBACzB,CAAC,KAAK,gBAAgB;AAAA,mBACzB,KAAK,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAQd,KAAK,mBAAmB;AAAA,sBAC5B,CAAC,KAAK,mBAAmB;AAAA,mBAC5B,KAAK,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA,UAKjC,KAAK,cACH,KAAK,4BAAA,IACL;AAAA,uBACW,KAAK,qBAAqB,SAAA,CAAU;AAAA,yBAClC,KAAK,mBAAmB;AAAA,0BACvB,KAAK,QAAQ;AAAA,uBAChB,KAAK,gBAAgB;AAAA;AAAA,gBAE5B,KAAK,qBAAqB;AAAA,uCACH;AAAA;AAAA;AAAA;AAAA;AAAA,0BAKb,KAAK,eAAe;AAAA,sBACxB,CAAC,KAAK,eAAe;AAAA,mBACxB,KAAK,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAQb,KAAK,eAAe;AAAA,sBACxB,CAAC,KAAK,eAAe;AAAA,mBACxB,KAAK,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMrC;AAAA,EAES,SAAS;AAChB,WAAO;AAAA;AAAA,gBAEK,SAAS;AAAA,MACf,SAAS;AAAA,MACT,gBAAgB,KAAK,YAAY;AAAA,MACjC,aAAa,KAAK,YAAY;AAAA,MAC9B,kBAAkB,KAAK,YAAY;AAAA,MACnC,UAAU,KAAK;AAAA,IAAA,CAChB,CAAC;AAAA;AAAA,yCAE+B,KAAK,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAMpD,KAAK,eAAe;AAAA;AAAA;AAAA;AAAA,EAI9B;AAGF;AAxPa,cAuPK,SAAS,UAAU,YAAY;AA7OrB,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAVb,cAUe,WAAA,WAAA,CAAA;AAUA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GApBb,cAoBe,WAAA,SAAA,CAAA;AAS2B,gBAAA;AAAA,EAApD,SAAS,EAAC,MAAM,QAAQ,WAAW,gBAAe;AAAA,GA7BxC,cA6B0C,WAAA,eAAA,CAAA;AASc,gBAAA;AAAA,EAAlE,SAAS,EAAC,MAAM,SAAS,WAAW,cAAc,SAAS,MAAK;AAAA,GAtCtD,cAsCwD,WAAA,aAAA,CAAA;AAGxC,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAzCd,cAyCgB,WAAA,YAAA,CAAA;AAzChB,gBAAN,gBAAA;AAAA,EADN,cAAc,gBAAgB;AAAA,GAClB,aAAA;"}
|
|
1
|
+
{"version":3,"file":"pagination.js","sources":["../../../src/components/pagination/pagination.ts"],"sourcesContent":["import {LitElement, html, unsafeCSS} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport {customElement} from '../../decorator.js';\nimport {classMap} from 'lit/directives/class-map.js';\nimport compentStyle from './pagination.css?inline';\n\nimport '../toggle-button-option/toggle-button-option.js';\nimport '../toggle-button-group/toggle-button-group.js';\nimport '../icon-button/icon-button.js';\nimport '../progress-indicator-dots/progress-indicator-dots.js';\nimport '../../icons/icon-page-first-google.js';\nimport '../../icons/icon-chevron-left-google.js';\nimport '../../icons/icon-chevron-right-google.js';\nimport '../../icons/icon-page-last-google.js';\nimport {ObcToggleButtonOptionVariant} from '../toggle-button-option/toggle-button-option.js';\n\n/**\n * Enumerates the supported style variants for the Pagination component.\n *\n * - `regular`: Default pagination styling.\n * - `flat`: Borderless, flat appearance.\n * - `condensed`: More compact layout for tighter spacing.\n */\nexport enum PaginationVariant {\n regular = 'regular',\n flat = 'flat',\n condensed = 'condensed',\n}\n\n/**\n * Event fired when the current page changes.\n * @event\n */\nexport type ObcPaginationValueChangeEvent = CustomEvent<{value: number}>;\n\n/**\n * Event fired when a navigation arrow is clicked.\n * @event\n */\nexport type ObcPaginationNavigateEvent = CustomEvent<{\n action: 'first' | 'previous' | 'next' | 'last';\n currentPage: number;\n}>;\n\n/**\n * Event fired when a page is selected.\n * @event\n */\nexport type ObcPaginationSelectPageEvent = CustomEvent<{\n page: number;\n}>;\n\n/**\n * `obc-pagination` – page navigation component for traversing multi-page content.\n *\n * Provides accessible, keyboard-navigable controls for moving between pages of content, such as tables, lists, or document sets. Includes support for ARIA live region updates and multiple visual variants to fit different UI layouts.\n *\n * Appears as a horizontal set of navigation buttons (first, previous, next, last) and page indicators, adapting its layout based on the selected variant. Designed for scenarios where users need to move between discrete pages of content, such as paginated tables, search results, or step-based flows.\n *\n * ## Features\n *\n * - **Variants:**\n * - `regular` (default): Standard pagination with numbered page buttons and navigation arrows.\n * - `flat`: Minimalist style with reduced elevation and flat toggle buttons.\n * - `condensed`: Compact mode showing only progress indicator dots and navigation arrows, ideal for limited space.\n * - **Navigation Controls:**\n * - First, previous, next, and last page buttons, each with ARIA labels and disabled states when navigation is not possible.\n * - **Page Indicators:**\n * - Numbered toggle buttons for each page (regular/flat), or progress dots (condensed).\n * - **Full Width Option:**\n * - Expands the pagination controls to fill the container width for better alignment in wide layouts.\n * - **Accessibility:**\n * - ARIA live region announces current page for assistive technologies.\n * - All controls are keyboard accessible.\n * - **Responsive:**\n * - Condensed variant adapts to smaller containers with a simplified indicator.\n *\n * ## Usage Guidelines\n *\n * Use `obc-pagination` to allow users to navigate through paged content, such as tables, lists, or multi-step flows.\n * - Choose the `regular` or `flat` variant for standard pagination at the bottom of a page or section.\n * - Use the `condensed` variant when space is limited or when a minimal indicator is preferred.\n * - Set the `pages` property to the total number of pages, and `currentPage` to the active page (1-based index).\n * - The component disables navigation buttons automatically at the first and last page.\n *\n * **Best Practices:**\n * - Only use pagination when content is split into discrete, sequential pages.\n * - For infinite scroll or continuous loading, consider alternative navigation patterns.\n * - Keep the number of visible page buttons reasonable (Material Design recommends limiting to avoid overwhelming the user).\n * - Always provide clear feedback about the current page (the component announces this for screen readers).\n *\n * **TODO(designer):** Confirm if there are recommended maximums for number of pages, or if there are design guidelines for when to use condensed vs. flat vs. regular in specific contexts.\n *\n * ## Example\n *\n * ```html\n * <obc-pagination\n * variant=\"regular\"\n * pages=\"5\"\n * current-page=\"2\"\n * ></obc-pagination>\n * ```\n *\n * ## Events\n *\n * - `value` – Fired when the current page changes (via user interaction).\n * - `navigate` – Fired when a navigation arrow (first, previous, next, last) is clicked.\n * - `select-page` – Fired when a specific page is selected.\n *\n * @fires value {ObcPaginationValueChangeEvent} Emitted whenever the current page changes.\n * @fires navigate {ObcPaginationNavigateEvent} Emitted when a navigation arrow is clicked.\n * @fires select-page {ObcPaginationSelectPageEvent} Emitted when a specific page is selected.\n */\n@customElement('obc-pagination')\nexport class ObcPagination extends LitElement {\n /**\n * Visual style variant of the pagination component.\n *\n * - `regular`: Standard pagination with numbered page buttons and navigation arrows.\n * - `flat`: Minimalist, low-elevation style with flat toggle buttons.\n * - `condensed`: Compact mode with progress indicator dots and navigation arrows only.\n *\n * Default: `regular`\n */\n @property({type: String}) variant: PaginationVariant =\n PaginationVariant.regular;\n\n /**\n * Total number of pages available for navigation.\n *\n * Must be a positive integer (minimum 1). If set below 1, defaults to 1.\n *\n * Default: `3`\n */\n @property({type: Number}) pages = 3;\n\n /**\n * The currently selected (active) page, 1-based index.\n *\n * If set below 1 or above the total number of pages, it is clamped to the valid range.\n *\n * Default: `1`\n */\n @property({type: Number, attribute: 'current-page'}) currentPage = 1;\n\n /**\n * Expands the pagination controls to fill the width of the container.\n *\n * When enabled, the page indicators (toggle button group or progress dots) stretch to align with the container.\n *\n * Default: `false`\n */\n @property({type: Boolean, attribute: 'full-width', reflect: true}) fullWidth =\n false;\n\n @property({type: Boolean}) disabled = false;\n\n private get isCondensed() {\n return this.variant === PaginationVariant.condensed;\n }\n\n private get toggleButtonVariant() {\n return this.variant === PaginationVariant.flat\n ? ObcToggleButtonOptionVariant.flat\n : ObcToggleButtonOptionVariant.regular;\n }\n\n private get validatedPages() {\n return Math.max(1, this.pages);\n }\n\n private get validatedCurrentPage() {\n return Math.max(1, Math.min(this.currentPage, this.validatedPages));\n }\n\n private get canNavigatePrevious() {\n return !this.disabled && this.validatedCurrentPage > 1;\n }\n\n private get canNavigateNext() {\n console.log(\n 'canNavigateNext',\n this.disabled,\n this.validatedCurrentPage,\n this.validatedPages\n );\n return !this.disabled && this.validatedCurrentPage < this.validatedPages;\n }\n\n private get canNavigateFirst() {\n return !this.disabled && this.canNavigatePrevious;\n }\n\n private get canNavigateLast() {\n return !this.disabled && this.canNavigateNext;\n }\n\n private get pageNumbers() {\n return Array.from({length: this.validatedPages}, (_, i) => i + 1);\n }\n\n private get announceMessage() {\n return `Page ${this.validatedCurrentPage} of ${this.validatedPages}`;\n }\n\n private setCurrentPage(newPage: number) {\n const page = Math.max(1, Math.min(newPage, this.validatedPages));\n if (page === this.currentPage) {\n return false;\n }\n\n this.currentPage = page;\n this.dispatchEvent(\n new CustomEvent('value', {\n detail: {value: page},\n }) as ObcPaginationValueChangeEvent\n );\n\n return true;\n }\n\n private dispatchNavigateEvent(\n action: 'first' | 'previous' | 'next' | 'last'\n ) {\n this.dispatchEvent(\n new CustomEvent('navigate', {\n detail: {action, currentPage: this.validatedCurrentPage},\n }) as ObcPaginationNavigateEvent\n );\n }\n\n private handlePageChange = (event: CustomEvent<{value: string}>) => {\n const success = this.setCurrentPage(Number(event.detail.value));\n\n if (success) {\n this.dispatchEvent(\n new CustomEvent('select-page', {\n detail: {page: Number(event.detail.value)},\n }) as ObcPaginationSelectPageEvent\n );\n }\n };\n\n private handleFirstClick = () => {\n if (!this.canNavigateFirst) return;\n this.setCurrentPage(1);\n this.dispatchNavigateEvent('first');\n };\n\n private handlePreviousClick = () => {\n if (!this.canNavigatePrevious) return;\n this.setCurrentPage(this.validatedCurrentPage - 1);\n this.dispatchNavigateEvent('previous');\n };\n\n private handleNextClick = () => {\n if (!this.canNavigateNext) return;\n this.setCurrentPage(this.validatedCurrentPage + 1);\n this.dispatchNavigateEvent('next');\n };\n\n private handleLastClick = () => {\n if (!this.canNavigateLast) return;\n this.setCurrentPage(this.validatedPages);\n this.dispatchNavigateEvent('last');\n };\n\n private renderToggleButtons() {\n return this.pageNumbers.map(\n (num) =>\n html`<obc-toggle-button-option\n .value=${num.toString()}\n .variant=${this.toggleButtonVariant}\n .selected=${num === this.validatedCurrentPage}\n .ariaLabel=${`Page ${num} of ${this.validatedPages}`}\n >\n ${num}\n </obc-toggle-button-option>`\n );\n }\n\n private renderProgressIndicatorDots() {\n return html`\n <obc-progress-indicator-dots\n .totalSteps=${this.validatedPages}\n .currentStep=${this.validatedCurrentPage}\n ></obc-progress-indicator-dots>\n `;\n }\n\n private renderNavigation() {\n return html`\n <div\n class=${classMap({'navigation-wrapper': true, disabled: this.disabled})}\n role=\"navigation\"\n aria-label=\"Pagination\"\n >\n <obc-icon-button\n variant=\"flat\"\n aria-label=\"First page\"\n aria-disabled=${this.canNavigateFirst}\n ?disabled=${!this.canNavigateFirst}\n @click=${this.handleFirstClick}\n >\n <obi-page-first-google></obi-page-first-google>\n </obc-icon-button>\n\n <obc-icon-button\n variant=\"flat\"\n aria-label=\"Previous page\"\n aria-disabled=${this.canNavigatePrevious}\n ?disabled=${!this.canNavigatePrevious}\n @click=${this.handlePreviousClick}\n >\n <obi-chevron-left-google></obi-chevron-left-google>\n </obc-icon-button>\n\n ${this.isCondensed\n ? this.renderProgressIndicatorDots()\n : html`<obc-toggle-button-group\n .value=${this.validatedCurrentPage.toString()}\n .variant=${this.toggleButtonVariant}\n ?disabled=${this.disabled}\n @value=${this.handlePageChange}\n >\n ${this.renderToggleButtons()}\n </obc-toggle-button-group>`}\n\n <obc-icon-button\n variant=\"flat\"\n aria-label=\"Next page\"\n aria-disabled=${this.canNavigateNext}\n ?disabled=${!this.canNavigateNext}\n @click=${this.handleNextClick}\n >\n <obi-chevron-right-google></obi-chevron-right-google>\n </obc-icon-button>\n\n <obc-icon-button\n variant=\"flat\"\n aria-label=\"Last page\"\n aria-disabled=${this.canNavigateLast}\n ?disabled=${!this.canNavigateLast}\n @click=${this.handleLastClick}\n >\n <obi-page-last-google></obi-page-last-google>\n </obc-icon-button>\n </div>\n `;\n }\n\n override render() {\n return html`\n <div\n class=${classMap({\n wrapper: true,\n 'type-regular': this.variant === PaginationVariant.regular,\n 'type-flat': this.variant === PaginationVariant.flat,\n 'type-condensed': this.variant === PaginationVariant.condensed,\n disabled: this.disabled,\n })}\n >\n <div class=\"content-container\">${this.renderNavigation()}</div>\n <span\n aria-live=\"polite\"\n aria-atomic=\"true\"\n style=\"position:absolute;width:1px;height:1px;margin:-1px;clip:rect(0 0 0 0);overflow:hidden;\"\n >\n ${this.announceMessage}\n </span>\n </div>\n `;\n }\n\n static override styles = unsafeCSS(compentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-pagination': ObcPagination;\n }\n}\n"],"names":["PaginationVariant"],"mappings":"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"}
|
|
@@ -17,6 +17,11 @@ export declare enum ObcSliderVariant {
|
|
|
17
17
|
* The event detail contains the new numeric value.
|
|
18
18
|
*/
|
|
19
19
|
export type ObcSliderValueEvent = CustomEvent<number>;
|
|
20
|
+
/**
|
|
21
|
+
* Custom event type for slider change event (fired after user interaction completes).
|
|
22
|
+
* The event detail contains the new numeric value.
|
|
23
|
+
*/
|
|
24
|
+
export type ObcSliderChangeEvent = CustomEvent<number>;
|
|
20
25
|
/**
|
|
21
26
|
* `<obc-slider>` – A horizontal slider component for selecting a numeric value within a defined range.
|
|
22
27
|
*
|
|
@@ -76,7 +81,8 @@ export type ObcSliderValueEvent = CustomEvent<number>;
|
|
|
76
81
|
* ---
|
|
77
82
|
*
|
|
78
83
|
* ### Events
|
|
79
|
-
* - `value` – Fired when the slider value changes
|
|
84
|
+
* - `value` – Fired continuously when the slider value changes during user interaction or programmatically. The event detail contains the new value as a number.
|
|
85
|
+
* - `change` – Fired only after user interaction completes (mouse/touch release or button click). The event detail contains the new value as a number.
|
|
80
86
|
*
|
|
81
87
|
* ---
|
|
82
88
|
*
|
|
@@ -112,6 +118,7 @@ export type ObcSliderValueEvent = CustomEvent<number>;
|
|
|
112
118
|
* @slot icon-right - Slot for the right icon button (shown when `hasRightIcon` is true)
|
|
113
119
|
* @attr hugcontainer - If set, the slider will not have any spacing between the slider icons and the container
|
|
114
120
|
* @fires value {ObcSliderValueEvent} - Fired when the value is changed
|
|
121
|
+
* @fires change {ObcSliderChangeEvent} - Fired when user interaction completes and value has changed
|
|
115
122
|
*/
|
|
116
123
|
export declare class ObcSlider extends LitElement {
|
|
117
124
|
/**
|
|
@@ -200,6 +207,12 @@ export declare class ObcSlider extends LitElement {
|
|
|
200
207
|
* @fires value
|
|
201
208
|
*/
|
|
202
209
|
onInput(value: number): void;
|
|
210
|
+
/**
|
|
211
|
+
* Fires the `change` event with the current value.
|
|
212
|
+
*
|
|
213
|
+
* @fires change
|
|
214
|
+
*/
|
|
215
|
+
private fireChangeEvent;
|
|
203
216
|
/**
|
|
204
217
|
* Decrements the value by `stepClick` when the left icon button is clicked.
|
|
205
218
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slider.d.ts","sourceRoot":"","sources":["../../../src/components/slider/slider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAkB,MAAM,KAAK,CAAC;AAKhD,OAAO,+BAA+B,CAAC;AAIvC;;;;;;GAMG;AACH,oBAAY,gBAAgB;IAC1B,MAAM,WAAW;IACjB,QAAQ,aAAa;IACrB,OAAO,aAAa;CACrB;AAED;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;AAEtD
|
|
1
|
+
{"version":3,"file":"slider.d.ts","sourceRoot":"","sources":["../../../src/components/slider/slider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAkB,MAAM,KAAK,CAAC;AAKhD,OAAO,+BAA+B,CAAC;AAIvC;;;;;;GAMG;AACH,oBAAY,gBAAgB;IAC1B,MAAM,WAAW;IACjB,QAAQ,aAAa;IACrB,OAAO,aAAa;CACrB;AAED;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;AAEtD;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiGG;AACH,qBACa,SAAU,SAAQ,UAAU;IACvC;;;;OAIG;IACuB,KAAK,SAAM;IAErC;;;;OAIG;IACuB,GAAG,SAAK;IAElC;;;;OAIG;IACuB,GAAG,SAAO;IAEpC;;;;;OAKG;IACuB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAEnD;;;;;OAKG;IACuB,SAAS,SAAM;IAEzC;;;;;;;;OAQG;IACuB,OAAO,EAAE,gBAAgB,CAA2B;IAE9E;;;;OAIG;IACwB,WAAW,UAAS;IAE/C;;;;OAIG;IACwB,YAAY,UAAS;IAEhD;;;;;OAKG;IACwB,YAAY,UAAS;IAEhD;;;;;;OAMG;IACuB,YAAY,SAAS;IAEpB,QAAQ,UAAS;IAE5C,OAAO,KAAK,KAAK,GAMhB;IAED,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,kBAAkB,CAAuB;IACjD,OAAO,CAAC,mBAAmB,CAAa;IAExC;;;;;;OAMG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM;IAKrB;;;;OAIG;IACH,OAAO,CAAC,eAAe;IAMvB;;OAEG;IACH,aAAa;IAMb;;OAEG;IACH,eAAe;IAMf,OAAO,KAAK,MAAM,GAEjB;IAED,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,iBAAiB,CAEvB;IAEF,OAAO,CAAC,eAAe,CAErB;IAEF,OAAO,CAAC,iBAAiB,CAEvB;IAEF,OAAO,CAAC,gBAAgB,CAEtB;IAEF,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,iBAAiB;IAgBzB,OAAO,CAAC,cAAc;IA0DtB,OAAO,CAAC,aAAa;IAOZ,MAAM;IA8Ef,OAAgB,MAAM,0BAA6B;CACpD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,YAAY,EAAE,SAAS,CAAC;KACzB;CACF"}
|
|
@@ -73,12 +73,23 @@ let ObcSlider = class extends LitElement {
|
|
|
73
73
|
this.value = value;
|
|
74
74
|
this.dispatchEvent(new CustomEvent("value", { detail: this.value }));
|
|
75
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Fires the `change` event with the current value.
|
|
78
|
+
*
|
|
79
|
+
* @fires change
|
|
80
|
+
*/
|
|
81
|
+
fireChangeEvent() {
|
|
82
|
+
this.dispatchEvent(
|
|
83
|
+
new CustomEvent("change", { detail: this.value })
|
|
84
|
+
);
|
|
85
|
+
}
|
|
76
86
|
/**
|
|
77
87
|
* Decrements the value by `stepClick` when the left icon button is clicked.
|
|
78
88
|
*/
|
|
79
89
|
onReduceClick() {
|
|
80
90
|
if (this.disabled) return;
|
|
81
91
|
this.onInput(Math.max(this.value - this.stepClick, this.min));
|
|
92
|
+
this.fireChangeEvent();
|
|
82
93
|
}
|
|
83
94
|
/**
|
|
84
95
|
* Increments the value by `stepClick` when the right icon button is clicked.
|
|
@@ -86,6 +97,7 @@ let ObcSlider = class extends LitElement {
|
|
|
86
97
|
onIncreaseClick() {
|
|
87
98
|
if (this.disabled) return;
|
|
88
99
|
this.onInput(Math.min(this.value + this.stepClick, this.max));
|
|
100
|
+
this.fireChangeEvent();
|
|
89
101
|
}
|
|
90
102
|
get slider() {
|
|
91
103
|
return this.renderRoot.querySelector('input[type="range"]');
|
|
@@ -143,12 +155,14 @@ let ObcSlider = class extends LitElement {
|
|
|
143
155
|
window.removeEventListener("mousemove", this.onWindowMouseMove);
|
|
144
156
|
window.removeEventListener("mouseup", this.onWindowMouseUp);
|
|
145
157
|
this.stopAnimation();
|
|
158
|
+
this.fireChangeEvent();
|
|
146
159
|
}
|
|
147
160
|
onTouchEnd() {
|
|
148
161
|
this.isTouchActive = false;
|
|
149
162
|
window.removeEventListener("touchmove", this.onWindowTouchMove);
|
|
150
163
|
window.removeEventListener("touchend", this.onWindowTouchEnd);
|
|
151
164
|
this.stopAnimation();
|
|
165
|
+
this.fireChangeEvent();
|
|
152
166
|
}
|
|
153
167
|
updateTargetValue(e) {
|
|
154
168
|
const rect = this.slider.getBoundingClientRect();
|
|
@@ -242,6 +256,9 @@ let ObcSlider = class extends LitElement {
|
|
|
242
256
|
@input=${(event) => {
|
|
243
257
|
this.value = Number(event.target.value);
|
|
244
258
|
this.dispatchEvent(new CustomEvent("value", { detail: this.value }));
|
|
259
|
+
}}
|
|
260
|
+
@change=${() => {
|
|
261
|
+
this.fireChangeEvent();
|
|
245
262
|
}}
|
|
246
263
|
@mousedown=${this.onMouseDown}
|
|
247
264
|
@touchstart=${this.onTouchStart}
|
|
@@ -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
|
|
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":"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"}
|
|
@@ -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
|
|
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"}
|