@redvars/peacock 3.5.0 → 3.6.0
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/BaseButton-BNFAYn-S.js +219 -0
- package/dist/BaseButton-BNFAYn-S.js.map +1 -0
- package/dist/BaseHyperlinkMixin-BNuwbiEf.js +65 -0
- package/dist/BaseHyperlinkMixin-BNuwbiEf.js.map +1 -0
- package/dist/BaseInput-14YmcfK7.js +27 -0
- package/dist/BaseInput-14YmcfK7.js.map +1 -0
- package/dist/assets/components.css +1 -1
- package/dist/assets/components.css.map +1 -1
- package/dist/assets/styles.css +1 -1
- package/dist/assets/styles.css.map +1 -1
- package/dist/banner.js +14 -30
- package/dist/banner.js.map +1 -1
- package/dist/{button-DMN1dPAg.js → button-colors-Ccys3hvS.js} +5 -468
- package/dist/button-colors-Ccys3hvS.js.map +1 -0
- package/dist/button-group.js +228 -8
- package/dist/button-group.js.map +1 -1
- package/dist/button.js +294 -8
- package/dist/button.js.map +1 -1
- package/dist/calendar-column-view.js +634 -0
- package/dist/calendar-column-view.js.map +1 -0
- package/dist/calendar-event-BrQ_SEKD.js +199 -0
- package/dist/calendar-event-BrQ_SEKD.js.map +1 -0
- package/dist/calendar-month-view.js +376 -0
- package/dist/calendar-month-view.js.map +1 -0
- package/dist/calendar.js +339 -0
- package/dist/calendar.js.map +1 -0
- package/dist/canvas.js +361 -0
- package/dist/canvas.js.map +1 -0
- package/dist/card.js +18 -73
- package/dist/card.js.map +1 -1
- package/dist/cb-compound-expression.js +125 -0
- package/dist/cb-compound-expression.js.map +1 -0
- package/dist/cb-divider.js +150 -0
- package/dist/cb-divider.js.map +1 -0
- package/dist/cb-expression.js +75 -0
- package/dist/cb-expression.js.map +1 -0
- package/dist/cb-predicate.js +137 -0
- package/dist/cb-predicate.js.map +1 -0
- package/dist/chart-bar.js.map +1 -1
- package/dist/chart-doughnut.js +2 -2
- package/dist/chart-doughnut.js.map +1 -1
- package/dist/chart-pie.js +2 -2
- package/dist/chart-pie.js.map +1 -1
- package/dist/chart-stacked-bar.js.map +1 -1
- package/dist/code-editor.js +2 -1
- package/dist/code-editor.js.map +1 -1
- package/dist/code-highlighter.js +2 -1
- package/dist/code-highlighter.js.map +1 -1
- package/dist/condition-builder.js +58 -0
- package/dist/condition-builder.js.map +1 -0
- package/dist/custom-elements-jsdocs.json +10860 -5567
- package/dist/custom-elements.json +16180 -7996
- package/dist/dropdown-button.js +216 -0
- package/dist/dropdown-button.js.map +1 -0
- package/dist/event-manager-D-QCmUgR.js +113 -0
- package/dist/event-manager-D-QCmUgR.js.map +1 -0
- package/dist/fab.js +421 -9
- package/dist/fab.js.map +1 -1
- package/dist/flow-designer-dZnLJOQT.js +1656 -0
- package/dist/flow-designer-dZnLJOQT.js.map +1 -0
- package/dist/flow-designer-node-XMe-jlKg.js +548 -0
- package/dist/flow-designer-node-XMe-jlKg.js.map +1 -0
- package/dist/flow-designer-node.js +4 -0
- package/dist/flow-designer-node.js.map +1 -0
- package/dist/flow-designer.js +16 -0
- package/dist/flow-designer.js.map +1 -0
- package/dist/html-editor.js +358 -0
- package/dist/html-editor.js.map +1 -0
- package/dist/icon-button-CK1ZuE-2.js +247 -0
- package/dist/icon-button-CK1ZuE-2.js.map +1 -0
- package/dist/index.js +31 -8
- package/dist/index.js.map +1 -1
- package/dist/{is-dark-mode-DicqGkCJ.js → is-dark-mode-DOcaw4Yq.js} +2 -27
- package/dist/is-dark-mode-DOcaw4Yq.js.map +1 -0
- package/dist/modal.js +418 -0
- package/dist/modal.js.map +1 -0
- package/dist/{select-4pl4XBj7.js → navigation-rail-DyO0oAZU.js} +2000 -2767
- package/dist/navigation-rail-DyO0oAZU.js.map +1 -0
- package/dist/notification-manager.js +268 -0
- package/dist/notification-manager.js.map +1 -0
- package/dist/notification.js +3 -2
- package/dist/notification.js.map +1 -1
- package/dist/peacock-loader.js +102 -14
- package/dist/peacock-loader.js.map +1 -1
- package/dist/popover-NC7b1lTq.js +1971 -0
- package/dist/popover-NC7b1lTq.js.map +1 -0
- package/dist/popover-content.js +125 -0
- package/dist/popover-content.js.map +1 -0
- package/dist/popover.js +4 -0
- package/dist/popover.js.map +1 -0
- package/dist/search.js +4 -0
- package/dist/search.js.map +1 -1
- package/dist/split-button.js +388 -0
- package/dist/split-button.js.map +1 -0
- package/dist/src/__controllers/floating-controller.d.ts +35 -0
- package/dist/src/__mixins/BaseButtonMixin.d.ts +20 -0
- package/dist/src/__mixins/BaseHyperlinkMixin.d.ts +18 -0
- package/dist/src/__mixins/MixinConstructor.d.ts +1 -0
- package/dist/src/banner/banner.d.ts +0 -4
- package/dist/src/button/BaseButton.d.ts +4 -47
- package/dist/src/button/button/button.d.ts +32 -3
- package/dist/src/button/button-group/button-group.d.ts +2 -2
- package/dist/src/button/icon-button/icon-button.d.ts +33 -8
- package/dist/src/calendar/base-event.d.ts +10 -0
- package/dist/src/calendar/calendar-column-view.d.ts +41 -0
- package/dist/src/calendar/calendar-event.d.ts +7 -0
- package/dist/src/calendar/calendar-month-view.d.ts +31 -0
- package/dist/src/calendar/calendar.d.ts +65 -0
- package/dist/src/calendar/event-manager.d.ts +17 -0
- package/dist/src/calendar/index.d.ts +4 -0
- package/dist/src/calendar/types.d.ts +13 -0
- package/dist/src/calendar/utils.d.ts +31 -0
- package/dist/src/canvas/canvas.d.ts +92 -0
- package/dist/src/canvas/index.d.ts +2 -0
- package/dist/src/card/card.d.ts +4 -15
- package/dist/src/condition-builder/cb-compound-expression.d.ts +31 -0
- package/dist/src/condition-builder/cb-divider.d.ts +26 -0
- package/dist/src/condition-builder/cb-expression.d.ts +31 -0
- package/dist/src/condition-builder/cb-predicate.d.ts +30 -0
- package/dist/src/condition-builder/condition-builder.d.ts +27 -0
- package/dist/src/condition-builder/index.d.ts +5 -0
- package/dist/src/dropdown-button/dropdown-button.d.ts +68 -0
- package/dist/src/dropdown-button/index.d.ts +1 -0
- package/dist/src/fab/fab.d.ts +4 -35
- package/dist/src/flow-designer/commands.d.ts +66 -0
- package/dist/src/flow-designer/flow-designer-node.d.ts +46 -0
- package/dist/src/flow-designer/flow-designer.d.ts +133 -0
- package/dist/src/flow-designer/index.d.ts +7 -0
- package/dist/src/flow-designer/layout.d.ts +30 -0
- package/dist/src/flow-designer/types.d.ts +142 -0
- package/dist/src/flow-designer/validation.d.ts +43 -0
- package/dist/src/flow-designer/workflow-utils.d.ts +40 -0
- package/dist/src/focus-ring/focus-ring.d.ts +11 -5
- package/dist/src/html-editor/html-editor.d.ts +56 -0
- package/dist/src/html-editor/index.d.ts +2 -0
- package/dist/src/index.d.ts +16 -1
- package/dist/src/link/link.d.ts +1 -1
- package/dist/src/menu/menu/menu.d.ts +5 -7
- package/dist/src/menu/menu-item/menu-item.d.ts +14 -13
- package/dist/src/modal/index.d.ts +1 -0
- package/dist/src/modal/modal.d.ts +63 -0
- package/dist/src/navigation-rail/index.d.ts +2 -0
- package/dist/src/navigation-rail/navigation-rail-item.d.ts +55 -0
- package/dist/src/navigation-rail/navigation-rail.d.ts +71 -0
- package/dist/src/notification-manager/index.d.ts +1 -0
- package/dist/src/notification-manager/notification-manager.d.ts +44 -0
- package/dist/src/popover/index.d.ts +2 -0
- package/dist/src/popover/popover-content.d.ts +29 -0
- package/dist/src/popover/popover.d.ts +62 -0
- package/dist/src/sidebar-menu/index.d.ts +3 -0
- package/dist/src/sidebar-menu/sidebar-menu-item.d.ts +58 -0
- package/dist/src/sidebar-menu/sidebar-menu.d.ts +38 -0
- package/dist/src/sidebar-menu/sidebar-sub-menu.d.ts +35 -0
- package/dist/src/split-button/index.d.ts +1 -0
- package/dist/src/split-button/split-button.d.ts +72 -0
- package/dist/src/toolbar/toolbar.d.ts +10 -10
- package/dist/src/tooltip/tooltip.d.ts +5 -15
- package/dist/src/url-field/index.d.ts +1 -0
- package/dist/src/url-field/url-field.d.ts +48 -0
- package/dist/test/flow-designer.test.d.ts +1 -0
- package/dist/test/sidebar-menu.test.d.ts +1 -0
- package/dist/toolbar.js +10 -10
- package/dist/toolbar.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -2
- package/readme.md +73 -65
- package/scss/mixin.scss +16 -0
- package/src/__controllers/floating-controller.ts +237 -0
- package/src/__mixins/BaseButtonMixin.ts +83 -0
- package/src/__mixins/BaseHyperlinkMixin.ts +68 -0
- package/src/__mixins/MixinConstructor.ts +1 -0
- package/src/{__base_element → __mixins}/README.md +2 -2
- package/src/banner/banner.scss +20 -25
- package/src/banner/banner.ts +1 -7
- package/src/button/BaseButton.ts +11 -100
- package/src/button/button/button-sizes.scss +4 -2
- package/src/button/button/button.ts +77 -23
- package/src/button/button-group/button-group.ts +2 -2
- package/src/button/icon-button/icon-button.ts +75 -33
- package/src/calendar/base-event.ts +49 -0
- package/src/calendar/calendar-column-view.scss +326 -0
- package/src/calendar/calendar-column-view.ts +392 -0
- package/src/calendar/calendar-event.ts +20 -0
- package/src/calendar/calendar-month-view.scss +192 -0
- package/src/calendar/calendar-month-view.ts +244 -0
- package/src/calendar/calendar.scss +71 -0
- package/src/calendar/calendar.ts +298 -0
- package/src/calendar/event-manager.ts +117 -0
- package/src/calendar/index.ts +4 -0
- package/src/calendar/types.ts +14 -0
- package/src/calendar/utils.ts +180 -0
- package/src/canvas/canvas.scss +60 -0
- package/src/canvas/canvas.ts +391 -0
- package/src/canvas/index.ts +2 -0
- package/src/card/card.ts +11 -71
- package/src/chart-bar/chart-bar.ts +9 -14
- package/src/chart-bar/chart-stacked-bar.ts +12 -18
- package/src/chart-doughnut/chart-doughnut.ts +23 -27
- package/src/chart-pie/chart-pie.ts +19 -23
- package/src/checkbox/checkbox.scss +17 -34
- package/src/checkbox/checkbox.ts +3 -1
- package/src/code-highlighter/code-highlighter.scss +1 -0
- package/src/code-highlighter/code-highlighter.ts +1 -1
- package/src/condition-builder/cb-compound-expression.scss +37 -0
- package/src/condition-builder/cb-compound-expression.ts +80 -0
- package/src/condition-builder/cb-divider.scss +93 -0
- package/src/condition-builder/cb-divider.ts +56 -0
- package/src/condition-builder/cb-expression.scss +14 -0
- package/src/condition-builder/cb-expression.ts +49 -0
- package/src/condition-builder/cb-predicate.scss +35 -0
- package/src/condition-builder/cb-predicate.ts +102 -0
- package/src/condition-builder/condition-builder.scss +13 -0
- package/src/condition-builder/condition-builder.ts +38 -0
- package/src/condition-builder/index.ts +5 -0
- package/src/date-picker/date-picker.ts +1 -1
- package/src/dropdown-button/demo/index.html +110 -0
- package/src/dropdown-button/dropdown-button.scss +22 -0
- package/src/dropdown-button/dropdown-button.ts +206 -0
- package/src/dropdown-button/index.ts +1 -0
- package/src/elevation/elevation.scss +5 -5
- package/src/fab/fab.ts +29 -100
- package/src/flow-designer/DEMO.md +239 -0
- package/src/flow-designer/commands.ts +278 -0
- package/src/flow-designer/flow-designer-node.ts +172 -0
- package/src/flow-designer/flow-designer.scss +457 -0
- package/src/flow-designer/flow-designer.ts +611 -0
- package/src/flow-designer/index.ts +41 -0
- package/src/flow-designer/layout.ts +357 -0
- package/src/flow-designer/types.ts +166 -0
- package/src/flow-designer/validation.ts +284 -0
- package/src/flow-designer/workflow-utils.ts +282 -0
- package/src/focus-ring/focus-ring.ts +47 -40
- package/src/html-editor/html-editor.scss +146 -0
- package/src/html-editor/html-editor.ts +276 -0
- package/src/html-editor/index.ts +3 -0
- package/src/index.ts +28 -1
- package/src/input/input.ts +3 -1
- package/src/link/link.ts +2 -2
- package/src/menu/menu/menu.scss +2 -2
- package/src/menu/menu/menu.ts +91 -101
- package/src/menu/menu-item/menu-item.scss +4 -0
- package/src/menu/menu-item/menu-item.ts +85 -79
- package/src/modal/index.ts +1 -0
- package/src/modal/modal.scss +206 -0
- package/src/modal/modal.ts +201 -0
- package/src/navigation-rail/index.ts +2 -0
- package/src/navigation-rail/navigation-rail-item.scss +216 -0
- package/src/navigation-rail/navigation-rail-item.ts +223 -0
- package/src/navigation-rail/navigation-rail.scss +72 -0
- package/src/navigation-rail/navigation-rail.ts +149 -0
- package/src/notification/notification.ts +3 -2
- package/src/notification-manager/index.ts +1 -0
- package/src/notification-manager/notification-manager.scss +113 -0
- package/src/notification-manager/notification-manager.ts +199 -0
- package/src/number-field/number-field.ts +6 -4
- package/src/pagination/pagination.ts +6 -4
- package/src/peacock-loader.ts +93 -5
- package/src/popover/index.ts +2 -0
- package/src/popover/popover-content.scss +69 -0
- package/src/popover/popover-content.ts +51 -0
- package/src/popover/popover.scss +7 -0
- package/src/popover/popover.ts +170 -0
- package/src/search/search.ts +4 -0
- package/src/sidebar-menu/demo/index.html +68 -0
- package/src/sidebar-menu/index.ts +3 -0
- package/src/sidebar-menu/sidebar-menu-item.scss +102 -0
- package/src/sidebar-menu/sidebar-menu-item.ts +151 -0
- package/src/{tree-view/tree-view.scss → sidebar-menu/sidebar-menu.scss} +1 -1
- package/src/sidebar-menu/sidebar-menu.ts +182 -0
- package/src/sidebar-menu/sidebar-sub-menu.scss +130 -0
- package/src/sidebar-menu/sidebar-sub-menu.ts +160 -0
- package/src/skeleton/skeleton.scss +18 -24
- package/src/snackbar/snackbar.ts +1 -1
- package/src/split-button/index.ts +1 -0
- package/src/split-button/split-button-colors.scss +56 -0
- package/src/split-button/split-button-sizes.scss +28 -0
- package/src/split-button/split-button.scss +79 -0
- package/src/split-button/split-button.ts +236 -0
- package/src/table/table.ts +2 -2
- package/src/tabs/tab.ts +4 -3
- package/src/text/text.css-component.scss +7 -1
- package/src/time-picker/time-picker.ts +1 -1
- package/src/toolbar/toolbar.ts +10 -10
- package/src/tooltip/tooltip.scss +4 -3
- package/src/tooltip/tooltip.ts +64 -98
- package/src/url-field/index.ts +1 -0
- package/src/url-field/url-field.scss +50 -0
- package/src/url-field/url-field.ts +239 -0
- package/dist/button-DMN1dPAg.js.map +0 -1
- package/dist/button-group-CX9CUUXk.js +0 -435
- package/dist/button-group-CX9CUUXk.js.map +0 -1
- package/dist/fab-C5Nzxk0E.js +0 -497
- package/dist/fab-C5Nzxk0E.js.map +0 -1
- package/dist/is-dark-mode-DicqGkCJ.js.map +0 -1
- package/dist/select-4pl4XBj7.js.map +0 -1
- package/dist/spread-B5cgadZl.js +0 -32
- package/dist/spread-B5cgadZl.js.map +0 -1
- package/dist/src/__base_element/BaseHyperlink.d.ts +0 -20
- package/dist/src/menu/menu/MenuSurfaceController.d.ts +0 -18
- package/dist/src/tree-view/index.d.ts +0 -2
- package/dist/src/tree-view/tree-node.d.ts +0 -69
- package/dist/src/tree-view/tree-view.d.ts +0 -40
- package/dist/src/tree-view/wc-tree-view.d.ts +0 -6
- package/dist/test/tree-view.test.d.ts +0 -1
- package/dist/throttle-C7ZAPqtu.js +0 -24
- package/dist/throttle-C7ZAPqtu.js.map +0 -1
- package/src/__base_element/BaseHyperlink.ts +0 -42
- package/src/menu/menu/MenuSurfaceController.ts +0 -61
- package/src/tree-view/demo/index.html +0 -57
- package/src/tree-view/index.ts +0 -2
- package/src/tree-view/tree-node.scss +0 -101
- package/src/tree-view/tree-node.ts +0 -268
- package/src/tree-view/tree-view.ts +0 -182
- package/src/tree-view/wc-tree-view.ts +0 -9
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { html, LitElement } from 'lit';
|
|
2
|
+
import { property } from 'lit/decorators.js';
|
|
3
|
+
import type { Placement } from '@floating-ui/dom';
|
|
4
|
+
import IndividualComponent from '@/IndividualComponent.js';
|
|
5
|
+
import { FloatingController } from '../__controllers/floating-controller.js';
|
|
6
|
+
import styles from './popover.scss';
|
|
7
|
+
import type { PopoverContent } from './popover-content.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @label Popover
|
|
11
|
+
* @tag wc-popover
|
|
12
|
+
* @rawTag popover
|
|
13
|
+
* @summary Displays additional information in a floating panel anchored to a trigger element.
|
|
14
|
+
* @overview
|
|
15
|
+
* <p>The Popover component wraps a trigger element and a <code>wc-popover-content</code> child. It uses
|
|
16
|
+
* floating-ui to compute position, keeping the panel visible inside the viewport even on scroll.</p>
|
|
17
|
+
* @tags display
|
|
18
|
+
*
|
|
19
|
+
* @fires {CustomEvent} wc-popover--open - Fired when the popover opens.
|
|
20
|
+
* @fires {CustomEvent} wc-popover--close - Fired when the popover closes.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```html
|
|
24
|
+
* <wc-popover trigger="click">
|
|
25
|
+
* <wc-button>Open popover</wc-button>
|
|
26
|
+
* <wc-popover-content>
|
|
27
|
+
* <p>Popover body text goes here.</p>
|
|
28
|
+
* </wc-popover-content>
|
|
29
|
+
* </wc-popover>
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
@IndividualComponent
|
|
33
|
+
export class Popover extends LitElement {
|
|
34
|
+
static styles = [styles];
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Determines how the popover is triggered.
|
|
38
|
+
* Possible values are `"click"`, `"hover"`, `"manual"`.
|
|
39
|
+
*/
|
|
40
|
+
@property({ reflect: true }) trigger: 'click' | 'hover' | 'manual' = 'click';
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Preferred placement of the popover relative to the trigger element.
|
|
44
|
+
* Accepts any floating-ui `Placement` string such as `"bottom"`, `"top-start"`, `"right"`, etc.
|
|
45
|
+
*/
|
|
46
|
+
@property({ reflect: true }) placement: Placement = 'bottom';
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Whether the popover is open.
|
|
50
|
+
*/
|
|
51
|
+
@property({ type: Boolean, reflect: true }) open = false;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Distance in pixels between the trigger element and the popover panel.
|
|
55
|
+
*/
|
|
56
|
+
@property({ type: Number }) offset = 8;
|
|
57
|
+
|
|
58
|
+
private _floating: FloatingController | null = null;
|
|
59
|
+
|
|
60
|
+
private _contentEl: PopoverContent | null = null;
|
|
61
|
+
|
|
62
|
+
private _triggerEl: HTMLElement | null = null;
|
|
63
|
+
|
|
64
|
+
private _setupFloating() {
|
|
65
|
+
// Tear down any existing controller
|
|
66
|
+
if (this._floating) {
|
|
67
|
+
this._floating = null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Resolve the content element
|
|
71
|
+
this._contentEl = this.querySelector<PopoverContent>('wc-popover-content');
|
|
72
|
+
|
|
73
|
+
// Resolve the trigger element: first light-DOM child that is NOT wc-popover-content
|
|
74
|
+
this._triggerEl =
|
|
75
|
+
(Array.from(this.children).find(
|
|
76
|
+
(c) => c.tagName.toLowerCase() !== 'wc-popover-content',
|
|
77
|
+
) as HTMLElement) ?? null;
|
|
78
|
+
|
|
79
|
+
if (!this._triggerEl || !this._contentEl) return;
|
|
80
|
+
|
|
81
|
+
const triggerMode =
|
|
82
|
+
this.trigger === 'manual'
|
|
83
|
+
? 'manual'
|
|
84
|
+
: (this.trigger as 'click' | 'hover');
|
|
85
|
+
|
|
86
|
+
this._floating = new FloatingController(this, {
|
|
87
|
+
placement: this.placement,
|
|
88
|
+
strategy: 'fixed',
|
|
89
|
+
offset: this.offset,
|
|
90
|
+
trigger: triggerMode,
|
|
91
|
+
closeOnClickOutside: true,
|
|
92
|
+
onOpenChange: (isOpen) => {
|
|
93
|
+
this.open = isOpen;
|
|
94
|
+
if (this._contentEl) {
|
|
95
|
+
this._contentEl.open = isOpen;
|
|
96
|
+
}
|
|
97
|
+
this.dispatchEvent(
|
|
98
|
+
new CustomEvent(isOpen ? 'wc-popover--open' : 'wc-popover--close', {
|
|
99
|
+
bubbles: true,
|
|
100
|
+
composed: true,
|
|
101
|
+
}),
|
|
102
|
+
);
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
this._floating.setElements(
|
|
107
|
+
this._triggerEl,
|
|
108
|
+
this._contentEl as unknown as HTMLElement,
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
if (this.open) {
|
|
112
|
+
this._floating.open();
|
|
113
|
+
this._contentEl.open = true;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
connectedCallback() {
|
|
118
|
+
super.connectedCallback();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
firstUpdated() {
|
|
122
|
+
this._setupFloating();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
updated(changedProps: Map<string, unknown>) {
|
|
126
|
+
if (
|
|
127
|
+
changedProps.has('trigger') ||
|
|
128
|
+
changedProps.has('placement') ||
|
|
129
|
+
changedProps.has('offset')
|
|
130
|
+
) {
|
|
131
|
+
this._setupFloating();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (changedProps.has('open') && this._floating) {
|
|
135
|
+
if (this.open && !this._floating.isOpen) {
|
|
136
|
+
this._floating.open();
|
|
137
|
+
if (this._contentEl) this._contentEl.open = true;
|
|
138
|
+
} else if (!this.open && this._floating.isOpen) {
|
|
139
|
+
this._floating.close();
|
|
140
|
+
if (this._contentEl) this._contentEl.open = false;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Programmatically opens the popover.
|
|
147
|
+
*/
|
|
148
|
+
show() {
|
|
149
|
+
if (this._floating && !this._floating.isOpen) {
|
|
150
|
+
this._floating.open();
|
|
151
|
+
} else if (!this._floating) {
|
|
152
|
+
this.open = true;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Programmatically closes the popover.
|
|
158
|
+
*/
|
|
159
|
+
hide() {
|
|
160
|
+
if (this._floating && this._floating.isOpen) {
|
|
161
|
+
this._floating.close();
|
|
162
|
+
} else if (!this._floating) {
|
|
163
|
+
this.open = false;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
render() {
|
|
168
|
+
return html`<slot></slot>`;
|
|
169
|
+
}
|
|
170
|
+
}
|
package/src/search/search.ts
CHANGED
|
@@ -110,6 +110,8 @@ export class Search extends LitElement {
|
|
|
110
110
|
private __handleInput(event: InputEvent) {
|
|
111
111
|
const input = event.target as HTMLInputElement;
|
|
112
112
|
this.value = input.value;
|
|
113
|
+
// Prevent the native input event from escaping in addition to our API event.
|
|
114
|
+
event.stopPropagation();
|
|
113
115
|
this.dispatchEvent(
|
|
114
116
|
new CustomEvent('input', {
|
|
115
117
|
detail: { value: this.value },
|
|
@@ -122,6 +124,8 @@ export class Search extends LitElement {
|
|
|
122
124
|
private __handleChange(event: Event) {
|
|
123
125
|
const input = event.target as HTMLInputElement;
|
|
124
126
|
this.value = input.value;
|
|
127
|
+
// Prevent the native change event from escaping in addition to our API event.
|
|
128
|
+
event.stopPropagation();
|
|
125
129
|
this.dispatchEvent(
|
|
126
130
|
new CustomEvent('change', {
|
|
127
131
|
detail: { value: this.value },
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang='en-GB'>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset='utf-8'>
|
|
5
|
+
<meta name='viewport' content='width=device-width, initial-scale=1.0, viewport-fit=cover' />
|
|
6
|
+
<link rel='stylesheet' href='/dist/assets/styles/tokens.css' />
|
|
7
|
+
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+Mono:wght@100..900&family=Noto+Sans:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
|
|
8
|
+
|
|
9
|
+
<style>
|
|
10
|
+
body {
|
|
11
|
+
background: #fafafa;
|
|
12
|
+
padding: 2rem;
|
|
13
|
+
font-family: 'Noto Sans', sans-serif;
|
|
14
|
+
}
|
|
15
|
+
h2 {
|
|
16
|
+
margin-top: 2rem;
|
|
17
|
+
margin-bottom: 0.5rem;
|
|
18
|
+
}
|
|
19
|
+
</style>
|
|
20
|
+
</head>
|
|
21
|
+
<body>
|
|
22
|
+
|
|
23
|
+
<h2>Basic Sidebar Menu</h2>
|
|
24
|
+
<wc-sidebar-menu>
|
|
25
|
+
<wc-sidebar-sub-menu label="Documents" icon="folder" expanded>
|
|
26
|
+
<wc-sidebar-sub-menu label="Work" icon="folder" expanded>
|
|
27
|
+
<wc-sidebar-menu-item label="Project A" icon="description"></wc-sidebar-menu-item>
|
|
28
|
+
<wc-sidebar-menu-item label="Project B" icon="description"></wc-sidebar-menu-item>
|
|
29
|
+
</wc-sidebar-sub-menu>
|
|
30
|
+
<wc-sidebar-menu-item label="Personal" icon="folder"></wc-sidebar-menu-item>
|
|
31
|
+
</wc-sidebar-sub-menu>
|
|
32
|
+
<wc-sidebar-sub-menu label="Pictures" icon="image" expanded>
|
|
33
|
+
<wc-sidebar-menu-item label="Vacation 2024" icon="image"></wc-sidebar-menu-item>
|
|
34
|
+
<wc-sidebar-menu-item label="Family" icon="image"></wc-sidebar-menu-item>
|
|
35
|
+
</wc-sidebar-sub-menu>
|
|
36
|
+
</wc-sidebar-menu>
|
|
37
|
+
|
|
38
|
+
<h2>Sidebar Menu without icons</h2>
|
|
39
|
+
<wc-sidebar-menu>
|
|
40
|
+
<wc-sidebar-sub-menu label="Category 1" expanded>
|
|
41
|
+
<wc-sidebar-menu-item label="Subcategory 1.1"></wc-sidebar-menu-item>
|
|
42
|
+
<wc-sidebar-menu-item label="Subcategory 1.2"></wc-sidebar-menu-item>
|
|
43
|
+
</wc-sidebar-sub-menu>
|
|
44
|
+
<wc-sidebar-menu-item label="Category 2"></wc-sidebar-menu-item>
|
|
45
|
+
</wc-sidebar-menu>
|
|
46
|
+
|
|
47
|
+
<h2>Disabled items</h2>
|
|
48
|
+
<wc-sidebar-menu>
|
|
49
|
+
<wc-sidebar-sub-menu label="Enabled" expanded>
|
|
50
|
+
<wc-sidebar-menu-item label="Child 1"></wc-sidebar-menu-item>
|
|
51
|
+
<wc-sidebar-menu-item label="Child 2" disabled></wc-sidebar-menu-item>
|
|
52
|
+
</wc-sidebar-sub-menu>
|
|
53
|
+
<wc-sidebar-menu-item label="Disabled" disabled></wc-sidebar-menu-item>
|
|
54
|
+
</wc-sidebar-menu>
|
|
55
|
+
|
|
56
|
+
<script type='module'>
|
|
57
|
+
import '/dist/index.es2017.js';
|
|
58
|
+
|
|
59
|
+
const menu = document.querySelector('wc-sidebar-menu');
|
|
60
|
+
if (menu) {
|
|
61
|
+
menu.addEventListener('sidebar-menu:change', (e) => {
|
|
62
|
+
console.log('Selected item:', e.detail);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
</script>
|
|
66
|
+
|
|
67
|
+
</body>
|
|
68
|
+
</html>
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
@use '../../scss/mixin';
|
|
2
|
+
|
|
3
|
+
@include mixin.base-styles;
|
|
4
|
+
|
|
5
|
+
:host {
|
|
6
|
+
display: block;
|
|
7
|
+
|
|
8
|
+
// M3 sidebar menu item sizing
|
|
9
|
+
--sidebar-menu-item-height: 3rem;
|
|
10
|
+
--sidebar-menu-item-icon-size: 1.25rem;
|
|
11
|
+
--sidebar-menu-item-border-radius: var(--global-shape-corner-full, 9999px);
|
|
12
|
+
|
|
13
|
+
// M3 color tokens
|
|
14
|
+
--sidebar-menu-item-label-color: var(--color-on-surface);
|
|
15
|
+
--sidebar-menu-item-icon-color: var(--color-on-surface-variant);
|
|
16
|
+
--sidebar-menu-item-selected-background: var(--color-secondary-container);
|
|
17
|
+
--sidebar-menu-item-selected-color: var(--color-on-secondary-container);
|
|
18
|
+
--sidebar-menu-item-focus-ring-color: var(--color-primary);
|
|
19
|
+
|
|
20
|
+
// M3 animation timing
|
|
21
|
+
--sidebar-menu-item-transition-duration: 200ms;
|
|
22
|
+
--sidebar-menu-item-transition-easing: cubic-bezier(0.4, 0, 0.2, 1);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.sidebar-menu-item {
|
|
26
|
+
position: relative;
|
|
27
|
+
display: flex;
|
|
28
|
+
align-items: center;
|
|
29
|
+
min-height: var(--sidebar-menu-item-height);
|
|
30
|
+
border-radius: var(--sidebar-menu-item-border-radius);
|
|
31
|
+
color: var(--_label-color);
|
|
32
|
+
cursor: pointer;
|
|
33
|
+
user-select: none;
|
|
34
|
+
text-decoration: none;
|
|
35
|
+
outline: none;
|
|
36
|
+
|
|
37
|
+
--_container-color: transparent;
|
|
38
|
+
--_container-opacity: 1;
|
|
39
|
+
--_label-color: var(--sidebar-menu-item-label-color);
|
|
40
|
+
|
|
41
|
+
@include mixin.get-typography(label-large);
|
|
42
|
+
|
|
43
|
+
&.selected {
|
|
44
|
+
--_container-color: var(--sidebar-menu-item-selected-background);
|
|
45
|
+
--_label-color: var(--sidebar-menu-item-selected-color);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
&.disabled {
|
|
49
|
+
cursor: not-allowed;
|
|
50
|
+
opacity: 0.6;
|
|
51
|
+
|
|
52
|
+
.ripple {
|
|
53
|
+
display: none;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.sidebar-menu-item-content {
|
|
59
|
+
display: flex;
|
|
60
|
+
align-items: center;
|
|
61
|
+
gap: 0.25rem;
|
|
62
|
+
flex: 1;
|
|
63
|
+
min-height: var(--sidebar-menu-item-height);
|
|
64
|
+
padding-inline: 0.75rem;
|
|
65
|
+
color: inherit;
|
|
66
|
+
z-index: 1;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.background {
|
|
70
|
+
position: absolute;
|
|
71
|
+
inset: 0;
|
|
72
|
+
background-color: var(--_container-color);
|
|
73
|
+
opacity: var(--_container-opacity);
|
|
74
|
+
border-radius: inherit;
|
|
75
|
+
pointer-events: none;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.focus-ring {
|
|
79
|
+
z-index: 2;
|
|
80
|
+
--focus-ring-color: var(--sidebar-menu-item-focus-ring-color);
|
|
81
|
+
--focus-ring-container-shape-start-start: var(--sidebar-menu-item-border-radius);
|
|
82
|
+
--focus-ring-container-shape-start-end: var(--sidebar-menu-item-border-radius);
|
|
83
|
+
--focus-ring-container-shape-end-start: var(--sidebar-menu-item-border-radius);
|
|
84
|
+
--focus-ring-container-shape-end-end: var(--sidebar-menu-item-border-radius);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.ripple {
|
|
88
|
+
--ripple-pressed-color: var(--color-on-surface);
|
|
89
|
+
border-radius: inherit;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.sidebar-menu-item.selected .ripple {
|
|
93
|
+
--ripple-pressed-color: var(--sidebar-menu-item-selected-color);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.sidebar-menu-item-label {
|
|
97
|
+
flex: 1;
|
|
98
|
+
overflow: hidden;
|
|
99
|
+
text-overflow: ellipsis;
|
|
100
|
+
white-space: nowrap;
|
|
101
|
+
}
|
|
102
|
+
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { html, LitElement } from 'lit';
|
|
2
|
+
import { property, query } from 'lit/decorators.js';
|
|
3
|
+
import { classMap } from 'lit/directives/class-map.js';
|
|
4
|
+
import styles from './sidebar-menu-item.scss';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @label Sidebar Menu Item
|
|
8
|
+
* @tag wc-sidebar-menu-item
|
|
9
|
+
* @rawTag sidebar-menu-item
|
|
10
|
+
* @parentRawTag sidebar-menu
|
|
11
|
+
* @summary A sidebar menu item represents a selectable leaf item in the sidebar navigation tree.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```html
|
|
15
|
+
* <wc-sidebar-menu>
|
|
16
|
+
* <wc-sidebar-sub-menu label="Parent" expanded>
|
|
17
|
+
* <wc-sidebar-menu-item label="Child"></wc-sidebar-menu-item>
|
|
18
|
+
* </wc-sidebar-sub-menu>
|
|
19
|
+
* </wc-sidebar-menu>
|
|
20
|
+
* ```
|
|
21
|
+
* @tags navigation
|
|
22
|
+
*/
|
|
23
|
+
export class SidebarMenuItem extends LitElement {
|
|
24
|
+
static styles = [styles];
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The value used to identify this item when selected.
|
|
28
|
+
*/
|
|
29
|
+
@property({ type: String, reflect: true })
|
|
30
|
+
value: string = '';
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The display label for this item.
|
|
34
|
+
*/
|
|
35
|
+
@property({ type: String, reflect: true })
|
|
36
|
+
label: string = '';
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Optional icon name to display before the label.
|
|
40
|
+
*/
|
|
41
|
+
@property({ type: String, reflect: true })
|
|
42
|
+
icon: string = '';
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Optional hyperlink to navigate to on click.
|
|
46
|
+
*/
|
|
47
|
+
@property({ type: String, reflect: true })
|
|
48
|
+
href: string = '';
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Sets or retrieves the window or frame at which to target content.
|
|
52
|
+
*/
|
|
53
|
+
@property({ type: String, reflect: true })
|
|
54
|
+
target: string = '_self';
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* If true, the user cannot interact with the item.
|
|
58
|
+
*/
|
|
59
|
+
@property({ type: Boolean, reflect: true })
|
|
60
|
+
disabled: boolean = false;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Whether the item is currently selected.
|
|
64
|
+
*/
|
|
65
|
+
@property({ type: Boolean, reflect: true })
|
|
66
|
+
selected: boolean = false;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* The nesting depth level (set automatically by the parent sidebar-menu).
|
|
70
|
+
*/
|
|
71
|
+
@property({ type: Number, reflect: true })
|
|
72
|
+
level: number = 0;
|
|
73
|
+
|
|
74
|
+
@query('.sidebar-menu-item-content')
|
|
75
|
+
private readonly _nativeElement!: HTMLElement | null;
|
|
76
|
+
|
|
77
|
+
override focus() {
|
|
78
|
+
this._nativeElement?.focus();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
override blur() {
|
|
82
|
+
this._nativeElement?.blur();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private _onClick = () => {
|
|
86
|
+
if (this.disabled) return;
|
|
87
|
+
|
|
88
|
+
this.dispatchEvent(
|
|
89
|
+
new CustomEvent('sidebar-menu-item:click', {
|
|
90
|
+
bubbles: true,
|
|
91
|
+
composed: true,
|
|
92
|
+
detail: { value: this.value, label: this.label },
|
|
93
|
+
}),
|
|
94
|
+
);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
override render() {
|
|
98
|
+
const classes = classMap({
|
|
99
|
+
'sidebar-menu-item': true,
|
|
100
|
+
disabled: this.disabled,
|
|
101
|
+
selected: this.selected,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const content = html`
|
|
105
|
+
<wc-focus-ring class="focus-ring" for="item"></wc-focus-ring>
|
|
106
|
+
<div class="background"></div>
|
|
107
|
+
<wc-ripple class="ripple"></wc-ripple>
|
|
108
|
+
<div class="sidebar-menu-item-content">
|
|
109
|
+
${this.icon ? html`<wc-icon name="${this.icon}"></wc-icon>` : ''}
|
|
110
|
+
<span class="sidebar-menu-item-label">${this.label}</span>
|
|
111
|
+
</div>
|
|
112
|
+
`;
|
|
113
|
+
|
|
114
|
+
if (this.href) {
|
|
115
|
+
return html`
|
|
116
|
+
<a
|
|
117
|
+
id="item"
|
|
118
|
+
href="${this.href}"
|
|
119
|
+
target="${this.target}"
|
|
120
|
+
class="${classes}"
|
|
121
|
+
aria-disabled="${this.disabled}"
|
|
122
|
+
tabindex="${this.disabled ? -1 : 0}"
|
|
123
|
+
@click="${this._onClick}"
|
|
124
|
+
>
|
|
125
|
+
${content}
|
|
126
|
+
</a>
|
|
127
|
+
`;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return html`
|
|
131
|
+
<div
|
|
132
|
+
id="item"
|
|
133
|
+
class="${classes}"
|
|
134
|
+
role="treeitem"
|
|
135
|
+
aria-label="${this.label}"
|
|
136
|
+
aria-selected="${String(this.selected)}"
|
|
137
|
+
aria-disabled="${this.disabled}"
|
|
138
|
+
tabindex="${this.disabled ? -1 : 0}"
|
|
139
|
+
@click="${this._onClick}"
|
|
140
|
+
@keydown="${(e: KeyboardEvent) => {
|
|
141
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
142
|
+
e.preventDefault();
|
|
143
|
+
this._onClick();
|
|
144
|
+
}
|
|
145
|
+
}}"
|
|
146
|
+
>
|
|
147
|
+
${content}
|
|
148
|
+
</div>
|
|
149
|
+
`;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { html, LitElement } from 'lit';
|
|
2
|
+
import { property } from 'lit/decorators.js';
|
|
3
|
+
import styles from './sidebar-menu.scss';
|
|
4
|
+
import { SidebarMenuItem } from './sidebar-menu-item.js';
|
|
5
|
+
import { SidebarSubMenu } from './sidebar-sub-menu.js';
|
|
6
|
+
|
|
7
|
+
type SidebarNode = SidebarMenuItem | SidebarSubMenu;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @label Sidebar Menu
|
|
11
|
+
* @tag wc-sidebar-menu
|
|
12
|
+
* @rawTag sidebar-menu
|
|
13
|
+
* @summary A sidebar menu is a hierarchical structure that provides nested levels of navigation. It supports keyboard navigation, single/multi select, and expandable items.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```html
|
|
17
|
+
* <wc-sidebar-menu>
|
|
18
|
+
* <wc-sidebar-sub-menu label="Parent" expanded>
|
|
19
|
+
* <wc-sidebar-menu-item label="Child 1"></wc-sidebar-menu-item>
|
|
20
|
+
* <wc-sidebar-menu-item label="Child 2"></wc-sidebar-menu-item>
|
|
21
|
+
* </wc-sidebar-sub-menu>
|
|
22
|
+
* </wc-sidebar-menu>
|
|
23
|
+
* ```
|
|
24
|
+
* @tags navigation
|
|
25
|
+
*/
|
|
26
|
+
export class SidebarMenu extends LitElement {
|
|
27
|
+
static styles = [styles];
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The value of the currently selected item.
|
|
31
|
+
*/
|
|
32
|
+
@property({ type: String, attribute: 'selected-item', reflect: true })
|
|
33
|
+
selectedItem: string = '';
|
|
34
|
+
|
|
35
|
+
connectedCallback() {
|
|
36
|
+
super.connectedCallback();
|
|
37
|
+
this.addEventListener('sidebar-menu-item:click', this._onItemClick as EventListener);
|
|
38
|
+
this.addEventListener('keydown', this._onKeyDown);
|
|
39
|
+
this.setAttribute('role', 'tree');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
updated(changedProps: Map<string, unknown>) {
|
|
43
|
+
super.updated(changedProps);
|
|
44
|
+
|
|
45
|
+
if (changedProps.has('selectedItem')) {
|
|
46
|
+
this._syncSelectedStateFromProperty();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
disconnectedCallback() {
|
|
51
|
+
super.disconnectedCallback();
|
|
52
|
+
this.removeEventListener('sidebar-menu-item:click', this._onItemClick as EventListener);
|
|
53
|
+
this.removeEventListener('keydown', this._onKeyDown);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private _isSidebarNode(element: Element): element is SidebarNode {
|
|
57
|
+
const tag = element.tagName.toLowerCase();
|
|
58
|
+
return tag === 'wc-sidebar-menu-item' || tag === 'wc-sidebar-sub-menu';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private _getTopLevelItems(): SidebarNode[] {
|
|
62
|
+
return Array.from(this.children).filter(
|
|
63
|
+
el => this._isSidebarNode(el),
|
|
64
|
+
) as SidebarNode[];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private _getChildNodes(item: SidebarSubMenu): SidebarNode[] {
|
|
68
|
+
return Array.from(item.children).filter(
|
|
69
|
+
child => this._isSidebarNode(child),
|
|
70
|
+
) as SidebarNode[];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private _getAllVisibleItems(): SidebarNode[] {
|
|
74
|
+
const result: SidebarNode[] = [];
|
|
75
|
+
const collect = (items: SidebarNode[]) => {
|
|
76
|
+
items.forEach(item => {
|
|
77
|
+
result.push(item);
|
|
78
|
+
if (item instanceof SidebarSubMenu && item.expanded) {
|
|
79
|
+
collect(this._getChildNodes(item));
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
collect(this._getTopLevelItems());
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private _onItemClick = (event: CustomEvent) => {
|
|
88
|
+
const item = event.target as SidebarNode;
|
|
89
|
+
if (item.disabled) return;
|
|
90
|
+
|
|
91
|
+
const value = event.detail?.value ?? item.value ?? item.label;
|
|
92
|
+
this.selectedItem = value;
|
|
93
|
+
|
|
94
|
+
// Update selected state on all items
|
|
95
|
+
this._updateSelectedState(value);
|
|
96
|
+
|
|
97
|
+
this.dispatchEvent(
|
|
98
|
+
new CustomEvent('sidebar-menu:change', {
|
|
99
|
+
bubbles: true,
|
|
100
|
+
composed: true,
|
|
101
|
+
detail: { value, item },
|
|
102
|
+
}),
|
|
103
|
+
);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
private _updateSelectedState(selectedValue: string) {
|
|
107
|
+
const allItems = this._collectAllItems(this._getTopLevelItems());
|
|
108
|
+
allItems.forEach(item => {
|
|
109
|
+
const itemValue = item.value || item.label;
|
|
110
|
+
// eslint-disable-next-line no-param-reassign
|
|
111
|
+
item.selected = itemValue === selectedValue;
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private _collectAllItems(items: SidebarNode[]): SidebarNode[] {
|
|
116
|
+
const result: SidebarNode[] = [];
|
|
117
|
+
items.forEach(item => {
|
|
118
|
+
result.push(item);
|
|
119
|
+
if (item instanceof SidebarSubMenu) {
|
|
120
|
+
result.push(...this._collectAllItems(this._getChildNodes(item)));
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
private _syncSelectedStateFromProperty() {
|
|
127
|
+
const allItems = this._collectAllItems(this._getTopLevelItems());
|
|
128
|
+
allItems.forEach(item => {
|
|
129
|
+
const itemValue = item.value || item.label;
|
|
130
|
+
item.selected = itemValue === this.selectedItem;
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
private _onKeyDown = (event: KeyboardEvent) => {
|
|
135
|
+
const allVisible = this._getAllVisibleItems();
|
|
136
|
+
const currentElement = event.composedPath().find(
|
|
137
|
+
target => target instanceof SidebarMenuItem || target instanceof SidebarSubMenu,
|
|
138
|
+
) as SidebarNode | undefined;
|
|
139
|
+
|
|
140
|
+
if (!currentElement) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (!allVisible.includes(currentElement)) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const currentIndex = allVisible.indexOf(currentElement);
|
|
149
|
+
|
|
150
|
+
if (event.key === 'ArrowDown') {
|
|
151
|
+
event.preventDefault();
|
|
152
|
+
const nextIndex = (currentIndex + 1) % allVisible.length;
|
|
153
|
+
allVisible[nextIndex].focus();
|
|
154
|
+
} else if (event.key === 'ArrowUp') {
|
|
155
|
+
event.preventDefault();
|
|
156
|
+
const prevIndex = currentIndex === 0 ? allVisible.length - 1 : currentIndex - 1;
|
|
157
|
+
allVisible[prevIndex].focus();
|
|
158
|
+
} else if (event.key === 'Enter' || event.key === ' ') {
|
|
159
|
+
event.preventDefault();
|
|
160
|
+
currentElement.click();
|
|
161
|
+
} else if (event.key === 'ArrowRight') {
|
|
162
|
+
event.preventDefault();
|
|
163
|
+
if (currentElement instanceof SidebarSubMenu && !currentElement.expanded) {
|
|
164
|
+
currentElement.expanded = true;
|
|
165
|
+
} else if (currentElement instanceof SidebarSubMenu) {
|
|
166
|
+
const children = this._getChildNodes(currentElement);
|
|
167
|
+
if (children.length > 0) {
|
|
168
|
+
children[0].focus();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
} else if (event.key === 'ArrowLeft') {
|
|
172
|
+
event.preventDefault();
|
|
173
|
+
if (currentElement instanceof SidebarSubMenu && currentElement.expanded) {
|
|
174
|
+
currentElement.expanded = false;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
override render() {
|
|
180
|
+
return html` <div class="sidebar-menu"><slot></slot></div> `;
|
|
181
|
+
}
|
|
182
|
+
}
|