@redvars/peacock 3.5.0 → 3.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/dist/BaseButton-DuASuVth.js +219 -0
  2. package/dist/BaseButton-DuASuVth.js.map +1 -0
  3. package/dist/BaseHyperlinkMixin-BNuwbiEf.js +65 -0
  4. package/dist/BaseHyperlinkMixin-BNuwbiEf.js.map +1 -0
  5. package/dist/assets/components.css +1 -1
  6. package/dist/assets/components.css.map +1 -1
  7. package/dist/assets/styles.css +1 -1
  8. package/dist/assets/styles.css.map +1 -1
  9. package/dist/banner.js +12 -27
  10. package/dist/banner.js.map +1 -1
  11. package/dist/{button-DMN1dPAg.js → button-DouvOfEU.js} +77 -251
  12. package/dist/button-DouvOfEU.js.map +1 -0
  13. package/dist/{button-group-CX9CUUXk.js → button-group-CEdMwvJJ.js} +71 -42
  14. package/dist/button-group-CEdMwvJJ.js.map +1 -0
  15. package/dist/button-group.js +5 -5
  16. package/dist/button.js +3 -3
  17. package/dist/card.js +18 -73
  18. package/dist/card.js.map +1 -1
  19. package/dist/chart-bar.js.map +1 -1
  20. package/dist/chart-doughnut.js +2 -2
  21. package/dist/chart-doughnut.js.map +1 -1
  22. package/dist/chart-pie.js +2 -2
  23. package/dist/chart-pie.js.map +1 -1
  24. package/dist/chart-stacked-bar.js.map +1 -1
  25. package/dist/code-highlighter.js +2 -1
  26. package/dist/code-highlighter.js.map +1 -1
  27. package/dist/custom-elements-jsdocs.json +3105 -1494
  28. package/dist/custom-elements.json +9244 -7829
  29. package/dist/fab.js +421 -9
  30. package/dist/fab.js.map +1 -1
  31. package/dist/index.js +6 -6
  32. package/dist/{select-4pl4XBj7.js → navigation-rail-Lxetd5-Z.js} +2214 -1090
  33. package/dist/navigation-rail-Lxetd5-Z.js.map +1 -0
  34. package/dist/notification.js +3 -2
  35. package/dist/notification.js.map +1 -1
  36. package/dist/peacock-loader.js +22 -10
  37. package/dist/peacock-loader.js.map +1 -1
  38. package/dist/search.js +4 -0
  39. package/dist/search.js.map +1 -1
  40. package/dist/src/__mixins/BaseButtonMixin.d.ts +20 -0
  41. package/dist/src/__mixins/BaseHyperlinkMixin.d.ts +18 -0
  42. package/dist/src/__mixins/MixinConstructor.d.ts +1 -0
  43. package/dist/src/banner/banner.d.ts +0 -4
  44. package/dist/src/button/BaseButton.d.ts +4 -47
  45. package/dist/src/button/button/button.d.ts +32 -3
  46. package/dist/src/button/button-group/button-group.d.ts +2 -2
  47. package/dist/src/button/icon-button/icon-button.d.ts +33 -8
  48. package/dist/src/card/card.d.ts +4 -15
  49. package/dist/src/fab/fab.d.ts +4 -35
  50. package/dist/src/focus-ring/focus-ring.d.ts +11 -5
  51. package/dist/src/index.d.ts +3 -1
  52. package/dist/src/link/link.d.ts +1 -1
  53. package/dist/src/navigation-rail/index.d.ts +2 -0
  54. package/dist/src/navigation-rail/navigation-rail-item.d.ts +55 -0
  55. package/dist/src/navigation-rail/navigation-rail.d.ts +71 -0
  56. package/dist/src/sidebar-menu/index.d.ts +3 -0
  57. package/dist/src/sidebar-menu/sidebar-menu-item.d.ts +58 -0
  58. package/dist/src/sidebar-menu/sidebar-menu.d.ts +38 -0
  59. package/dist/src/sidebar-menu/sidebar-sub-menu.d.ts +35 -0
  60. package/dist/src/toolbar/toolbar.d.ts +10 -10
  61. package/dist/src/tooltip/tooltip.d.ts +3 -0
  62. package/dist/src/url-field/index.d.ts +1 -0
  63. package/dist/src/url-field/url-field.d.ts +48 -0
  64. package/dist/test/sidebar-menu.test.d.ts +1 -0
  65. package/dist/toolbar.js +10 -10
  66. package/dist/toolbar.js.map +1 -1
  67. package/dist/tsconfig.tsbuildinfo +1 -1
  68. package/package.json +1 -1
  69. package/readme.md +73 -65
  70. package/scss/mixin.scss +16 -0
  71. package/src/__mixins/BaseButtonMixin.ts +83 -0
  72. package/src/__mixins/BaseHyperlinkMixin.ts +68 -0
  73. package/src/__mixins/MixinConstructor.ts +1 -0
  74. package/src/{__base_element → __mixins}/README.md +2 -2
  75. package/src/banner/banner.scss +18 -22
  76. package/src/banner/banner.ts +1 -7
  77. package/src/button/BaseButton.ts +11 -100
  78. package/src/button/button/button-sizes.scss +4 -2
  79. package/src/button/button/button.ts +76 -23
  80. package/src/button/button-group/button-group.ts +2 -2
  81. package/src/button/icon-button/icon-button.ts +75 -33
  82. package/src/card/card.ts +11 -71
  83. package/src/chart-bar/chart-bar.ts +9 -14
  84. package/src/chart-bar/chart-stacked-bar.ts +12 -18
  85. package/src/chart-doughnut/chart-doughnut.ts +23 -27
  86. package/src/chart-pie/chart-pie.ts +19 -23
  87. package/src/checkbox/checkbox.scss +17 -34
  88. package/src/checkbox/checkbox.ts +3 -1
  89. package/src/code-highlighter/code-highlighter.scss +1 -0
  90. package/src/code-highlighter/code-highlighter.ts +1 -1
  91. package/src/date-picker/date-picker.ts +1 -1
  92. package/src/elevation/elevation.scss +5 -5
  93. package/src/fab/fab.ts +29 -100
  94. package/src/focus-ring/focus-ring.ts +47 -40
  95. package/src/index.ts +3 -1
  96. package/src/input/input.ts +3 -1
  97. package/src/link/link.ts +2 -2
  98. package/src/menu/menu-item/menu-item.ts +3 -1
  99. package/src/navigation-rail/index.ts +2 -0
  100. package/src/navigation-rail/navigation-rail-item.scss +216 -0
  101. package/src/navigation-rail/navigation-rail-item.ts +223 -0
  102. package/src/navigation-rail/navigation-rail.scss +72 -0
  103. package/src/navigation-rail/navigation-rail.ts +149 -0
  104. package/src/notification/notification.ts +3 -2
  105. package/src/number-field/number-field.ts +6 -4
  106. package/src/pagination/pagination.ts +6 -4
  107. package/src/peacock-loader.ts +22 -5
  108. package/src/search/search.ts +4 -0
  109. package/src/sidebar-menu/demo/index.html +68 -0
  110. package/src/sidebar-menu/index.ts +3 -0
  111. package/src/sidebar-menu/sidebar-menu-item.scss +102 -0
  112. package/src/sidebar-menu/sidebar-menu-item.ts +151 -0
  113. package/src/{tree-view/tree-view.scss → sidebar-menu/sidebar-menu.scss} +1 -1
  114. package/src/sidebar-menu/sidebar-menu.ts +182 -0
  115. package/src/sidebar-menu/sidebar-sub-menu.scss +130 -0
  116. package/src/sidebar-menu/sidebar-sub-menu.ts +160 -0
  117. package/src/skeleton/skeleton.scss +18 -24
  118. package/src/snackbar/snackbar.ts +1 -1
  119. package/src/tabs/tab.ts +4 -3
  120. package/src/text/text.css-component.scss +7 -1
  121. package/src/time-picker/time-picker.ts +1 -1
  122. package/src/toolbar/toolbar.ts +10 -10
  123. package/src/tooltip/tooltip.ts +24 -0
  124. package/src/url-field/index.ts +1 -0
  125. package/src/url-field/url-field.scss +50 -0
  126. package/src/url-field/url-field.ts +239 -0
  127. package/dist/button-DMN1dPAg.js.map +0 -1
  128. package/dist/button-group-CX9CUUXk.js.map +0 -1
  129. package/dist/fab-C5Nzxk0E.js +0 -497
  130. package/dist/fab-C5Nzxk0E.js.map +0 -1
  131. package/dist/select-4pl4XBj7.js.map +0 -1
  132. package/dist/spread-B5cgadZl.js +0 -32
  133. package/dist/spread-B5cgadZl.js.map +0 -1
  134. package/dist/src/__base_element/BaseHyperlink.d.ts +0 -20
  135. package/dist/src/tree-view/index.d.ts +0 -2
  136. package/dist/src/tree-view/tree-node.d.ts +0 -69
  137. package/dist/src/tree-view/tree-view.d.ts +0 -40
  138. package/dist/src/tree-view/wc-tree-view.d.ts +0 -6
  139. package/dist/test/tree-view.test.d.ts +0 -1
  140. package/dist/throttle-C7ZAPqtu.js +0 -24
  141. package/dist/throttle-C7ZAPqtu.js.map +0 -1
  142. package/src/__base_element/BaseHyperlink.ts +0 -42
  143. package/src/tree-view/demo/index.html +0 -57
  144. package/src/tree-view/index.ts +0 -2
  145. package/src/tree-view/tree-node.scss +0 -101
  146. package/src/tree-view/tree-node.ts +0 -268
  147. package/src/tree-view/tree-view.ts +0 -182
  148. package/src/tree-view/wc-tree-view.ts +0 -9
@@ -0,0 +1,223 @@
1
+ import { html, LitElement, nothing } from 'lit';
2
+ import { property, query, state } from 'lit/decorators.js';
3
+ import { classMap } from 'lit/directives/class-map.js';
4
+ import { dispatchActivationClick, isActivationClick } from '@/__utils/dispatch-event-utils.js';
5
+ import { observerSlotChangesWithCallback } from '@/__utils/observe-slot-change.js';
6
+ import { throttle } from '@/__utils/throttle.js';
7
+ import styles from './navigation-rail-item.scss';
8
+
9
+ /**
10
+ * @label Navigation Rail Item
11
+ * @tag wc-navigation-rail-item
12
+ * @rawTag navigation-rail-item
13
+ * @parentRawTag navigation-rail
14
+ *
15
+ * @summary An individual item within a navigation rail.
16
+ * @overview
17
+ * <p>Navigation rail items display a destination with an icon and optional label.</p>
18
+ *
19
+ * @example
20
+ * ```html
21
+ * <wc-navigation-rail-item>
22
+ * <wc-icon slot="icon">home</wc-icon>
23
+ * Home
24
+ * </wc-navigation-rail-item>
25
+ * ```
26
+ * @tags navigation
27
+ */
28
+ export class NavigationRailItem extends LitElement {
29
+ #id = crypto.randomUUID();
30
+
31
+ static styles = [styles];
32
+
33
+ /** Whether this item is currently active/selected. */
34
+ @property({ type: Boolean, reflect: true }) active = false;
35
+
36
+ /** Whether this item is disabled. */
37
+ @property({ type: Boolean, reflect: true }) disabled = false;
38
+
39
+ /** Whether the parent rail is in collapsed mode (labels hidden). */
40
+ @property({ type: Boolean, reflect: true }) collapsed = false;
41
+
42
+ /** If provided, the item renders as a link. */
43
+ @property({ reflect: true }) href?: string;
44
+
45
+ /** Link target. */
46
+ @property() target: string = '_self';
47
+
48
+ /** Value used for identification when managing active state externally. */
49
+ @property({ reflect: true }) value?: string;
50
+
51
+ /** Reason the item is disabled (shown to screen readers). */
52
+ @property({ attribute: 'disabled-reason' }) disabledReason: string = '';
53
+
54
+ /** Sets the delay for throttle in milliseconds. Defaults to 200 milliseconds. */
55
+ @property({ type: Number }) throttleDelay = 200;
56
+
57
+ @state() private _isPressed = false;
58
+
59
+ @state() private _hasLabel = false;
60
+
61
+ @state() private _hasActiveIcon = false;
62
+
63
+ @query('.item-element') readonly itemElement!: HTMLElement | null;
64
+
65
+ override focus() {
66
+ this.itemElement?.focus();
67
+ }
68
+
69
+ override blur() {
70
+ this.itemElement?.blur();
71
+ }
72
+
73
+ override firstUpdated() {
74
+ this.__dispatchClickWithThrottle = throttle(
75
+ this.__dispatchClick,
76
+ this.throttleDelay,
77
+ );
78
+
79
+ observerSlotChangesWithCallback(
80
+ this.renderRoot.querySelector('slot:not([name])'),
81
+ hasContent => {
82
+ this._hasLabel = hasContent;
83
+ this.requestUpdate();
84
+ },
85
+ );
86
+
87
+ observerSlotChangesWithCallback(
88
+ this.renderRoot.querySelector('slot[name="active-icon"]'),
89
+ hasContent => {
90
+ this._hasActiveIcon = hasContent;
91
+ this.requestUpdate();
92
+ },
93
+ );
94
+ }
95
+
96
+ __dispatchClickWithThrottle: (event: MouseEvent | KeyboardEvent) => void =
97
+ event => {
98
+ this.__dispatchClick(event);
99
+ };
100
+
101
+ __dispatchClick = (event: MouseEvent | KeyboardEvent) => {
102
+ if (this.disabled && this.href) {
103
+ event.stopImmediatePropagation();
104
+ event.preventDefault();
105
+ return;
106
+ }
107
+
108
+ if (!isActivationClick(event) || !this.itemElement) {
109
+ return;
110
+ }
111
+
112
+ this.focus();
113
+ dispatchActivationClick(this.itemElement);
114
+ };
115
+
116
+ __handlePress = (event: KeyboardEvent | MouseEvent) => {
117
+ if (this.disabled) return;
118
+ if (
119
+ event instanceof KeyboardEvent &&
120
+ event.type === 'keydown' &&
121
+ (event.key === 'Enter' || event.key === ' ')
122
+ ) {
123
+ this._isPressed = true;
124
+ } else if (event.type === 'mousedown') {
125
+ this._isPressed = true;
126
+ } else {
127
+ this._isPressed = false;
128
+ }
129
+ };
130
+
131
+ __isLink() {
132
+ return !!this.href;
133
+ }
134
+
135
+ __getDisabledReasonID() {
136
+ return this.disabled && this.disabledReason
137
+ ? `disabled-reason-${this.#id}`
138
+ : nothing;
139
+ }
140
+
141
+ __renderDisabledReason() {
142
+ const disabledReasonID = this.__getDisabledReasonID();
143
+ if (disabledReasonID)
144
+ return html`<div
145
+ id="disabled-reason-${this.#id}"
146
+ role="tooltip"
147
+ aria-label=${this.disabledReason}
148
+ class="screen-reader-only"
149
+ >
150
+ ${this.disabledReason}
151
+ </div>`;
152
+ return nothing;
153
+ }
154
+
155
+ __renderItemContent() {
156
+ return html`
157
+ <wc-focus-ring class="focus-ring" for='item'></wc-focus-ring>
158
+ <div class="state-layer"></div>
159
+ <wc-ripple class="ripple"></wc-ripple>
160
+
161
+ <div class="item-content">
162
+ <div class="indicator">
163
+ <div class="icon-container">
164
+ <slot name="active-icon" class="active-icon-slot"></slot>
165
+ <slot name="icon" class="icon-slot"></slot>
166
+ </div>
167
+ </div>
168
+ ${this._hasLabel && !this.collapsed
169
+ ? html`<div class="label"><slot></slot></div>`
170
+ : html`<slot class="hidden-slot"></slot>`}
171
+ </div>
172
+
173
+ ${this.__renderDisabledReason()}
174
+ `;
175
+ }
176
+
177
+ render() {
178
+ const isLink = this.__isLink();
179
+
180
+ const cssClasses = {
181
+ item: true,
182
+ 'item-element': true,
183
+ active: this.active,
184
+ disabled: this.disabled,
185
+ pressed: this._isPressed,
186
+ 'has-label': this._hasLabel,
187
+ 'has-active-icon': this._hasActiveIcon,
188
+ };
189
+
190
+ if (!isLink) {
191
+ return html`<button
192
+ id="item"
193
+ class=${classMap(cssClasses)}
194
+ ?disabled=${this.disabled}
195
+ aria-disabled=${`${this.disabled}`}
196
+ aria-current=${this.active ? 'page' : nothing}
197
+ ?aria-describedby=${this.__getDisabledReasonID()}
198
+ @click=${this.__dispatchClickWithThrottle}
199
+ @mousedown=${this.__handlePress}
200
+ @keydown=${this.__handlePress}
201
+ @keyup=${this.__handlePress}
202
+ >
203
+ ${this.__renderItemContent()}
204
+ </button>`;
205
+ }
206
+
207
+ return html`<a
208
+ id="item"
209
+ class=${classMap(cssClasses)}
210
+ href=${this.href}
211
+ target=${this.target}
212
+ aria-current=${this.active ? 'page' : nothing}
213
+ aria-disabled=${`${this.disabled}`}
214
+ ?aria-describedby=${this.__getDisabledReasonID()}
215
+ @click=${this.__dispatchClickWithThrottle}
216
+ @mousedown=${this.__handlePress}
217
+ @keydown=${this.__handlePress}
218
+ @keyup=${this.__handlePress}
219
+ >
220
+ ${this.__renderItemContent()}
221
+ </a>`;
222
+ }
223
+ }
@@ -0,0 +1,72 @@
1
+ @use '../../scss/mixin';
2
+
3
+ @include mixin.base-styles;
4
+
5
+ :host {
6
+ display: block;
7
+ height: 100%;
8
+ width: var(--nav-rail-width, 5rem); /* 80dp */
9
+ overflow: hidden;
10
+ }
11
+
12
+ .rail {
13
+ display: flex;
14
+ flex-direction: column;
15
+ align-items: center;
16
+ height: 100%;
17
+ width: 100%;
18
+ border-radius: inherit;
19
+ background-color: var(--nav-rail-container-color, var(--color-surface));
20
+ padding-block: var(--nav-rail-padding-block, 0.75rem); /* 12dp */
21
+ box-sizing: border-box;
22
+
23
+ .header {
24
+ display: flex;
25
+ flex-direction: column;
26
+ align-items: center;
27
+ width: 100%;
28
+ flex-shrink: 0;
29
+
30
+ &:empty {
31
+ display: none;
32
+ }
33
+ }
34
+
35
+ wc-divider {
36
+ width: calc(100% - 1rem);
37
+ margin-block: 0.5rem;
38
+ flex-shrink: 0;
39
+ }
40
+
41
+ .items {
42
+ display: flex;
43
+ flex-direction: column;
44
+ align-items: center;
45
+ width: 100%;
46
+ gap: 0.75rem; /* 12dp between items */
47
+ flex: 1;
48
+
49
+ ::slotted(wc-navigation-rail-item) {
50
+ width: 100%;
51
+ }
52
+ }
53
+
54
+ /* Alignment variants */
55
+ &.align-top {
56
+ .items {
57
+ justify-content: flex-start;
58
+ }
59
+ }
60
+
61
+ &.align-center {
62
+ .items {
63
+ justify-content: center;
64
+ }
65
+ }
66
+
67
+ &.align-bottom {
68
+ .items {
69
+ justify-content: flex-end;
70
+ }
71
+ }
72
+ }
@@ -0,0 +1,149 @@
1
+ import { html, LitElement, PropertyValues } from 'lit';
2
+ import { property } from 'lit/decorators.js';
3
+ import { classMap } from 'lit/directives/class-map.js';
4
+ import styles from './navigation-rail.scss';
5
+ import { NavigationRailItem } from './navigation-rail-item.js';
6
+
7
+ /**
8
+ * @label Navigation Rail
9
+ * @tag wc-navigation-rail
10
+ * @rawTag navigation-rail
11
+ *
12
+ * @summary A vertical side navigation for medium-sized screens, following Material Design 3 specs.
13
+ * @overview
14
+ * <p>Navigation rail provides access to primary destinations in an app using icons—with or without labels—on a vertical rail.</p>
15
+ * <p>Use navigation rail on medium-sized screens (tablets) with 3–7 destinations.</p>
16
+ *
17
+ * @cssprop --nav-rail-width - Width of the rail container. Defaults to 5rem (80dp).
18
+ * @cssprop --nav-rail-container-color - Background color of the rail. Defaults to surface color.
19
+ * @cssprop --nav-rail-indicator-color - Color of the active indicator. Defaults to secondary-container.
20
+ * @cssprop --nav-rail-indicator-shape - Shape (border-radius) of the active indicator. Defaults to full (pill).
21
+ * @cssprop --nav-rail-indicator-width - Width of the active indicator. Defaults to 3.5rem (56dp).
22
+ * @cssprop --nav-rail-indicator-height - Height of the active indicator. Defaults to 2rem (32dp).
23
+ * @cssprop --nav-rail-inactive-icon-color - Color of inactive icons. Defaults to on-surface-variant.
24
+ * @cssprop --nav-rail-active-icon-color - Color of active icons. Defaults to on-secondary-container.
25
+ * @cssprop --nav-rail-inactive-label-color - Color of inactive labels. Defaults to on-surface-variant.
26
+ * @cssprop --nav-rail-active-label-color - Color of active labels. Defaults to on-surface.
27
+ *
28
+ * @example
29
+ * ```html
30
+ * <wc-navigation-rail>
31
+ * <wc-navigation-rail-item active>
32
+ * <wc-icon slot="icon">home</wc-icon>
33
+ * Home
34
+ * </wc-navigation-rail-item>
35
+ * <wc-navigation-rail-item>
36
+ * <wc-icon slot="icon">search</wc-icon>
37
+ * Search
38
+ * </wc-navigation-rail-item>
39
+ * <wc-navigation-rail-item>
40
+ * <wc-icon slot="icon">settings</wc-icon>
41
+ * Settings
42
+ * </wc-navigation-rail-item>
43
+ * </wc-navigation-rail>
44
+ * ```
45
+ * @tags navigation
46
+ */
47
+ export class NavigationRail extends LitElement {
48
+ static styles = [styles];
49
+
50
+ static Item = NavigationRailItem;
51
+
52
+ /**
53
+ * Vertical alignment of items within the rail.
54
+ * - `"top"`: Items align to the top.
55
+ * - `"center"`: Items are centered (default).
56
+ * - `"bottom"`: Items align to the bottom.
57
+ */
58
+ @property({ reflect: true }) alignment: 'top' | 'center' | 'bottom' = 'center';
59
+
60
+ /**
61
+ * Display mode of the navigation rail.
62
+ * - `"expanded"`: shows labels.
63
+ * - `"collapsed"`: hides labels.
64
+ */
65
+ @property({ reflect: true }) mode: 'expanded' | 'collapsed' = 'expanded';
66
+
67
+ /**
68
+ * Whether to show a divider between the header and items sections.
69
+ */
70
+ @property({ type: Boolean, attribute: 'show-divider' }) showDivider = false;
71
+
72
+ connectedCallback() {
73
+ super.connectedCallback();
74
+ this.addEventListener('click', this._handleItemClick);
75
+ this.setAttribute('role', 'navigation');
76
+ this.setAttribute('aria-label', this.getAttribute('aria-label') ?? 'Main navigation');
77
+ }
78
+
79
+ disconnectedCallback() {
80
+ this.removeEventListener('click', this._handleItemClick);
81
+ super.disconnectedCallback();
82
+ }
83
+
84
+ protected override firstUpdated() {
85
+ this._syncItemMode();
86
+ }
87
+
88
+ protected override updated(changedProperties: PropertyValues<this>) {
89
+ if (changedProperties.has('mode')) {
90
+ this._syncItemMode();
91
+ }
92
+ }
93
+
94
+ private _handleItemClick = (event: Event) => {
95
+ const target = event.target as HTMLElement;
96
+ const item = target.closest('wc-navigation-rail-item') as NavigationRailItem | null;
97
+
98
+ if (!item || item.disabled) return;
99
+
100
+ // Deactivate all items and activate the clicked one
101
+ for (const railItem of this._getItems()) {
102
+ railItem.active = railItem === item;
103
+ }
104
+
105
+ this.dispatchEvent(
106
+ new CustomEvent('nav-change', {
107
+ detail: {
108
+ value: item.value,
109
+ item,
110
+ },
111
+ bubbles: true,
112
+ composed: true,
113
+ }),
114
+ );
115
+ };
116
+
117
+ private _getItems(): NavigationRailItem[] {
118
+ return Array.from(
119
+ this.querySelectorAll('wc-navigation-rail-item'),
120
+ ) as NavigationRailItem[];
121
+ }
122
+
123
+ private _syncItemMode = () => {
124
+ const isCollapsed = this.mode === 'collapsed';
125
+ for (const railItem of this._getItems()) {
126
+ railItem.collapsed = isCollapsed;
127
+ }
128
+ };
129
+
130
+ render() {
131
+ const cssClasses = {
132
+ rail: true,
133
+ [`align-${this.alignment}`]: true,
134
+ [`mode-${this.mode}`]: true,
135
+ };
136
+
137
+ return html`
138
+ <div class=${classMap(cssClasses)}>
139
+ <div class="header">
140
+ <slot name="header"></slot>
141
+ </div>
142
+ ${this.showDivider ? html`<wc-divider></wc-divider>` : ''}
143
+ <nav class="items" role="presentation">
144
+ <slot @slotchange=${this._syncItemMode}></slot>
145
+ </nav>
146
+ </div>
147
+ `;
148
+ }
149
+ }
@@ -193,11 +193,12 @@ export class Notification extends LitElement {
193
193
  variant="text"
194
194
  size="sm"
195
195
  aria-label="Close notification"
196
- name="close"
197
196
  @click=${() => {
198
197
  this.hideAndEmitDismiss('dismiss');
199
198
  }}
200
- ></wc-icon-button>
199
+ >
200
+ <wc-icon name="close"></wc-icon>
201
+ </wc-icon-button>
201
202
  </div>`
202
203
  : nothing}
203
204
  </div>
@@ -170,11 +170,12 @@ export class NumberField extends BaseInput {
170
170
  ${this.stepper && !this.disabled
171
171
  ? html`<wc-icon-button
172
172
  class="stepper"
173
- name="remove"
174
173
  variant="text"
175
174
  slot="field-start"
176
175
  @click=${this.stepDown}
177
- ></wc-icon-button>`
176
+ >
177
+ <wc-icon name="remove"></wc-icon>
178
+ </wc-icon-button>`
178
179
  : nothing}
179
180
 
180
181
  <slot name="start" slot="field-start"></slot>
@@ -206,10 +207,11 @@ export class NumberField extends BaseInput {
206
207
  ? html`<wc-icon-button
207
208
  class="stepper"
208
209
  variant="text"
209
- name="add"
210
210
  slot="field-end"
211
211
  @click=${this.stepUp}
212
- ></wc-icon-button>`
212
+ >
213
+ <wc-icon name="add"></wc-icon>
214
+ </wc-icon-button>`
213
215
  : nothing}
214
216
  </wc-field>
215
217
  `;
@@ -166,21 +166,23 @@ export class Pagination extends LitElement {
166
166
  color="secondary"
167
167
  variant="text"
168
168
  size="sm"
169
- name="keyboard_arrow_left"
170
169
  title="Previous page"
171
170
  ?disabled=${isFirstPage}
172
171
  @click=${this.handlePreviousPage}
173
- ></wc-icon-button>
172
+ >
173
+ <wc-icon name="keyboard_arrow_left"></wc-icon>
174
+ </wc-icon-button>
174
175
  <wc-icon-button
175
176
  class="nav-button"
176
177
  color="secondary"
177
178
  variant="text"
178
179
  size="sm"
179
- name="keyboard_arrow_right"
180
180
  title="Next page"
181
181
  ?disabled=${isLastPage}
182
182
  @click=${this.handleNextPage}
183
- ></wc-icon-button>
183
+ >
184
+ <wc-icon name="keyboard_arrow_right"></wc-icon>
185
+ </wc-icon-button>
184
186
  </div>
185
187
  </div>
186
188
  `;
@@ -15,6 +15,7 @@ import { Fab } from './fab/fab.js';
15
15
  import { SegmentedButton } from './segmented-button/segmented-button.js';
16
16
  import { SegmentedButtonGroup } from './segmented-button/segmented-button-group.js';
17
17
  import { Input } from './input/input.js';
18
+ import { UrlField } from './url-field/url-field.js';
18
19
  import { Field } from './field/field.js';
19
20
  import { NumberField } from './number-field/number-field.js';
20
21
  import { DatePicker } from './date-picker/date-picker.js';
@@ -54,7 +55,9 @@ import { TabPanel } from './tabs/tab-panel.js';
54
55
  import { Slider } from './slider/slider.js';
55
56
  import { Table } from './table/table.js';
56
57
  import { Pagination } from './pagination/pagination.js';
57
- import { TreeView } from './tree-view/tree-view.js';
58
+ import { SidebarMenu } from './sidebar-menu/sidebar-menu.js';
59
+ import { SidebarMenuItem } from './sidebar-menu/sidebar-menu-item.js';
60
+ import { SidebarSubMenu } from './sidebar-menu/sidebar-sub-menu.js';
58
61
  import { Card } from './card/card.js';
59
62
  import { CardContent } from './card/card-content.js';
60
63
  import { Banner } from './banner/banner.js';
@@ -66,6 +69,8 @@ import { Select } from './select/select.js';
66
69
  import { SelectOptionElement } from './select/option.js';
67
70
  import { Search } from './search/search.js';
68
71
  import { Toolbar } from './toolbar/toolbar.js';
72
+ import { NavigationRail } from './navigation-rail/navigation-rail.js';
73
+ import { NavigationRailItem } from './navigation-rail/navigation-rail-item.js';
69
74
 
70
75
  const distDirectory = `${import.meta.url}/..`;
71
76
  await loadCSS(`${distDirectory}/assets/styles.css`);
@@ -190,6 +195,9 @@ const loaderConfig: LoaderConfig = {
190
195
  'wc-input': {
191
196
  CustomElementClass: Input,
192
197
  },
198
+ 'wc-url-field': {
199
+ CustomElementClass: UrlField,
200
+ },
193
201
  'wc-number-field': {
194
202
  CustomElementClass: NumberField,
195
203
  },
@@ -259,11 +267,14 @@ const loaderConfig: LoaderConfig = {
259
267
  'wc-pagination': {
260
268
  CustomElementClass: Pagination,
261
269
  },
262
- 'wc-tree-view': {
263
- CustomElementClass: TreeView,
270
+ 'wc-sidebar-menu': {
271
+ CustomElementClass: SidebarMenu,
272
+ },
273
+ 'wc-sidebar-menu-item': {
274
+ CustomElementClass: SidebarMenuItem,
264
275
  },
265
- 'wc-tree-node': {
266
- CustomElementClass: TreeView.Node,
276
+ 'wc-sidebar-sub-menu': {
277
+ CustomElementClass: SidebarSubMenu,
267
278
  },
268
279
  'wc-snackbar': {
269
280
  CustomElementClass: Snackbar,
@@ -286,6 +297,12 @@ const loaderConfig: LoaderConfig = {
286
297
  'wc-toolbar': {
287
298
  CustomElementClass: Toolbar,
288
299
  },
300
+ 'wc-navigation-rail': {
301
+ CustomElementClass: NavigationRail,
302
+ },
303
+ 'wc-navigation-rail-item': {
304
+ CustomElementClass: NavigationRailItem,
305
+ },
289
306
  'wc-chart-doughnut': {
290
307
  importPath: `${distDirectory}/chart-doughnut.js`,
291
308
  },
@@ -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,3 @@
1
+ export { SidebarMenuItem } from './sidebar-menu-item.js';
2
+ export { SidebarSubMenu } from './sidebar-sub-menu.js';
3
+ export { SidebarMenu } from './sidebar-menu.js';