@oicl/openbridge-webcomponents 0.0.20260414104700 → 0.0.20260414111415
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/dist/components/navigation-menu/navigation-menu.css.js +3 -3
- package/dist/components/navigation-menu/navigation-menu.d.ts +1 -0
- package/dist/components/navigation-menu/navigation-menu.d.ts.map +1 -1
- package/dist/components/navigation-menu/navigation-menu.js +7 -2
- package/dist/components/navigation-menu/navigation-menu.js.map +1 -1
- package/dist/components/slider/slider.css.js +62 -18
- package/dist/components/slider/slider.css.js.map +1 -1
- package/dist/components/slider/slider.d.ts +1 -0
- package/dist/components/slider/slider.d.ts.map +1 -1
- package/dist/components/slider/slider.js +13 -2
- package/dist/components/slider/slider.js.map +1 -1
- package/package.json +1 -1
|
@@ -42,7 +42,7 @@ const compentStyle = css`
|
|
|
42
42
|
.wrapper .footer {
|
|
43
43
|
display: flex;
|
|
44
44
|
flex-direction: column;
|
|
45
|
-
border-top: 1px solid var(--border-outline-color
|
|
45
|
+
border-top: 1px solid var(--border-outline-color);
|
|
46
46
|
flex: 0;
|
|
47
47
|
}
|
|
48
48
|
|
|
@@ -52,8 +52,8 @@ const compentStyle = css`
|
|
|
52
52
|
width: 100%;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
.full .footer nav {
|
|
56
|
-
border-bottom: 1px solid var(--border-outline-color
|
|
55
|
+
.full .footer.has-footer nav {
|
|
56
|
+
border-bottom: 1px solid var(--border-outline-color);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
.full .logo {
|
|
@@ -134,6 +134,7 @@ export declare class ObcNavigationMenu extends LitElement {
|
|
|
134
134
|
*/
|
|
135
135
|
smallScreen: boolean;
|
|
136
136
|
private slotObservers;
|
|
137
|
+
private hasFooter;
|
|
137
138
|
findAllElements<T extends Element>(el: Element, tag: string, { slot, stopTag, }?: {
|
|
138
139
|
slot?: 'main' | 'footer' | 'logo';
|
|
139
140
|
stopTag?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigation-menu.d.ts","sourceRoot":"","sources":["../../../src/components/navigation-menu/navigation-menu.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,cAAc,EAA2B,MAAM,KAAK,CAAC;AAGzE,OAAO,EAAC,sBAAsB,EAAC,MAAM,mDAAmD,CAAC;AACzF,OAAO,EAAC,iBAAiB,EAAC,MAAM,uCAAuC,CAAC;AAGxE;;;;;;;;;GASG;AACH,oBAAY,wBAAwB;IAClC,IAAI,SAAS;IACb,QAAQ,cAAc,CAAE,yEAAyE;IACjG,aAAa,oBAAoB,CAAE,iEAAiE;IACpG,OAAO,YAAY;CACpB;AAED;;;;;;;GAOG;AACH,oBAAY,8BAA8B;IACxC,IAAI,SAAS;IACb,OAAO,YAAY;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoFG;AACH,qBACa,iBAAkB,SAAQ,UAAU;IAC/C;;;;;;;OAOG;IACuB,OAAO,EAAE,wBAAwB,CAC3B;IAEhC;;;OAGG;IACuB,aAAa,EAAE,8BAA8B,CACjC;IAEtC;;OAEG;IACwB,WAAW,UAAS;IAE/C,OAAO,CAAC,aAAa,CAA0B;
|
|
1
|
+
{"version":3,"file":"navigation-menu.d.ts","sourceRoot":"","sources":["../../../src/components/navigation-menu/navigation-menu.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,cAAc,EAA2B,MAAM,KAAK,CAAC;AAGzE,OAAO,EAAC,sBAAsB,EAAC,MAAM,mDAAmD,CAAC;AACzF,OAAO,EAAC,iBAAiB,EAAC,MAAM,uCAAuC,CAAC;AAGxE;;;;;;;;;GASG;AACH,oBAAY,wBAAwB;IAClC,IAAI,SAAS;IACb,QAAQ,cAAc,CAAE,yEAAyE;IACjG,aAAa,oBAAoB,CAAE,iEAAiE;IACpG,OAAO,YAAY;CACpB;AAED;;;;;;;GAOG;AACH,oBAAY,8BAA8B;IACxC,IAAI,SAAS;IACb,OAAO,YAAY;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoFG;AACH,qBACa,iBAAkB,SAAQ,UAAU;IAC/C;;;;;;;OAOG;IACuB,OAAO,EAAE,wBAAwB,CAC3B;IAEhC;;;OAGG;IACuB,aAAa,EAAE,8BAA8B,CACjC;IAEtC;;OAEG;IACwB,WAAW,UAAS;IAE/C,OAAO,CAAC,aAAa,CAA0B;IACtC,OAAO,CAAC,SAAS,CAAS;IAEnC,eAAe,CAAC,CAAC,SAAS,OAAO,EAC/B,EAAE,EAAE,OAAO,EACX,GAAG,EAAE,MAAM,EACX,EACE,IAAI,EACJ,OAAO,GACR,GAAE;QACD,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;QAClC,OAAO,CAAC,EAAE,MAAM,CAAC;KACb,GACL,CAAC,EAAE;IAoBN,aAAa,CAAC,EAAE,EAAE,OAAO,GAAG,sBAAsB,EAAE;IAQpD,aAAa,CAAC,EAAE,EAAE,OAAO,GAAG,iBAAiB,EAAE;IAO/C,YAAY,CACV,EAAE,EAAE,OAAO,EACX,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,GAChC,iBAAiB,EAAE;IAMtB,cAAc;IAOd,aAAa,CAAC,MAAM,EAAE,sBAAsB,EAAE;IAc9C,OAAO,CAAC,oBAAoB;IAK5B,OAAO,CAAC,kBAAkB;cA+BP,YAAY,CAAC,kBAAkB,EAAE,cAAc,GAAG,IAAI;cAMtD,OAAO,CAAC,kBAAkB,EAAE,cAAc,GAAG,IAAI;IAWpE,OAAO,CAAC,uBAAuB;IAiBtB,oBAAoB,IAAI,IAAI;IAKrC,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,UAAU;IAuClB,OAAO,CAAC,cAAc;IAQb,MAAM;IA+Bf,OAAgB,MAAM,0BAA2B;CAClD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,qBAAqB,EAAE,iBAAiB,CAAC;KAC1C;CACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { unsafeCSS, LitElement, nothing, html } from "lit";
|
|
2
|
-
import { property } from "lit/decorators.js";
|
|
2
|
+
import { property, state } from "lit/decorators.js";
|
|
3
3
|
import compentStyle from "./navigation-menu.css.js";
|
|
4
4
|
import { customElement } from "../../decorator.js";
|
|
5
5
|
var __defProp = Object.defineProperty;
|
|
@@ -31,6 +31,7 @@ let ObcNavigationMenu = class extends LitElement {
|
|
|
31
31
|
this.flyoutVariant = "full";
|
|
32
32
|
this.smallScreen = false;
|
|
33
33
|
this.slotObservers = [];
|
|
34
|
+
this.hasFooter = false;
|
|
34
35
|
}
|
|
35
36
|
findAllElements(el, tag, {
|
|
36
37
|
slot,
|
|
@@ -101,6 +102,7 @@ let ObcNavigationMenu = class extends LitElement {
|
|
|
101
102
|
const footerSlot = this.shadowRoot?.querySelector(
|
|
102
103
|
'slot[name="footer"]'
|
|
103
104
|
);
|
|
105
|
+
this.hasFooter = footerSlot?.assignedElements().length > 0;
|
|
104
106
|
[mainSlot, footerSlot].forEach((slot) => {
|
|
105
107
|
if (slot) {
|
|
106
108
|
const slottedElements = slot.assignedElements();
|
|
@@ -192,7 +194,7 @@ let ObcNavigationMenu = class extends LitElement {
|
|
|
192
194
|
<slot name="main" @slotchange=${this.handleSlotChange}></slot>
|
|
193
195
|
</ol>
|
|
194
196
|
</nav>
|
|
195
|
-
<div class="footer">
|
|
197
|
+
<div class="footer ${this.hasFooter ? "has-footer" : ""}">
|
|
196
198
|
<nav>
|
|
197
199
|
<ol>
|
|
198
200
|
<slot name="footer" @slotchange=${this.handleSlotChange}></slot>
|
|
@@ -219,6 +221,9 @@ __decorateClass([
|
|
|
219
221
|
__decorateClass([
|
|
220
222
|
property({ type: Boolean })
|
|
221
223
|
], ObcNavigationMenu.prototype, "smallScreen", 2);
|
|
224
|
+
__decorateClass([
|
|
225
|
+
state()
|
|
226
|
+
], ObcNavigationMenu.prototype, "hasFooter", 2);
|
|
222
227
|
ObcNavigationMenu = __decorateClass([
|
|
223
228
|
customElement("obc-navigation-menu")
|
|
224
229
|
], ObcNavigationMenu);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigation-menu.js","sources":["../../../src/components/navigation-menu/navigation-menu.ts"],"sourcesContent":["import {LitElement, PropertyValues, html, nothing, unsafeCSS} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport compentStyle from './navigation-menu.css?inline';\nimport {ObcNavigationItemGroup} from '../navigation-item-group/navigation-item-group.js';\nimport {ObcNavigationItem} from '../navigation-item/navigation-item.js';\nimport {customElement} from '../../decorator.js';\n\n/**\n * `ObcNavigationMenuVariant` – Enumerates the available visual and behavioral variants for `<obc-navigation-menu>`.\n *\n * - `Full`: Standard navigation menu with both icons and labels.\n * - `IconOnly`: Compact menu showing only icons (should only be used when no flyouts/submenus are present).\n * - `IconOnlyLarge`: Icon-only menu variant designed for use when flyouts/submenus are present.\n * - `Compact`: Space-saving menu with reduced padding and layout.\n *\n * Use these variants to adapt the navigation menu to different layouts or device sizes.\n */\nexport enum ObcNavigationMenuVariant {\n Full = 'full',\n IconOnly = 'icon-only', // Should only be used when no flyouts are present in the navigation menu\n IconOnlyLarge = 'icon-only-large', // Should be used when flyouts are present in the navigation menu\n Compact = 'compact',\n}\n\n/**\n * `ObcNavigationMenuFlyoutVariant` – Enumerates the available visual and behavioral variants for the flyout.\n *\n * - `Full`: Standard navigation flyout that takes the full height.\n * - `Compact`: Space-saving menu with reduced padding and layout.\n *\n * Use these variants to adapt the flyout menu to different layouts or device sizes.\n */\nexport enum ObcNavigationMenuFlyoutVariant {\n Full = 'full',\n Compact = 'compact',\n}\n\n/**\n * `<obc-navigation-menu>` – A flexible, slot-based navigation menu component for organizing primary and secondary navigation items.\n *\n * This component provides a vertical navigation structure supporting groups, flyouts, and footer sections. It adapts to various layouts and device sizes via its `variant` and `smallScreen` properties. Items and groups are provided via slots, allowing for icons, labels, and nested navigation hierarchies.\n *\n * Appears as a sidebar or persistent navigation panel, supporting both icon-only and full-label modes. Designed for use as the main navigation in applications, dashboards, or any interface requiring structured navigation.\n *\n * ## Features\n *\n * - **Variants:**\n * - **Full:** Displays both icons and labels for all navigation items (default).\n * - **IconOnly:** Shows only icons for a compact appearance. *Should only be used when no navigation items have sub-items or flyouts.*\n * - **IconOnlyLarge:** Icon-only mode that supports flyouts/submenus. Use when navigation contains groups or nested items.\n * - **Compact:** Reduces padding and overall width for a space-saving layout.\n * - **Responsive Layout:**\n * - `smallScreen` property adapts the footer and logo layout for smaller viewports.\n * - **Slot-based Content:**\n * - `main` slot for primary navigation items and groups.\n * - `footer` slot for secondary actions or links.\n * - `logo` slot for branding or logo placement (position adapts based on variant and screen size).\n * - **Nested Navigation:**\n * - Supports nested groups and flyouts via `<obc-navigation-item-group>`.\n * - **Automatic Variant Propagation:**\n * - Child items and groups automatically receive the correct variant for consistent appearance.\n * - **Dynamic Content Handling:**\n * - Reacts to dynamic addition/removal of items and groups, updating layout and variants as needed.\n * - **Interaction:**\n * - Clicking a navigation item closes all open groups/flyouts for streamlined navigation.\n *\n * ## Usage Guidelines\n *\n * Use `<obc-navigation-menu>` as the main navigation container in your application layout. Place navigation items and groups in the `main` slot for primary navigation, and use the `footer` slot for secondary actions (such as settings or help). The `logo` slot is intended for branding and is positioned according to the selected variant and screen size.\n *\n * - Use the `Full` variant for standard navigation with both icons and labels.\n * - Use `IconOnly` only when there are no nested groups or flyouts; otherwise, use `IconOnlyLarge` for icon-only navigation with flyout support.\n * - The `Compact` variant is suitable for layouts with limited space or when a minimal navigation appearance is desired.\n * - Set `smallScreen` to `true` to optimize the layout for smaller devices or responsive breakpoints.\n *\n * **TODO(designer):** Provide additional guidance on when to use each variant and recommended slot content for best usability.\n *\n * ## Slots\n *\n * | Slot Name | Renders When... | Purpose |\n * |-----------|----------------|---------|\n * | main | Always | Primary navigation items and groups. |\n * | footer | Always | Secondary navigation items (e.g., settings, help). |\n * | logo | Always | Branding/logo area (position varies by variant and screen size). |\n *\n * Place `<obc-navigation-item>`, `<obc-navigation-item-group>`, or other suitable elements in these slots. For icons, use `<obi-placeholder>`, `<obi-applications>`, or other OpenBridge icon components in the `icon` slot of each navigation item.\n *\n * ## Properties\n *\n * - `variant` (`ObcNavigationMenuVariant`): Controls the visual style and layout of the menu. Default is `Full`.\n * - `smallScreen` (`boolean`): When `true`, adapts the layout for small screens (e.g., moves logo into the footer area).\n *\n * ## Best Practices and Constraints\n *\n * - Only use the `IconOnly` variant when there are no navigation items with sub-items or flyouts. Use `IconOnlyLarge` if your navigation includes groups or nested items.\n * - Place only navigation-related components in the `main` and `footer` slots for clarity and accessibility.\n * - For best accessibility, ensure each navigation item has a clear label and, if using icons, a suitable `aria-label` or accessible name.\n * - Avoid placing interactive elements other than navigation items/groups in the `main` or `footer` slots.\n *\n * ## Example\n *\n * ```html\n * <obc-navigation-menu variant=\"full\">\n * <obc-navigation-item-group slot=\"main\" label=\"Apps\">\n * <obi-applications slot=\"icon\"></obi-applications>\n * <obc-navigation-item label=\"Sub item 1\" hasIcon href=\"#\">\n * <obi-placeholder slot=\"icon\"></obi-placeholder>\n * </obc-navigation-item>\n * </obc-navigation-item-group>\n * <obc-navigation-item slot=\"footer\" label=\"Settings\" hasIcon href=\"#\">\n * <obi-settings-iec slot=\"icon\"></obi-settings-iec>\n * </obc-navigation-item>\n * <obc-vendor-button imageSrc=\"/companylogo-day.png\" alt=\"logo\" slot=\"logo\"></obc-vendor-button>\n * </obc-navigation-menu>\n * ```\n *\n * In this example, the menu displays a group with sub-items in the main navigation, several footer actions, and a logo.\n *\n * @slot main - Slot for primary navigation items and groups.\n * @slot footer - Slot for secondary navigation items (e.g., settings, help).\n * @slot logo - Slot for branding/logo area.\n */\n@customElement('obc-navigation-menu')\nexport class ObcNavigationMenu extends LitElement {\n /**\n * Controls the visual style and layout of the navigation menu.\n *\n * - `full`: Standard menu with icons and labels (default).\n * - `icon-only`: Compact, icon-only menu (use only when no flyouts/groups are present).\n * - `icon-only-large`: Icon-only menu supporting flyouts/groups.\n * - `compact`: Minimal, space-saving menu.\n */\n @property({type: String}) variant: ObcNavigationMenuVariant =\n ObcNavigationMenuVariant.Full;\n\n /**\n * Visual variant of the flyout.\n * One of `Full` (default) or `Compact`.\n */\n @property({type: String}) flyoutVariant: ObcNavigationMenuFlyoutVariant =\n ObcNavigationMenuFlyoutVariant.Full;\n\n /**\n * When `true`, adapts the layout for small screens (e.g., moves logo into the footer area and adjusts item layout).\n */\n @property({type: Boolean}) smallScreen = false;\n\n private slotObservers: MutationObserver[] = [];\n\n findAllElements<T extends Element>(\n el: Element,\n tag: string,\n {\n slot,\n stopTag,\n }: {\n slot?: 'main' | 'footer' | 'logo';\n stopTag?: string;\n } = {}\n ): T[] {\n const elements: T[] = [];\n for (const child of el.children) {\n if (child.tagName.toLowerCase() === tag) {\n if (slot && child.getAttribute('slot') !== slot) {\n continue;\n }\n elements.push(child as T);\n } else if (stopTag && child.tagName.toLowerCase() === stopTag) {\n continue;\n } else {\n if (slot && child.getAttribute('slot') !== slot) {\n continue;\n }\n elements.push(...this.findAllElements<T>(child, tag, {stopTag}));\n }\n }\n return elements;\n }\n\n findAllGroups(el: Element): ObcNavigationItemGroup[] {\n // Find all groups that are not in a group\n return this.findAllElements<ObcNavigationItemGroup>(\n el,\n 'obc-navigation-item-group'\n );\n }\n\n findRootItems(el: Element): ObcNavigationItem[] {\n // Find all items that are not in a group or in an item\n return this.findAllElements<ObcNavigationItem>(el, 'obc-navigation-item', {\n stopTag: 'obc-navigation-item-group',\n });\n }\n\n findAllItems(\n el: Element,\n slot?: 'main' | 'footer' | 'logo'\n ): ObcNavigationItem[] {\n return this.findAllElements<ObcNavigationItem>(el, 'obc-navigation-item', {\n slot,\n });\n }\n\n closeAllGroups() {\n const groups = this.findAllGroups(this);\n groups.forEach((group) => {\n group.close();\n });\n }\n\n registerGroup(groups: ObcNavigationItemGroup[]) {\n groups.forEach((group) => {\n group.addEventListener('open', () => {\n groups.forEach((g) => {\n if (g !== group) {\n g.close();\n }\n });\n });\n const subGroups = this.findAllGroups(group);\n this.registerGroup(subGroups);\n });\n }\n\n private cleanupSlotObservers() {\n this.slotObservers.forEach((observer) => observer.disconnect());\n this.slotObservers = [];\n }\n\n private setupSlotObservers() {\n this.cleanupSlotObservers();\n\n const mainSlot = this.shadowRoot?.querySelector(\n 'slot[name=\"main\"]'\n ) as HTMLSlotElement;\n const footerSlot = this.shadowRoot?.querySelector(\n 'slot[name=\"footer\"]'\n ) as HTMLSlotElement;\n\n [mainSlot, footerSlot].forEach((slot) => {\n if (slot) {\n const slottedElements = slot.assignedElements();\n slottedElements.forEach((element) => {\n const observer = new MutationObserver(() => {\n this.setupItems();\n });\n\n observer.observe(element, {\n childList: true,\n subtree: true,\n });\n\n this.slotObservers.push(observer);\n });\n }\n });\n }\n\n protected override firstUpdated(_changedProperties: PropertyValues): void {\n super.firstUpdated(_changedProperties);\n const groups = this.findAllGroups(this);\n this.registerGroup(groups);\n }\n\n protected override updated(_changedProperties: PropertyValues): void {\n super.updated(_changedProperties);\n if (\n _changedProperties.has('variant') ||\n _changedProperties.has('flyoutVariant')\n ) {\n this.setupItems();\n }\n }\n\n // Recursively set variant for children of groups\n private setVariantToFlyoutItems(el: Element) {\n // Find all descendant items inside this element (not direct children of the nav menu)\n const items = this.findAllElements<ObcNavigationItem>(\n el,\n 'obc-navigation-item'\n );\n items.forEach((item) => {\n item.variant = ObcNavigationMenuVariant.Full;\n });\n\n const groups = this.findAllGroups(el);\n groups.forEach((group) => {\n group.variant = ObcNavigationMenuVariant.Full;\n this.setVariantToFlyoutItems(group);\n });\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.cleanupSlotObservers();\n }\n\n private handleSlotChange() {\n this.setupItems();\n this.setupSlotObservers();\n }\n\n private setupItems() {\n const hug =\n this.variant !== ObcNavigationMenuVariant.Full ||\n this.flyoutVariant === ObcNavigationMenuFlyoutVariant.Compact;\n this.setHugToGroups(this, hug);\n\n // Set variant to all groups (top-level)\n const groups = this.findAllGroups(this);\n groups.forEach((group) => {\n group.variant = this.variant;\n // But for flyout children, force variant to full\n this.setVariantToFlyoutItems(group);\n });\n\n // Set variant to all root items (not in group)\n this.findRootItems(this).forEach((item) => {\n item.variant = this.variant;\n });\n\n // Footer and logo logic (same as before)\n const footerVariant =\n this.smallScreen && this.variant === ObcNavigationMenuVariant.Full\n ? ObcNavigationMenuVariant.Compact\n : this.variant;\n this.findAllItems(this, 'footer').forEach((item) => {\n item.variant = footerVariant;\n });\n this.findAllItems(this, 'logo').forEach((item) => {\n item.variant = footerVariant;\n });\n\n // Close all groups on item click (unchanged)\n this.findAllItems(this).forEach((item) => {\n item.addEventListener('click', () => {\n this.closeAllGroups();\n });\n });\n }\n\n private setHugToGroups(el: Element, hug: boolean) {\n const groups = this.findAllGroups(el);\n groups.forEach((group) => {\n group.hug = hug;\n this.setHugToGroups(group, hug);\n });\n }\n\n override render() {\n return html`\n <div\n class=\"wrapper ${this.variant} ${this.smallScreen\n ? 'small-screen'\n : ''}\"\n >\n <nav class=\"main\">\n <ol>\n <slot name=\"main\" @slotchange=${this.handleSlotChange}></slot>\n </ol>\n </nav>\n <div class=\"footer\">\n <nav>\n <ol>\n <slot name=\"footer\" @slotchange=${this.handleSlotChange}></slot>\n ${this.smallScreen ? html` <slot name=\"logo\"></slot> ` : nothing}\n </ol>\n </nav>\n ${this.smallScreen\n ? nothing\n : html`\n <div class=\"logo\">\n <slot name=\"logo\"></slot>\n </div>\n `}\n </div>\n </div>\n `;\n }\n\n static override styles = unsafeCSS(compentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-navigation-menu': ObcNavigationMenu;\n }\n}\n"],"names":["ObcNavigationMenuVariant","ObcNavigationMenuFlyoutVariant"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"navigation-menu.js","sources":["../../../src/components/navigation-menu/navigation-menu.ts"],"sourcesContent":["import {LitElement, PropertyValues, html, nothing, unsafeCSS} from 'lit';\nimport {property, state} from 'lit/decorators.js';\nimport compentStyle from './navigation-menu.css?inline';\nimport {ObcNavigationItemGroup} from '../navigation-item-group/navigation-item-group.js';\nimport {ObcNavigationItem} from '../navigation-item/navigation-item.js';\nimport {customElement} from '../../decorator.js';\n\n/**\n * `ObcNavigationMenuVariant` – Enumerates the available visual and behavioral variants for `<obc-navigation-menu>`.\n *\n * - `Full`: Standard navigation menu with both icons and labels.\n * - `IconOnly`: Compact menu showing only icons (should only be used when no flyouts/submenus are present).\n * - `IconOnlyLarge`: Icon-only menu variant designed for use when flyouts/submenus are present.\n * - `Compact`: Space-saving menu with reduced padding and layout.\n *\n * Use these variants to adapt the navigation menu to different layouts or device sizes.\n */\nexport enum ObcNavigationMenuVariant {\n Full = 'full',\n IconOnly = 'icon-only', // Should only be used when no flyouts are present in the navigation menu\n IconOnlyLarge = 'icon-only-large', // Should be used when flyouts are present in the navigation menu\n Compact = 'compact',\n}\n\n/**\n * `ObcNavigationMenuFlyoutVariant` – Enumerates the available visual and behavioral variants for the flyout.\n *\n * - `Full`: Standard navigation flyout that takes the full height.\n * - `Compact`: Space-saving menu with reduced padding and layout.\n *\n * Use these variants to adapt the flyout menu to different layouts or device sizes.\n */\nexport enum ObcNavigationMenuFlyoutVariant {\n Full = 'full',\n Compact = 'compact',\n}\n\n/**\n * `<obc-navigation-menu>` – A flexible, slot-based navigation menu component for organizing primary and secondary navigation items.\n *\n * This component provides a vertical navigation structure supporting groups, flyouts, and footer sections. It adapts to various layouts and device sizes via its `variant` and `smallScreen` properties. Items and groups are provided via slots, allowing for icons, labels, and nested navigation hierarchies.\n *\n * Appears as a sidebar or persistent navigation panel, supporting both icon-only and full-label modes. Designed for use as the main navigation in applications, dashboards, or any interface requiring structured navigation.\n *\n * ## Features\n *\n * - **Variants:**\n * - **Full:** Displays both icons and labels for all navigation items (default).\n * - **IconOnly:** Shows only icons for a compact appearance. *Should only be used when no navigation items have sub-items or flyouts.*\n * - **IconOnlyLarge:** Icon-only mode that supports flyouts/submenus. Use when navigation contains groups or nested items.\n * - **Compact:** Reduces padding and overall width for a space-saving layout.\n * - **Responsive Layout:**\n * - `smallScreen` property adapts the footer and logo layout for smaller viewports.\n * - **Slot-based Content:**\n * - `main` slot for primary navigation items and groups.\n * - `footer` slot for secondary actions or links.\n * - `logo` slot for branding or logo placement (position adapts based on variant and screen size).\n * - **Nested Navigation:**\n * - Supports nested groups and flyouts via `<obc-navigation-item-group>`.\n * - **Automatic Variant Propagation:**\n * - Child items and groups automatically receive the correct variant for consistent appearance.\n * - **Dynamic Content Handling:**\n * - Reacts to dynamic addition/removal of items and groups, updating layout and variants as needed.\n * - **Interaction:**\n * - Clicking a navigation item closes all open groups/flyouts for streamlined navigation.\n *\n * ## Usage Guidelines\n *\n * Use `<obc-navigation-menu>` as the main navigation container in your application layout. Place navigation items and groups in the `main` slot for primary navigation, and use the `footer` slot for secondary actions (such as settings or help). The `logo` slot is intended for branding and is positioned according to the selected variant and screen size.\n *\n * - Use the `Full` variant for standard navigation with both icons and labels.\n * - Use `IconOnly` only when there are no nested groups or flyouts; otherwise, use `IconOnlyLarge` for icon-only navigation with flyout support.\n * - The `Compact` variant is suitable for layouts with limited space or when a minimal navigation appearance is desired.\n * - Set `smallScreen` to `true` to optimize the layout for smaller devices or responsive breakpoints.\n *\n * **TODO(designer):** Provide additional guidance on when to use each variant and recommended slot content for best usability.\n *\n * ## Slots\n *\n * | Slot Name | Renders When... | Purpose |\n * |-----------|----------------|---------|\n * | main | Always | Primary navigation items and groups. |\n * | footer | Always | Secondary navigation items (e.g., settings, help). |\n * | logo | Always | Branding/logo area (position varies by variant and screen size). |\n *\n * Place `<obc-navigation-item>`, `<obc-navigation-item-group>`, or other suitable elements in these slots. For icons, use `<obi-placeholder>`, `<obi-applications>`, or other OpenBridge icon components in the `icon` slot of each navigation item.\n *\n * ## Properties\n *\n * - `variant` (`ObcNavigationMenuVariant`): Controls the visual style and layout of the menu. Default is `Full`.\n * - `smallScreen` (`boolean`): When `true`, adapts the layout for small screens (e.g., moves logo into the footer area).\n *\n * ## Best Practices and Constraints\n *\n * - Only use the `IconOnly` variant when there are no navigation items with sub-items or flyouts. Use `IconOnlyLarge` if your navigation includes groups or nested items.\n * - Place only navigation-related components in the `main` and `footer` slots for clarity and accessibility.\n * - For best accessibility, ensure each navigation item has a clear label and, if using icons, a suitable `aria-label` or accessible name.\n * - Avoid placing interactive elements other than navigation items/groups in the `main` or `footer` slots.\n *\n * ## Example\n *\n * ```html\n * <obc-navigation-menu variant=\"full\">\n * <obc-navigation-item-group slot=\"main\" label=\"Apps\">\n * <obi-applications slot=\"icon\"></obi-applications>\n * <obc-navigation-item label=\"Sub item 1\" hasIcon href=\"#\">\n * <obi-placeholder slot=\"icon\"></obi-placeholder>\n * </obc-navigation-item>\n * </obc-navigation-item-group>\n * <obc-navigation-item slot=\"footer\" label=\"Settings\" hasIcon href=\"#\">\n * <obi-settings-iec slot=\"icon\"></obi-settings-iec>\n * </obc-navigation-item>\n * <obc-vendor-button imageSrc=\"/companylogo-day.png\" alt=\"logo\" slot=\"logo\"></obc-vendor-button>\n * </obc-navigation-menu>\n * ```\n *\n * In this example, the menu displays a group with sub-items in the main navigation, several footer actions, and a logo.\n *\n * @slot main - Slot for primary navigation items and groups.\n * @slot footer - Slot for secondary navigation items (e.g., settings, help).\n * @slot logo - Slot for branding/logo area.\n */\n@customElement('obc-navigation-menu')\nexport class ObcNavigationMenu extends LitElement {\n /**\n * Controls the visual style and layout of the navigation menu.\n *\n * - `full`: Standard menu with icons and labels (default).\n * - `icon-only`: Compact, icon-only menu (use only when no flyouts/groups are present).\n * - `icon-only-large`: Icon-only menu supporting flyouts/groups.\n * - `compact`: Minimal, space-saving menu.\n */\n @property({type: String}) variant: ObcNavigationMenuVariant =\n ObcNavigationMenuVariant.Full;\n\n /**\n * Visual variant of the flyout.\n * One of `Full` (default) or `Compact`.\n */\n @property({type: String}) flyoutVariant: ObcNavigationMenuFlyoutVariant =\n ObcNavigationMenuFlyoutVariant.Full;\n\n /**\n * When `true`, adapts the layout for small screens (e.g., moves logo into the footer area and adjusts item layout).\n */\n @property({type: Boolean}) smallScreen = false;\n\n private slotObservers: MutationObserver[] = [];\n @state() private hasFooter = false;\n\n findAllElements<T extends Element>(\n el: Element,\n tag: string,\n {\n slot,\n stopTag,\n }: {\n slot?: 'main' | 'footer' | 'logo';\n stopTag?: string;\n } = {}\n ): T[] {\n const elements: T[] = [];\n for (const child of el.children) {\n if (child.tagName.toLowerCase() === tag) {\n if (slot && child.getAttribute('slot') !== slot) {\n continue;\n }\n elements.push(child as T);\n } else if (stopTag && child.tagName.toLowerCase() === stopTag) {\n continue;\n } else {\n if (slot && child.getAttribute('slot') !== slot) {\n continue;\n }\n elements.push(...this.findAllElements<T>(child, tag, {stopTag}));\n }\n }\n return elements;\n }\n\n findAllGroups(el: Element): ObcNavigationItemGroup[] {\n // Find all groups that are not in a group\n return this.findAllElements<ObcNavigationItemGroup>(\n el,\n 'obc-navigation-item-group'\n );\n }\n\n findRootItems(el: Element): ObcNavigationItem[] {\n // Find all items that are not in a group or in an item\n return this.findAllElements<ObcNavigationItem>(el, 'obc-navigation-item', {\n stopTag: 'obc-navigation-item-group',\n });\n }\n\n findAllItems(\n el: Element,\n slot?: 'main' | 'footer' | 'logo'\n ): ObcNavigationItem[] {\n return this.findAllElements<ObcNavigationItem>(el, 'obc-navigation-item', {\n slot,\n });\n }\n\n closeAllGroups() {\n const groups = this.findAllGroups(this);\n groups.forEach((group) => {\n group.close();\n });\n }\n\n registerGroup(groups: ObcNavigationItemGroup[]) {\n groups.forEach((group) => {\n group.addEventListener('open', () => {\n groups.forEach((g) => {\n if (g !== group) {\n g.close();\n }\n });\n });\n const subGroups = this.findAllGroups(group);\n this.registerGroup(subGroups);\n });\n }\n\n private cleanupSlotObservers() {\n this.slotObservers.forEach((observer) => observer.disconnect());\n this.slotObservers = [];\n }\n\n private setupSlotObservers() {\n this.cleanupSlotObservers();\n\n const mainSlot = this.shadowRoot?.querySelector(\n 'slot[name=\"main\"]'\n ) as HTMLSlotElement;\n const footerSlot = this.shadowRoot?.querySelector(\n 'slot[name=\"footer\"]'\n ) as HTMLSlotElement;\n\n this.hasFooter = footerSlot?.assignedElements().length > 0;\n\n [mainSlot, footerSlot].forEach((slot) => {\n if (slot) {\n const slottedElements = slot.assignedElements();\n slottedElements.forEach((element) => {\n const observer = new MutationObserver(() => {\n this.setupItems();\n });\n\n observer.observe(element, {\n childList: true,\n subtree: true,\n });\n\n this.slotObservers.push(observer);\n });\n }\n });\n }\n\n protected override firstUpdated(_changedProperties: PropertyValues): void {\n super.firstUpdated(_changedProperties);\n const groups = this.findAllGroups(this);\n this.registerGroup(groups);\n }\n\n protected override updated(_changedProperties: PropertyValues): void {\n super.updated(_changedProperties);\n if (\n _changedProperties.has('variant') ||\n _changedProperties.has('flyoutVariant')\n ) {\n this.setupItems();\n }\n }\n\n // Recursively set variant for children of groups\n private setVariantToFlyoutItems(el: Element) {\n // Find all descendant items inside this element (not direct children of the nav menu)\n const items = this.findAllElements<ObcNavigationItem>(\n el,\n 'obc-navigation-item'\n );\n items.forEach((item) => {\n item.variant = ObcNavigationMenuVariant.Full;\n });\n\n const groups = this.findAllGroups(el);\n groups.forEach((group) => {\n group.variant = ObcNavigationMenuVariant.Full;\n this.setVariantToFlyoutItems(group);\n });\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.cleanupSlotObservers();\n }\n\n private handleSlotChange() {\n this.setupItems();\n this.setupSlotObservers();\n }\n\n private setupItems() {\n const hug =\n this.variant !== ObcNavigationMenuVariant.Full ||\n this.flyoutVariant === ObcNavigationMenuFlyoutVariant.Compact;\n this.setHugToGroups(this, hug);\n\n // Set variant to all groups (top-level)\n const groups = this.findAllGroups(this);\n groups.forEach((group) => {\n group.variant = this.variant;\n // But for flyout children, force variant to full\n this.setVariantToFlyoutItems(group);\n });\n\n // Set variant to all root items (not in group)\n this.findRootItems(this).forEach((item) => {\n item.variant = this.variant;\n });\n\n // Footer and logo logic (same as before)\n const footerVariant =\n this.smallScreen && this.variant === ObcNavigationMenuVariant.Full\n ? ObcNavigationMenuVariant.Compact\n : this.variant;\n this.findAllItems(this, 'footer').forEach((item) => {\n item.variant = footerVariant;\n });\n this.findAllItems(this, 'logo').forEach((item) => {\n item.variant = footerVariant;\n });\n\n // Close all groups on item click (unchanged)\n this.findAllItems(this).forEach((item) => {\n item.addEventListener('click', () => {\n this.closeAllGroups();\n });\n });\n }\n\n private setHugToGroups(el: Element, hug: boolean) {\n const groups = this.findAllGroups(el);\n groups.forEach((group) => {\n group.hug = hug;\n this.setHugToGroups(group, hug);\n });\n }\n\n override render() {\n return html`\n <div\n class=\"wrapper ${this.variant} ${this.smallScreen\n ? 'small-screen'\n : ''}\"\n >\n <nav class=\"main\">\n <ol>\n <slot name=\"main\" @slotchange=${this.handleSlotChange}></slot>\n </ol>\n </nav>\n <div class=\"footer ${this.hasFooter ? 'has-footer' : ''}\">\n <nav>\n <ol>\n <slot name=\"footer\" @slotchange=${this.handleSlotChange}></slot>\n ${this.smallScreen ? html` <slot name=\"logo\"></slot> ` : nothing}\n </ol>\n </nav>\n ${this.smallScreen\n ? nothing\n : html`\n <div class=\"logo\">\n <slot name=\"logo\"></slot>\n </div>\n `}\n </div>\n </div>\n `;\n }\n\n static override styles = unsafeCSS(compentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-navigation-menu': ObcNavigationMenu;\n }\n}\n"],"names":["ObcNavigationMenuVariant","ObcNavigationMenuFlyoutVariant"],"mappings":"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"}
|
|
@@ -9,10 +9,13 @@ const componentStyle = css`
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
:host {
|
|
12
|
+
--_thumb-size: 48px;
|
|
13
|
+
--_thumb-half: 24px;
|
|
14
|
+
|
|
12
15
|
display: flex;
|
|
13
16
|
align-items: center;
|
|
14
17
|
justify-content: center;
|
|
15
|
-
height:
|
|
18
|
+
height: var(--_thumb-size);
|
|
16
19
|
|
|
17
20
|
color: var(--element-neutral-color, #1a1a1a);
|
|
18
21
|
}
|
|
@@ -24,7 +27,7 @@ const componentStyle = css`
|
|
|
24
27
|
|
|
25
28
|
.wrapper {
|
|
26
29
|
flex: 1;
|
|
27
|
-
height:
|
|
30
|
+
height: var(--_thumb-size);
|
|
28
31
|
position: relative;
|
|
29
32
|
}
|
|
30
33
|
|
|
@@ -65,7 +68,7 @@ const componentStyle = css`
|
|
|
65
68
|
-webkit-appearance: none;
|
|
66
69
|
appearance: none;
|
|
67
70
|
width: 100%;
|
|
68
|
-
height:
|
|
71
|
+
height: var(--_thumb-size);
|
|
69
72
|
margin: 0;
|
|
70
73
|
padding: 0;
|
|
71
74
|
background: none;
|
|
@@ -87,12 +90,31 @@ const componentStyle = css`
|
|
|
87
90
|
cursor: default;
|
|
88
91
|
}
|
|
89
92
|
|
|
93
|
+
.slider::-moz-range-track {
|
|
94
|
+
position: absolute;
|
|
95
|
+
margin: auto 0;
|
|
96
|
+
top: 0;
|
|
97
|
+
bottom: 0;
|
|
98
|
+
left: 0;
|
|
99
|
+
right: 0;
|
|
100
|
+
height: 40px;
|
|
101
|
+
border-radius: 6px;
|
|
102
|
+
cursor: pointer;
|
|
103
|
+
background: transparent;
|
|
104
|
+
border: none;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.no-input :is(.slider::-moz-range-track) {
|
|
108
|
+
cursor: default;
|
|
109
|
+
}
|
|
110
|
+
|
|
90
111
|
.container-hover {
|
|
91
112
|
position: absolute;
|
|
92
|
-
left:
|
|
113
|
+
left: calc(
|
|
114
|
+
var(--_ratio, 0) * (100% - var(--_thumb-size)) + var(--_thumb-size)
|
|
115
|
+
);
|
|
93
116
|
top: 0;
|
|
94
117
|
bottom: 0;
|
|
95
|
-
position-anchor: --thumb;
|
|
96
118
|
right: 0;
|
|
97
119
|
cursor: pointer;
|
|
98
120
|
}
|
|
@@ -160,8 +182,9 @@ const componentStyle = css`
|
|
|
160
182
|
left: 0;
|
|
161
183
|
top: 0;
|
|
162
184
|
bottom: 0;
|
|
163
|
-
|
|
164
|
-
|
|
185
|
+
right: calc(
|
|
186
|
+
(1 - var(--_ratio, 0)) * (100% - var(--_thumb-size)) + var(--_thumb-size)
|
|
187
|
+
);
|
|
165
188
|
cursor: pointer;
|
|
166
189
|
}
|
|
167
190
|
|
|
@@ -176,8 +199,9 @@ const componentStyle = css`
|
|
|
176
199
|
bottom: 0;
|
|
177
200
|
height: 4px;
|
|
178
201
|
border-radius: 6px;
|
|
179
|
-
right:
|
|
180
|
-
|
|
202
|
+
right: calc(
|
|
203
|
+
100% - var(--_ratio, 0) * (100% - var(--_thumb-size)) - var(--_thumb-half)
|
|
204
|
+
);
|
|
181
205
|
margin-top: auto;
|
|
182
206
|
margin-bottom: auto;
|
|
183
207
|
background: var(--selected-enabled-background-color);
|
|
@@ -189,7 +213,7 @@ const componentStyle = css`
|
|
|
189
213
|
|
|
190
214
|
.enhanced .interactive-track {
|
|
191
215
|
height: 32px;
|
|
192
|
-
right: calc(
|
|
216
|
+
right: calc(100% - var(--_ratio, 0) * (100% - var(--_thumb-size)) - 30px);
|
|
193
217
|
}
|
|
194
218
|
|
|
195
219
|
.interactive-track-hover:hover ~ .interactive-track,
|
|
@@ -211,33 +235,53 @@ input::-webkit-slider-thumb {
|
|
|
211
235
|
appearance: none;
|
|
212
236
|
margin: 0;
|
|
213
237
|
padding: 0;
|
|
214
|
-
width:
|
|
215
|
-
height:
|
|
238
|
+
width: var(--_thumb-size);
|
|
239
|
+
height: var(--_thumb-size);
|
|
216
240
|
background: transparent;
|
|
217
241
|
cursor: grab;
|
|
242
|
+
}
|
|
218
243
|
|
|
219
|
-
|
|
244
|
+
input::-moz-range-thumb {
|
|
245
|
+
appearance: none;
|
|
246
|
+
margin: 0;
|
|
247
|
+
padding: 0;
|
|
248
|
+
width: var(--_thumb-size);
|
|
249
|
+
height: var(--_thumb-size);
|
|
250
|
+
background: transparent;
|
|
251
|
+
border: none;
|
|
252
|
+
cursor: grab;
|
|
220
253
|
}
|
|
221
254
|
|
|
222
255
|
.no-input input::-webkit-slider-thumb {
|
|
223
256
|
cursor: default;
|
|
224
257
|
}
|
|
225
258
|
|
|
259
|
+
.no-input input::-moz-range-thumb {
|
|
260
|
+
cursor: default;
|
|
261
|
+
}
|
|
262
|
+
|
|
226
263
|
input:active::-webkit-slider-thumb {
|
|
227
264
|
cursor: grabbing;
|
|
228
265
|
}
|
|
229
266
|
|
|
267
|
+
input:active::-moz-range-thumb {
|
|
268
|
+
cursor: grabbing;
|
|
269
|
+
}
|
|
270
|
+
|
|
230
271
|
.no-input input:active::-webkit-slider-thumb {
|
|
231
272
|
cursor: default;
|
|
232
273
|
}
|
|
233
274
|
|
|
275
|
+
.no-input input:active::-moz-range-thumb {
|
|
276
|
+
cursor: default;
|
|
277
|
+
}
|
|
278
|
+
|
|
234
279
|
.thumb {
|
|
235
280
|
position: absolute;
|
|
236
|
-
top:
|
|
237
|
-
left:
|
|
238
|
-
right:
|
|
239
|
-
bottom:
|
|
240
|
-
position-anchor: --thumb;
|
|
281
|
+
top: 0;
|
|
282
|
+
left: calc(var(--_ratio, 0) * (100% - var(--_thumb-size)));
|
|
283
|
+
right: calc((1 - var(--_ratio, 0)) * (100% - var(--_thumb-size)));
|
|
284
|
+
bottom: 0;
|
|
241
285
|
border-radius: 6px;
|
|
242
286
|
border-width: 2px;
|
|
243
287
|
height: 28px;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slider.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"slider.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -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;
|
|
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+FG;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;;;;OAIG;IACuB,SAAS,SAAM;IAEzC;;;;;;;;OAQG;IACuB,OAAO,EAAE,gBAAgB,CAA2B;IAE9E;;;;OAIG;IACwB,WAAW,UAAS;IAE/C;;;;OAIG;IACwB,YAAY,UAAS;IAEhD;;;;OAIG;IACwB,YAAY,UAAS;IAEhD;;;;;OAKG;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;;OAEG;IACH,aAAa;IAKb;;OAEG;IACH,eAAe;IAKf,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;IAOjB,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,iBAAiB;IAgBzB,OAAO,CAAC,cAAc;IA0DtB,OAAO,CAAC,aAAa;IAOZ,MAAM;IA2Ef,OAAgB,MAAM,0BAA6B;CACpD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,YAAY,EAAE,SAAS,CAAC;KACzB;CACF"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { unsafeCSS, LitElement, html } from "lit";
|
|
2
2
|
import { property } from "lit/decorators.js";
|
|
3
3
|
import { ifDefined } from "lit/directives/if-defined.js";
|
|
4
|
+
import { styleMap } from "lit/directives/style-map.js";
|
|
4
5
|
import componentStyle from "./slider.css.js";
|
|
5
6
|
import "../icon-button/icon-button.js";
|
|
6
7
|
import { classMap } from "lit/directives/class-map.js";
|
|
@@ -54,6 +55,13 @@ let ObcSlider = class extends LitElement {
|
|
|
54
55
|
this.onTouchEnd();
|
|
55
56
|
};
|
|
56
57
|
}
|
|
58
|
+
get ratio() {
|
|
59
|
+
const range = this.max - this.min;
|
|
60
|
+
if (!Number.isFinite(range) || range <= 0) return 0;
|
|
61
|
+
const ratio = (this.value - this.min) / range;
|
|
62
|
+
if (!Number.isFinite(ratio)) return 0;
|
|
63
|
+
return Math.max(0, Math.min(1, ratio));
|
|
64
|
+
}
|
|
57
65
|
/**
|
|
58
66
|
* Handles input changes from the slider or buttons.
|
|
59
67
|
* Fires the `value` event with the new value.
|
|
@@ -87,10 +95,10 @@ let ObcSlider = class extends LitElement {
|
|
|
87
95
|
const left = rect.left + 24;
|
|
88
96
|
const width = rect.width - 48;
|
|
89
97
|
const thumbWidth = 48;
|
|
90
|
-
const ratioValue =
|
|
98
|
+
const ratioValue = this.ratio;
|
|
91
99
|
const thumbCenter = left + width * ratioValue;
|
|
92
100
|
let clientX;
|
|
93
|
-
if (
|
|
101
|
+
if ("touches" in e) {
|
|
94
102
|
clientX = e.touches[0].clientX;
|
|
95
103
|
} else {
|
|
96
104
|
clientX = e.clientX;
|
|
@@ -217,6 +225,9 @@ let ObcSlider = class extends LitElement {
|
|
|
217
225
|
wrapper: true,
|
|
218
226
|
[this.variant]: true,
|
|
219
227
|
disabled: this.disabled
|
|
228
|
+
})}
|
|
229
|
+
style=${styleMap({
|
|
230
|
+
"--_ratio": String(this.ratio)
|
|
220
231
|
})}
|
|
221
232
|
>
|
|
222
233
|
<div class="track"></div>
|
|
@@ -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 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 */\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 */\n @property({type: Boolean}) allowSeeking = false;\n\n /**\n * The speed of animated seeking (when `allowSeeking` is true).\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 */\n @property({type: Number}) seekingSpeed = 1 / 3;\n\n @property({type: Boolean}) disabled = false;\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 =\n parseFloat(this.slider.value) /\n (parseFloat(this.slider.max) - parseFloat(this.slider.min));\n const thumbCenter = left + width * ratioValue;\n\n let clientX: number;\n if (e instanceof TouchEvent) {\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 >\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 * `<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 */\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 */\n @property({type: Boolean}) allowSeeking = false;\n\n /**\n * The speed of animated seeking (when `allowSeeking` is true).\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 */\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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"}
|