@rcarls/rc-menu-button 0.5.0 → 0.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/CHANGELOG.md +44 -0
- package/README.md +58 -52
- package/dist/custom-elements.json +72 -5
- package/dist/{rc-menu-button-BuLMtVMw.js → rc-menu-button-DPs2AT2d.js} +159 -55
- package/dist/rc-menu-button-DPs2AT2d.js.map +1 -0
- package/dist/rc-menu-button-define.js +1 -1
- package/dist/rc-menu-button.js +1 -1
- package/dist/types/packages/rc-menu-button/src/index.d.ts +1 -1
- package/dist/types/packages/rc-menu-button/src/rc-menu-button.d.ts +27 -2
- package/package.json +4 -4
- package/dist/rc-menu-button-BuLMtVMw.js.map +0 -1
- package/dist/types/packages/rc-menu-button/src/rc-menu-button.test.d.ts +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,49 @@
|
|
|
1
1
|
# @rcarls/rc-menu-button
|
|
2
2
|
|
|
3
|
+
## 0.6.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 30eb232: Add icon-only activation-area sizing and Material icon-button variants. Align menu
|
|
8
|
+
selection and submenu affordances, and keep anchored popups within the viewport
|
|
9
|
+
across native and fallback positioning.
|
|
10
|
+
- 30eb232: Add `--rc-menu-button-touch-target-overlap-inline-start` and
|
|
11
|
+
`-inline-end` for an `icon-only` trigger, zero by default. A theme or
|
|
12
|
+
consumer sets one to let the accessible touch-target inflation on that
|
|
13
|
+
side overlap into whatever sits just outside the host, such as a toolbar's
|
|
14
|
+
own edge padding, instead of also reserving layout space there: the
|
|
15
|
+
visible trigger shifts flush with that edge while the invisible hit
|
|
16
|
+
region keeps its full accessible size. Mirrors `@rcarls/rc-button`'s own
|
|
17
|
+
touch-target overlap tokens.
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- 7382c71: Add a priority-aware action toolbar that moves original controls into an
|
|
22
|
+
overflow menu. Which actions are promoted is a purely declarative computation
|
|
23
|
+
from `max-shown` and each action's `data-priority`/authored `slot`, with no
|
|
24
|
+
runtime measurement of the toolbar's or its children's rendered size: a
|
|
25
|
+
consumer whose promoted count needs to react to available space owns that
|
|
26
|
+
decision and writes the resulting `max-shown` value down. Include controlled
|
|
27
|
+
and uncontrolled open state, keyboard navigation, light dismissal, and a
|
|
28
|
+
non-Popover fallback.
|
|
29
|
+
|
|
30
|
+
Fix `--rc-adaptive-menu-touch-target-overlap-inline-start`/`-end`: the host's
|
|
31
|
+
own `max-inline-size: 100%` self-referenced a shrink-to-fit ancestor's
|
|
32
|
+
already-margin-reduced auto size (an app bar's own trailing group, for
|
|
33
|
+
example), quietly clamping the host back down and canceling the overlap out
|
|
34
|
+
from under it. The cap now grows by the overlap amount so it only ever bounds
|
|
35
|
+
the host's real content.
|
|
36
|
+
|
|
37
|
+
- 57370e4: Align component metadata, aggregate framework typings, development-time native-child
|
|
38
|
+
validation, controlled menu state, package declarations, and public documentation before the
|
|
39
|
+
next release.
|
|
40
|
+
- Updated dependencies [7382c71]
|
|
41
|
+
- Updated dependencies [6683eb9]
|
|
42
|
+
- Updated dependencies [ee7ba6c]
|
|
43
|
+
- Updated dependencies [30eb232]
|
|
44
|
+
- @rcarls/rc-menu@0.6.0
|
|
45
|
+
- @rcarls/rc-common@0.6.0
|
|
46
|
+
|
|
3
47
|
## 0.5.0
|
|
4
48
|
|
|
5
49
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -18,8 +18,8 @@ npm install @rcarls/rc-menu-button
|
|
|
18
18
|
## Import
|
|
19
19
|
|
|
20
20
|
```js
|
|
21
|
-
import '@rcarls/rc-menu-button/define';
|
|
22
|
-
import { RCMenuButton } from '@rcarls/rc-menu-button';
|
|
21
|
+
import '@rcarls/rc-menu-button/define'; // side-effect: registers <rc-menu-button>
|
|
22
|
+
import { RCMenuButton } from '@rcarls/rc-menu-button'; // named class export
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
`rc-menu-button` depends on `rc-menu`. Ensure both are installed.
|
|
@@ -53,56 +53,62 @@ item.
|
|
|
53
53
|
|
|
54
54
|
### Properties / attributes
|
|
55
55
|
|
|
56
|
-
| Property
|
|
57
|
-
|
|
58
|
-
| `open`
|
|
59
|
-
| `defaultOpen` | `default-open` | `boolean`
|
|
60
|
-
| `orientation` | `orientation`
|
|
61
|
-
| `placement`
|
|
56
|
+
| Property | Attribute | Type | Default | Description |
|
|
57
|
+
| ------------- | -------------- | ----------------------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
58
|
+
| `open` | `open` | `boolean` | `false` | Whether the menu popup is visible. Reflects to attribute. Controlled mode: host writes silently. |
|
|
59
|
+
| `defaultOpen` | `default-open` | `boolean` | `false` | Initial open state for uncontrolled mode. Ignored after the first controlled write to `open`. |
|
|
60
|
+
| `orientation` | `orientation` | `'horizontal' \| 'vertical' \| undefined` | `undefined` | Arrow-key axis for opening the menu. Vertical triggers span their allocated menu-row width. When unset, inherited from a parent `rc-menubar` or `[role="menubar"]` element. Falls back to `'horizontal'`. |
|
|
61
|
+
| `placement` | `placement` | `AnchorPlacement` | `'bottom-start'` | Preferred placement of the popup relative to the trigger. Switches to `'right-start'` under vertical orientation unless explicitly overridden. |
|
|
62
|
+
| | `icon-only` | boolean attribute | absent | Hints that the trigger has no visible label so themes can apply icon-button sizing and activation-area geometry. |
|
|
62
63
|
|
|
63
64
|
### CSS custom properties
|
|
64
65
|
|
|
65
|
-
| Property
|
|
66
|
-
|
|
67
|
-
| `--rc-menu-button-trigger-block-size`
|
|
68
|
-
| `--rc-menu-button-trigger-padding-block`
|
|
69
|
-
| `--rc-menu-button-trigger-padding-inline`
|
|
70
|
-
| `--rc-menu-button-trigger-gap`
|
|
71
|
-
| `--rc-menu-button-trigger-border`
|
|
72
|
-
| `--rc-menu-button-trigger-radius`
|
|
73
|
-
| `--rc-menu-button-trigger-background`
|
|
74
|
-
| `--rc-menu-button-trigger-color`
|
|
75
|
-
| `--rc-menu-button-trigger-transition`
|
|
76
|
-
| `--rc-menu-button-trigger-hover-background`
|
|
77
|
-
| `--rc-menu-button-trigger-hover-color`
|
|
78
|
-
| `--rc-menu-button-trigger-hover-border-color`
|
|
79
|
-
| `--rc-menu-button-trigger-open-background`
|
|
80
|
-
| `--rc-menu-button-trigger-open-color`
|
|
81
|
-
| `--rc-menu-button-trigger-open-border-color`
|
|
82
|
-
| `--rc-menu-button-indicator-size`
|
|
83
|
-
| `--rc-menu-button-indicator-color`
|
|
84
|
-
| `--rc-menu-button-indicator-inset`
|
|
66
|
+
| Property | Default | Description |
|
|
67
|
+
| ---------------------------------------------------- | ------------------------------------------------ | --------------------------------------------------------------- |
|
|
68
|
+
| `--rc-menu-button-trigger-block-size` | `var(--rc-control-block-size)` | Minimum block size of the trigger |
|
|
69
|
+
| `--rc-menu-button-trigger-padding-block` | `var(--rc-control-padding-block)` | Trigger block-axis padding |
|
|
70
|
+
| `--rc-menu-button-trigger-padding-inline` | `var(--rc-control-padding-inline)` | Trigger inline-axis padding |
|
|
71
|
+
| `--rc-menu-button-trigger-gap` | `var(--rc-item-gap)` | Gap between flex children inside the trigger |
|
|
72
|
+
| `--rc-menu-button-trigger-border` | `var(--rc-border)` | Trigger border |
|
|
73
|
+
| `--rc-menu-button-trigger-radius` | `var(--rc-control-radius)` | Trigger border radius |
|
|
74
|
+
| `--rc-menu-button-trigger-background` | `var(--rc-button-bg)` | Trigger background |
|
|
75
|
+
| `--rc-menu-button-trigger-color` | `var(--rc-button-text)` | Trigger text color |
|
|
76
|
+
| `--rc-menu-button-trigger-transition` | `none` | Trigger state transition |
|
|
77
|
+
| `--rc-menu-button-trigger-hover-background` | `color-mix(in srgb, Highlight 8%, transparent)` | Trigger hover background |
|
|
78
|
+
| `--rc-menu-button-trigger-hover-color` | `inherit` | Trigger hover text color |
|
|
79
|
+
| `--rc-menu-button-trigger-hover-border-color` | `currentColor` | Trigger hover border color |
|
|
80
|
+
| `--rc-menu-button-trigger-open-background` | `color-mix(in srgb, Highlight 12%, transparent)` | Trigger background while the menu is open |
|
|
81
|
+
| `--rc-menu-button-trigger-open-color` | `inherit` | Trigger text color while the menu is open |
|
|
82
|
+
| `--rc-menu-button-trigger-open-border-color` | `currentColor` | Trigger border color while the menu is open |
|
|
83
|
+
| `--rc-menu-button-indicator-size` | `1em` | Inline and block size reserved for the optional indicator |
|
|
84
|
+
| `--rc-menu-button-indicator-color` | `currentColor` | Color of the optional indicator |
|
|
85
|
+
| `--rc-menu-button-indicator-inset` | Trigger inline padding | Indicator distance from the trigger's inline end |
|
|
86
|
+
| `--rc-menu-button-icon-size` | Trigger block size | Visible inline size of an `icon-only` trigger |
|
|
87
|
+
| `--rc-menu-button-touch-target-block-size` | `3rem` | Minimum block size of an `icon-only` trigger's activation area |
|
|
88
|
+
| `--rc-menu-button-touch-target-inline-size` | Activation-area block size | Minimum inline size of an `icon-only` trigger's activation area |
|
|
89
|
+
| `--rc-menu-button-touch-target-overlap-inline-start` | `0px` | Allows touch-target inflation to overlap the leading neighbor |
|
|
90
|
+
| `--rc-menu-button-touch-target-overlap-inline-end` | `0px` | Allows touch-target inflation to overlap the trailing neighbor |
|
|
85
91
|
|
|
86
92
|
### CSS parts
|
|
87
93
|
|
|
88
|
-
| Part
|
|
89
|
-
|
|
90
|
-
| `root`
|
|
94
|
+
| Part | Element | Description |
|
|
95
|
+
| ------- | ----------- | ------------------------------------------------------- |
|
|
96
|
+
| `root` | Outer `div` | Root wrapper |
|
|
91
97
|
| `popup` | Popup `div` | Container that shows/hides around the slotted `rc-menu` |
|
|
92
98
|
|
|
93
99
|
### Slots
|
|
94
100
|
|
|
95
|
-
| Slot
|
|
96
|
-
|
|
97
|
-
| `trigger`
|
|
101
|
+
| Slot | Description |
|
|
102
|
+
| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
103
|
+
| `trigger` | The button (or other interactive element) that toggles the menu. Receives `aria-haspopup` and `aria-expanded` automatically. |
|
|
98
104
|
| `indicator` | Optional author-supplied decorative submenu indicator. Rendered at the trigger's inline end with pointer events passed through to the trigger. |
|
|
99
|
-
|
|
|
105
|
+
| _(default)_ | The `rc-menu` to show as the popup. |
|
|
100
106
|
|
|
101
107
|
### Events
|
|
102
108
|
|
|
103
|
-
| Event
|
|
104
|
-
|
|
105
|
-
| `rc-menu-button-toggle` | Yes (composed) | No
|
|
109
|
+
| Event | Bubbles | Cancelable | Detail | When |
|
|
110
|
+
| ----------------------- | -------------- | ---------- | ------------------- | -------------------- |
|
|
111
|
+
| `rc-menu-button-toggle` | Yes (composed) | No | `{ open: boolean }` | Menu opens or closes |
|
|
106
112
|
|
|
107
113
|
### Public methods
|
|
108
114
|
|
|
@@ -124,25 +130,25 @@ toggleMenu(): void
|
|
|
124
130
|
Keyboard handling depends on the resolved `orientation` (horizontal by
|
|
125
131
|
default, or inherited from a parent menubar).
|
|
126
132
|
|
|
127
|
-
| Key
|
|
128
|
-
|
|
129
|
-
| `ArrowDown`
|
|
130
|
-
| `ArrowUp`
|
|
131
|
-
| `ArrowRight`
|
|
132
|
-
| `ArrowLeft`
|
|
133
|
-
| `Enter` / `Space` | Menu closed
|
|
134
|
-
| `Enter` / `Space` | Menu open
|
|
135
|
-
| `Escape`
|
|
133
|
+
| Key | Condition | Action |
|
|
134
|
+
| ----------------- | ---------------------- | ----------------------------------- |
|
|
135
|
+
| `ArrowDown` | Horizontal orientation | Open menu, focus first item |
|
|
136
|
+
| `ArrowUp` | Horizontal orientation | Open menu, focus last item |
|
|
137
|
+
| `ArrowRight` | Vertical orientation | Open menu, focus first item |
|
|
138
|
+
| `ArrowLeft` | Vertical orientation | Open menu, focus last item |
|
|
139
|
+
| `Enter` / `Space` | Menu closed | Open menu |
|
|
140
|
+
| `Enter` / `Space` | Menu open | Activate focused item, close menu |
|
|
141
|
+
| `Escape` | Menu open | Close menu, return focus to trigger |
|
|
136
142
|
|
|
137
143
|
---
|
|
138
144
|
|
|
139
145
|
## ARIA
|
|
140
146
|
|
|
141
|
-
| Attribute
|
|
142
|
-
|
|
143
|
-
| `aria-haspopup="menu"` | Trigger element | Set automatically on slot change
|
|
144
|
-
| `aria-expanded`
|
|
145
|
-
| `open`
|
|
147
|
+
| Attribute | Where | Value |
|
|
148
|
+
| ---------------------- | --------------- | ---------------------------------------------- |
|
|
149
|
+
| `aria-haspopup="menu"` | Trigger element | Set automatically on slot change |
|
|
150
|
+
| `aria-expanded` | Trigger element | `"true"` / `"false"`, kept in sync with `open` |
|
|
151
|
+
| `open` | Host element | Reflected boolean attribute when menu is open |
|
|
146
152
|
|
|
147
153
|
---
|
|
148
154
|
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"name": "*",
|
|
36
36
|
"declaration": {
|
|
37
37
|
"name": "*",
|
|
38
|
-
"module": "src/rc-menu-button"
|
|
38
|
+
"module": "src/rc-menu-button.js"
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
]
|
|
@@ -137,6 +137,29 @@
|
|
|
137
137
|
"description": "Indicator distance from the trigger's inline end",
|
|
138
138
|
"name": "--rc-menu-button-indicator-inset",
|
|
139
139
|
"default": "var(--rc-menu-button-trigger-padding-inline)"
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"description": "Inline size of an `icon-only` trigger's visible box. Square by default (equal to `--rc-menu-button-trigger-block-size`); set narrower or wider to change only the trigger's width, independent of its height.",
|
|
143
|
+
"name": "--rc-menu-button-icon-size"
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"description": "Minimum accessible touch target block size for an `icon-only` trigger. A floor, not a fixed size: has no effect once `--rc-menu-button-trigger-block-size` already meets or exceeds it. Grows the shadow-DOM trigger wrapper (reserving layout space) and the light-DOM hit-slop (the actual larger clickable region) together; the visible trigger itself stays at its own size, centered.",
|
|
147
|
+
"name": "--rc-menu-button-touch-target-block-size",
|
|
148
|
+
"default": "3rem"
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"description": "Minimum accessible touch target inline size for an `icon-only` trigger. Defers to `--rc-menu-button-touch-target-block-size` when unset.",
|
|
152
|
+
"name": "--rc-menu-button-touch-target-inline-size"
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"description": "Zero by default. A theme or consumer sets this on an `icon-only` trigger that sits at a real leading edge (no neighbor on that side) to let its touch-target inflation overlap into whatever sits just outside the host, such as a container's own edge padding, instead of also reserving layout space there.",
|
|
156
|
+
"name": "--rc-menu-button-touch-target-overlap-inline-start",
|
|
157
|
+
"default": "0px"
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"description": "The trailing-edge counterpart to `--rc-menu-button-touch-target-overlap-inline-start`.",
|
|
161
|
+
"name": "--rc-menu-button-touch-target-overlap-inline-end",
|
|
162
|
+
"default": "0px"
|
|
140
163
|
}
|
|
141
164
|
],
|
|
142
165
|
"cssParts": [
|
|
@@ -174,6 +197,33 @@
|
|
|
174
197
|
"default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true, }",
|
|
175
198
|
"description": "Enables delegatesFocus so the browser routes focus() on the host element\nto the slotted trigger button."
|
|
176
199
|
},
|
|
200
|
+
{
|
|
201
|
+
"kind": "field",
|
|
202
|
+
"name": "_styledRoots",
|
|
203
|
+
"privacy": "protected",
|
|
204
|
+
"static": true,
|
|
205
|
+
"readonly": true,
|
|
206
|
+
"default": "new Set<Document | ShadowRoot>()"
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
"kind": "method",
|
|
210
|
+
"name": "_ensureBaseStyles",
|
|
211
|
+
"privacy": "protected",
|
|
212
|
+
"static": true,
|
|
213
|
+
"return": {
|
|
214
|
+
"type": {
|
|
215
|
+
"text": "void"
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
"parameters": [
|
|
219
|
+
{
|
|
220
|
+
"name": "root",
|
|
221
|
+
"type": {
|
|
222
|
+
"text": "Document | ShadowRoot"
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
]
|
|
226
|
+
},
|
|
177
227
|
{
|
|
178
228
|
"kind": "field",
|
|
179
229
|
"name": "_defaultOpen",
|
|
@@ -187,10 +237,17 @@
|
|
|
187
237
|
"kind": "field",
|
|
188
238
|
"name": "_open",
|
|
189
239
|
"type": {
|
|
190
|
-
"text": "boolean"
|
|
240
|
+
"text": "boolean | undefined"
|
|
191
241
|
},
|
|
192
|
-
"privacy": "private"
|
|
193
|
-
|
|
242
|
+
"privacy": "private"
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"kind": "field",
|
|
246
|
+
"name": "_uncontrolledOpen",
|
|
247
|
+
"type": {
|
|
248
|
+
"text": "boolean | undefined"
|
|
249
|
+
},
|
|
250
|
+
"privacy": "private"
|
|
194
251
|
},
|
|
195
252
|
{
|
|
196
253
|
"kind": "field",
|
|
@@ -355,7 +412,13 @@
|
|
|
355
412
|
"kind": "method",
|
|
356
413
|
"name": "_dispatchToggle",
|
|
357
414
|
"privacy": "protected",
|
|
358
|
-
"
|
|
415
|
+
"parameters": [
|
|
416
|
+
{
|
|
417
|
+
"name": "open",
|
|
418
|
+
"default": "this.open"
|
|
419
|
+
}
|
|
420
|
+
],
|
|
421
|
+
"description": "Dispatches the `rc-menu-button-toggle` bubbling composed event with the requested open state."
|
|
359
422
|
},
|
|
360
423
|
{
|
|
361
424
|
"kind": "method",
|
|
@@ -543,6 +606,10 @@
|
|
|
543
606
|
},
|
|
544
607
|
"default": "'bottom-start'",
|
|
545
608
|
"fieldName": "placement"
|
|
609
|
+
},
|
|
610
|
+
{
|
|
611
|
+
"description": "Hints that the slotted trigger has no visible label, so themes can size it and its touch target as an icon button (see `--rc-menu-button-icon-size` and `--rc-menu-button-touch-target-*` above). Purely a styling hook; RCMenuButton does not read or derive it — set it whenever the trigger is rendered icon-only.",
|
|
612
|
+
"name": "icon-only"
|
|
546
613
|
}
|
|
547
614
|
],
|
|
548
615
|
"superclass": {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { css as
|
|
2
|
-
import { property as l, query as
|
|
1
|
+
import { css as p, LitElement as g, html as b } from "lit";
|
|
2
|
+
import { property as l, query as d, state as h } from "lit/decorators.js";
|
|
3
3
|
import { AnchorController as m, keyNavigation as v, keyInteraction as f } from "@rcarls/rc-common";
|
|
4
|
-
const
|
|
4
|
+
const y = p`
|
|
5
5
|
:host {
|
|
6
6
|
display: inline-block;
|
|
7
7
|
}
|
|
@@ -16,6 +16,7 @@ const _ = h`
|
|
|
16
16
|
|
|
17
17
|
:host([orientation='vertical']) #root {
|
|
18
18
|
display: block;
|
|
19
|
+
inline-size: 100%;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
#trigger-wrap {
|
|
@@ -25,10 +26,73 @@ const _ = h`
|
|
|
25
26
|
|
|
26
27
|
:host([orientation='vertical']) #trigger-wrap {
|
|
27
28
|
display: block;
|
|
29
|
+
inline-size: 100%;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/*
|
|
33
|
+
* Icon-only triggers (e.g. a toolbar's overflow button) can render
|
|
34
|
+
* visually smaller than the accessible 48dp touch-target minimum,
|
|
35
|
+
* especially at a narrow width. This is a floor, not a fixed size: a
|
|
36
|
+
* trigger already at or above it (the default width, or a labeled
|
|
37
|
+
* trigger) is unaffected. #trigger-wrap reserves the layout space and
|
|
38
|
+
* centers the (possibly smaller) slotted trigger within it; the actual
|
|
39
|
+
* larger hit region comes from the light-DOM hit-slop pseudo-element in
|
|
40
|
+
* rc-menu-button.ts. Mirrors rc-button's own touch-target affordance.
|
|
41
|
+
*
|
|
42
|
+
* Scoped to [icon-only] rather than applied unconditionally: switching
|
|
43
|
+
* #trigger-wrap to a flex/grid container would blockify the slotted
|
|
44
|
+
* trigger's own inline-flex display (its getComputedStyle().display
|
|
45
|
+
* becomes "flex", per the CSS Display spec's flex-item blockification —
|
|
46
|
+
* harmless for layout, since a flex item is sized by its container's
|
|
47
|
+
* flex algorithm regardless of its own inline/block outer type, but an
|
|
48
|
+
* observable change other callers shouldn't have to account for).
|
|
49
|
+
*/
|
|
50
|
+
:host([icon-only]) #trigger-wrap {
|
|
51
|
+
display: inline-flex;
|
|
52
|
+
align-items: center;
|
|
53
|
+
justify-content: center;
|
|
54
|
+
min-block-size: var(--rc-menu-button-touch-target-block-size, 3rem);
|
|
55
|
+
min-inline-size: var(
|
|
56
|
+
--rc-menu-button-touch-target-inline-size,
|
|
57
|
+
var(--rc-menu-button-touch-target-block-size, 3rem)
|
|
58
|
+
);
|
|
59
|
+
/*
|
|
60
|
+
* Zero by default. A theme or consumer sets one of these on a trigger
|
|
61
|
+
* that sits at a real edge (no neighbor on that side) to let the
|
|
62
|
+
* touch-target inflation above overlap into whatever sits just outside
|
|
63
|
+
* the host instead of also reserving layout space there. Mirrors
|
|
64
|
+
* rc-button's own --rc-button-touch-target-overlap-inline-* tokens.
|
|
65
|
+
*/
|
|
66
|
+
margin-inline-start: calc(-1 * var(--rc-menu-button-touch-target-overlap-inline-start, 0px));
|
|
67
|
+
margin-inline-end: calc(-1 * var(--rc-menu-button-touch-target-overlap-inline-end, 0px));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
:host([icon-only][orientation='vertical']) #trigger-wrap {
|
|
71
|
+
display: flex;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/*
|
|
75
|
+
* Icon-only trigger width: square by default (matches its own block
|
|
76
|
+
* size), or a distinct value for a narrower/wider variant. Padding is
|
|
77
|
+
* cleared since an icon-only trigger centers its (typically single) icon
|
|
78
|
+
* child via the flex alignment above rather than via inline padding.
|
|
79
|
+
*/
|
|
80
|
+
:host([icon-only]) slot[name='trigger']::slotted(button),
|
|
81
|
+
:host([icon-only]) slot[name='trigger']::slotted([role='button']) {
|
|
82
|
+
inline-size: var(
|
|
83
|
+
--rc-menu-button-icon-size,
|
|
84
|
+
var(--rc-menu-button-trigger-block-size, var(--rc-control-block-size, 2.25em))
|
|
85
|
+
);
|
|
86
|
+
min-inline-size: var(
|
|
87
|
+
--rc-menu-button-icon-size,
|
|
88
|
+
var(--rc-menu-button-trigger-block-size, var(--rc-control-block-size, 2.25em))
|
|
89
|
+
);
|
|
90
|
+
padding-inline: 0;
|
|
28
91
|
}
|
|
29
92
|
|
|
30
93
|
slot[name='trigger']::slotted(button),
|
|
31
94
|
slot[name='trigger']::slotted([role='button']) {
|
|
95
|
+
position: relative;
|
|
32
96
|
display: inline-flex;
|
|
33
97
|
align-items: center;
|
|
34
98
|
justify-content: center;
|
|
@@ -118,14 +182,48 @@ const _ = h`
|
|
|
118
182
|
color: inherit;
|
|
119
183
|
}
|
|
120
184
|
`;
|
|
121
|
-
var
|
|
122
|
-
for (var
|
|
123
|
-
(c = u[s]) && (
|
|
124
|
-
return
|
|
185
|
+
var _ = Object.defineProperty, k = Object.getOwnPropertyDescriptor, a = (u, t, e, n) => {
|
|
186
|
+
for (var i = n > 1 ? void 0 : n ? k(t, e) : t, s = u.length - 1, c; s >= 0; s--)
|
|
187
|
+
(c = u[s]) && (i = (n ? c(t, e, i) : c(i)) || i);
|
|
188
|
+
return n && i && _(t, e, i), i;
|
|
125
189
|
};
|
|
126
|
-
const
|
|
190
|
+
const x = `
|
|
191
|
+
@layer rc-base {
|
|
192
|
+
/*
|
|
193
|
+
* Expands an icon-only trigger's clickable region beyond its visible box
|
|
194
|
+
* up to the accessible touch-target minimum, the same way rc-button and
|
|
195
|
+
* rc-chip do: an absolutely-positioned, invisible pseudo-element on the
|
|
196
|
+
* actual slotted trigger element (not the host) extends the hit area
|
|
197
|
+
* symmetrically. The trigger already has position: relative from the
|
|
198
|
+
* shadow-scoped ::slotted(button) rule. max(100%, size) keeps this a
|
|
199
|
+
* no-op once the visible trigger already meets or exceeds the touch
|
|
200
|
+
* target, rather than shrinking it.
|
|
201
|
+
*/
|
|
202
|
+
rc-menu-button[icon-only] > [slot='trigger']::before {
|
|
203
|
+
content: '';
|
|
204
|
+
position: absolute;
|
|
205
|
+
inset-block: calc(
|
|
206
|
+
(
|
|
207
|
+
var(--rc-menu-button-touch-target-block-size, 3rem) -
|
|
208
|
+
max(100%, var(--rc-menu-button-trigger-block-size, 0px))
|
|
209
|
+
) / -2
|
|
210
|
+
);
|
|
211
|
+
inset-inline: calc(
|
|
212
|
+
(
|
|
213
|
+
var(
|
|
214
|
+
--rc-menu-button-touch-target-inline-size,
|
|
215
|
+
var(--rc-menu-button-touch-target-block-size, 3rem)
|
|
216
|
+
) -
|
|
217
|
+
max(100%, var(--rc-menu-button-icon-size, var(--rc-menu-button-trigger-block-size, 0px)))
|
|
218
|
+
) / -2
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
`;
|
|
223
|
+
var r;
|
|
224
|
+
const o = (r = class extends g {
|
|
127
225
|
constructor() {
|
|
128
|
-
super(...arguments), this._defaultOpen = !1, this.
|
|
226
|
+
super(...arguments), this._defaultOpen = !1, this._openInitialized = !1, this.placement = "bottom-start", this._anchorCtrl = new m(this, {
|
|
129
227
|
anchor: () => this._$root ?? null,
|
|
130
228
|
floating: () => this._$popup ?? null,
|
|
131
229
|
shadowHost: () => this,
|
|
@@ -146,13 +244,20 @@ const a = class a extends d {
|
|
|
146
244
|
}
|
|
147
245
|
};
|
|
148
246
|
}
|
|
247
|
+
static _ensureBaseStyles(t) {
|
|
248
|
+
if (r._styledRoots.has(t))
|
|
249
|
+
return;
|
|
250
|
+
r._styledRoots.add(t);
|
|
251
|
+
const e = document.createElement("style");
|
|
252
|
+
e.setAttribute("data-rc-light-dom-base", "rc-menu-button"), e.textContent = x, t instanceof Document ? t.head.append(e) : t.append(e);
|
|
253
|
+
}
|
|
149
254
|
get open() {
|
|
150
|
-
return this._open;
|
|
255
|
+
return this._open ?? this._uncontrolledOpen ?? this._defaultOpen;
|
|
151
256
|
}
|
|
152
257
|
/** Applies open state in controlled mode without dispatching an event. */
|
|
153
258
|
set open(t) {
|
|
154
|
-
const e = this.
|
|
155
|
-
|
|
259
|
+
const e = this.open;
|
|
260
|
+
this._open = t, this._openInitialized = !0, this.requestUpdate("open", e), this._syncTriggerAria();
|
|
156
261
|
}
|
|
157
262
|
get defaultOpen() {
|
|
158
263
|
return this._defaultOpen;
|
|
@@ -160,7 +265,7 @@ const a = class a extends d {
|
|
|
160
265
|
/** Applies the uncontrolled default before any controlled write occurs. */
|
|
161
266
|
set defaultOpen(t) {
|
|
162
267
|
const e = this._defaultOpen;
|
|
163
|
-
this._defaultOpen = t,
|
|
268
|
+
this._defaultOpen = t, !this._openInitialized && this._open === void 0 && this._uncontrolledOpen === void 0 && this.requestUpdate("open", e), this.requestUpdate("defaultOpen", e);
|
|
164
269
|
}
|
|
165
270
|
/**
|
|
166
271
|
* Popup placement adjusted for orientation.
|
|
@@ -190,7 +295,7 @@ const a = class a extends d {
|
|
|
190
295
|
}
|
|
191
296
|
/** Installs the tabindex mutation observer and the document-level click listener. */
|
|
192
297
|
connectedCallback() {
|
|
193
|
-
super.connectedCallback(), this._tabObserver = new MutationObserver(() => this._syncTriggerTabindex()), this._tabObserver.observe(this, { attributes: !0, attributeFilter: ["tabindex"] }), document.addEventListener("click", this._boundHandleDocumentClick, !0), this.
|
|
298
|
+
super.connectedCallback(), r._ensureBaseStyles(this.getRootNode()), this._tabObserver = new MutationObserver(() => this._syncTriggerTabindex()), this._tabObserver.observe(this, { attributes: !0, attributeFilter: ["tabindex"] }), document.addEventListener("click", this._boundHandleDocumentClick, !0), this.requestUpdate("open");
|
|
194
299
|
}
|
|
195
300
|
/** Disconnects the tabindex observer and removes the document-level click listener. */
|
|
196
301
|
disconnectedCallback() {
|
|
@@ -202,7 +307,9 @@ const a = class a extends d {
|
|
|
202
307
|
* @param focusTarget - which item receives initial focus when the menu opens
|
|
203
308
|
*/
|
|
204
309
|
openMenu(t = "first") {
|
|
205
|
-
this.open || (this._anchorCtrl.setOptions({ placement: this._effectivePlacement }), this._setOpen(!0, !0), this.
|
|
310
|
+
this.open || (this._anchorCtrl.setOptions({ placement: this._effectivePlacement }), this._setOpen(!0, !0), this.updateComplete.then(() => {
|
|
311
|
+
if (!this.open)
|
|
312
|
+
return;
|
|
206
313
|
const e = this._$menu?.deref();
|
|
207
314
|
t === "last" ? e?.focusLast() : e?.focusFirst();
|
|
208
315
|
}));
|
|
@@ -213,26 +320,26 @@ const a = class a extends d {
|
|
|
213
320
|
* @param returnFocus - when `true`, returns focus to the trigger button after closing
|
|
214
321
|
*/
|
|
215
322
|
closeMenu(t = !0) {
|
|
216
|
-
this.open && (this._setOpen(!1, !0), t && this._$trigger?.deref()?.focus());
|
|
323
|
+
this.open && (this._setOpen(!1, !0), t && !this.open && this._$trigger?.deref()?.focus());
|
|
217
324
|
}
|
|
218
325
|
/** Toggles the menu between open and closed. */
|
|
219
326
|
toggleMenu() {
|
|
220
327
|
this.open ? this.closeMenu() : this.openMenu();
|
|
221
328
|
}
|
|
222
|
-
/** Dispatches the `rc-menu-button-toggle` bubbling composed event with the
|
|
223
|
-
_dispatchToggle() {
|
|
329
|
+
/** Dispatches the `rc-menu-button-toggle` bubbling composed event with the requested open state. */
|
|
330
|
+
_dispatchToggle(t = this.open) {
|
|
224
331
|
this.dispatchEvent(
|
|
225
332
|
new CustomEvent("rc-menu-button-toggle", {
|
|
226
333
|
bubbles: !0,
|
|
227
334
|
composed: !0,
|
|
228
|
-
detail: { open:
|
|
335
|
+
detail: { open: t }
|
|
229
336
|
})
|
|
230
337
|
);
|
|
231
338
|
}
|
|
232
339
|
/** Caches a weak reference to the first assigned trigger element and syncs its ARIA and tabindex state. */
|
|
233
340
|
_handleTriggerSlotChange(t) {
|
|
234
|
-
const
|
|
235
|
-
|
|
341
|
+
const n = t.currentTarget.assignedElements()[0];
|
|
342
|
+
n && (this._$trigger = new WeakRef(n), this._syncTriggerAria(), this._syncTriggerTabindex());
|
|
236
343
|
}
|
|
237
344
|
/** Tracks optional indicator content so the trigger reserves its inline-end space. */
|
|
238
345
|
_handleIndicatorSlotChange(t) {
|
|
@@ -273,8 +380,8 @@ const a = class a extends d {
|
|
|
273
380
|
}
|
|
274
381
|
/** Caches a weak reference to the first assigned `rc-menu` element. */
|
|
275
382
|
_handleMenuSlotChange(t) {
|
|
276
|
-
const
|
|
277
|
-
|
|
383
|
+
const i = t.currentTarget.assignedElements().find((s) => s.tagName === "RC-MENU");
|
|
384
|
+
i && (this._$menu = new WeakRef(i));
|
|
278
385
|
}
|
|
279
386
|
/** Prevents the default button action and delegates to `toggleMenu`. */
|
|
280
387
|
_handleTriggerClick(t) {
|
|
@@ -294,13 +401,11 @@ const a = class a extends d {
|
|
|
294
401
|
}
|
|
295
402
|
/** Syncs trigger ARIA when `open` changes; updates anchor placement when `placement` or `orientation` change. */
|
|
296
403
|
updated(t) {
|
|
297
|
-
super.updated(t), t.has("open") && (this._syncTriggerAria(), this._$popup?.isConnected && this._$popup.togglePopover(this.open)), (t.has("placement") || t.has("orientation")) && this._anchorCtrl.setOptions({ placement: this._effectivePlacement });
|
|
404
|
+
super.updated(t), t.has("open") && (this._syncTriggerAria(), this._$popup?.isConnected && (this._$popup.togglePopover(this.open), this.open && this._anchorCtrl.update())), (t.has("placement") || t.has("orientation")) && this._anchorCtrl.setOptions({ placement: this._effectivePlacement });
|
|
298
405
|
}
|
|
299
406
|
_setOpen(t, e) {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
const r = this._open;
|
|
303
|
-
this._open = t, this.requestUpdate("open", r), this._syncTriggerAria(), e && this._dispatchToggle();
|
|
407
|
+
const n = this.open;
|
|
408
|
+
n !== t && (this._open === void 0 && (this._uncontrolledOpen = t), this.requestUpdate("open", n), this._syncTriggerAria(), e && this._dispatchToggle(t));
|
|
304
409
|
}
|
|
305
410
|
/** Writes `aria-haspopup` and `aria-expanded` to the trigger button to match the current open state. */
|
|
306
411
|
_syncTriggerAria() {
|
|
@@ -342,37 +447,36 @@ const a = class a extends d {
|
|
|
342
447
|
</div>
|
|
343
448
|
`;
|
|
344
449
|
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
...d.shadowRootOptions,
|
|
450
|
+
}, r.styles = [y], r.shadowRootOptions = {
|
|
451
|
+
...g.shadowRootOptions,
|
|
348
452
|
delegatesFocus: !0
|
|
349
|
-
};
|
|
350
|
-
|
|
351
|
-
o([
|
|
453
|
+
}, r._styledRoots = /* @__PURE__ */ new Set(), r);
|
|
454
|
+
a([
|
|
352
455
|
l({ type: Boolean, reflect: !0 })
|
|
353
|
-
],
|
|
354
|
-
|
|
456
|
+
], o.prototype, "open", 1);
|
|
457
|
+
a([
|
|
355
458
|
l({ type: Boolean, attribute: "default-open" })
|
|
356
|
-
],
|
|
357
|
-
|
|
459
|
+
], o.prototype, "defaultOpen", 1);
|
|
460
|
+
a([
|
|
358
461
|
l({ type: String, reflect: !0 })
|
|
359
|
-
],
|
|
360
|
-
|
|
462
|
+
], o.prototype, "orientation", 2);
|
|
463
|
+
a([
|
|
361
464
|
l({ reflect: !0 })
|
|
362
|
-
],
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
],
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
],
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
],
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
],
|
|
465
|
+
], o.prototype, "placement", 2);
|
|
466
|
+
a([
|
|
467
|
+
d("#root")
|
|
468
|
+
], o.prototype, "_$root", 2);
|
|
469
|
+
a([
|
|
470
|
+
d("#popup")
|
|
471
|
+
], o.prototype, "_$popup", 2);
|
|
472
|
+
a([
|
|
473
|
+
h()
|
|
474
|
+
], o.prototype, "_$trigger", 2);
|
|
475
|
+
a([
|
|
476
|
+
h()
|
|
477
|
+
], o.prototype, "_$menu", 2);
|
|
478
|
+
let C = o;
|
|
375
479
|
export {
|
|
376
|
-
|
|
480
|
+
C as R
|
|
377
481
|
};
|
|
378
|
-
//# sourceMappingURL=rc-menu-button-
|
|
482
|
+
//# sourceMappingURL=rc-menu-button-DPs2AT2d.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rc-menu-button-DPs2AT2d.js","sources":["../src/rc-menu-button.styles.ts","../src/rc-menu-button.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const menuButtonStyles = css`\n :host {\n display: inline-block;\n }\n\n :host([orientation='vertical']) {\n display: block;\n }\n\n #root {\n display: inline-block;\n }\n\n :host([orientation='vertical']) #root {\n display: block;\n inline-size: 100%;\n }\n\n #trigger-wrap {\n position: relative;\n display: inline-block;\n }\n\n :host([orientation='vertical']) #trigger-wrap {\n display: block;\n inline-size: 100%;\n }\n\n /*\n * Icon-only triggers (e.g. a toolbar's overflow button) can render\n * visually smaller than the accessible 48dp touch-target minimum,\n * especially at a narrow width. This is a floor, not a fixed size: a\n * trigger already at or above it (the default width, or a labeled\n * trigger) is unaffected. #trigger-wrap reserves the layout space and\n * centers the (possibly smaller) slotted trigger within it; the actual\n * larger hit region comes from the light-DOM hit-slop pseudo-element in\n * rc-menu-button.ts. Mirrors rc-button's own touch-target affordance.\n *\n * Scoped to [icon-only] rather than applied unconditionally: switching\n * #trigger-wrap to a flex/grid container would blockify the slotted\n * trigger's own inline-flex display (its getComputedStyle().display\n * becomes \"flex\", per the CSS Display spec's flex-item blockification —\n * harmless for layout, since a flex item is sized by its container's\n * flex algorithm regardless of its own inline/block outer type, but an\n * observable change other callers shouldn't have to account for).\n */\n :host([icon-only]) #trigger-wrap {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-block-size: var(--rc-menu-button-touch-target-block-size, 3rem);\n min-inline-size: var(\n --rc-menu-button-touch-target-inline-size,\n var(--rc-menu-button-touch-target-block-size, 3rem)\n );\n /*\n * Zero by default. A theme or consumer sets one of these on a trigger\n * that sits at a real edge (no neighbor on that side) to let the\n * touch-target inflation above overlap into whatever sits just outside\n * the host instead of also reserving layout space there. Mirrors\n * rc-button's own --rc-button-touch-target-overlap-inline-* tokens.\n */\n margin-inline-start: calc(-1 * var(--rc-menu-button-touch-target-overlap-inline-start, 0px));\n margin-inline-end: calc(-1 * var(--rc-menu-button-touch-target-overlap-inline-end, 0px));\n }\n\n :host([icon-only][orientation='vertical']) #trigger-wrap {\n display: flex;\n }\n\n /*\n * Icon-only trigger width: square by default (matches its own block\n * size), or a distinct value for a narrower/wider variant. Padding is\n * cleared since an icon-only trigger centers its (typically single) icon\n * child via the flex alignment above rather than via inline padding.\n */\n :host([icon-only]) slot[name='trigger']::slotted(button),\n :host([icon-only]) slot[name='trigger']::slotted([role='button']) {\n inline-size: var(\n --rc-menu-button-icon-size,\n var(--rc-menu-button-trigger-block-size, var(--rc-control-block-size, 2.25em))\n );\n min-inline-size: var(\n --rc-menu-button-icon-size,\n var(--rc-menu-button-trigger-block-size, var(--rc-control-block-size, 2.25em))\n );\n padding-inline: 0;\n }\n\n slot[name='trigger']::slotted(button),\n slot[name='trigger']::slotted([role='button']) {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--rc-menu-button-trigger-gap, var(--rc-item-gap, 0.5em));\n min-block-size: var(--rc-menu-button-trigger-block-size, var(--rc-control-block-size, 2.25em));\n padding: var(--rc-menu-button-trigger-padding-block, var(--rc-control-padding-block, 0.25em))\n var(--rc-menu-button-trigger-padding-inline, var(--rc-control-padding-inline, 0.5em));\n appearance: none;\n box-sizing: border-box;\n border: var(--rc-menu-button-trigger-border, var(--rc-border, 1px solid ButtonBorder));\n border-radius: var(--rc-menu-button-trigger-radius, var(--rc-control-radius, 0.125em));\n background: var(--rc-menu-button-trigger-background, var(--rc-button-bg, ButtonFace));\n color: var(--rc-menu-button-trigger-color, var(--rc-button-text, ButtonText));\n font: inherit;\n text-decoration: none;\n cursor: default;\n user-select: none;\n transition: var(--rc-menu-button-trigger-transition);\n }\n\n slot[name='trigger']::slotted(button:hover),\n slot[name='trigger']::slotted([role='button']:hover) {\n border-color: var(--rc-menu-button-trigger-hover-border-color, currentColor);\n background: var(\n --rc-menu-button-trigger-hover-background,\n color-mix(in srgb, Highlight 8%, transparent)\n );\n color: var(--rc-menu-button-trigger-hover-color, inherit);\n }\n\n slot[name='trigger']::slotted(button[aria-expanded='true']),\n slot[name='trigger']::slotted([role='button'][aria-expanded='true']) {\n border-color: var(--rc-menu-button-trigger-open-border-color, currentColor);\n background: var(\n --rc-menu-button-trigger-open-background,\n color-mix(in srgb, Highlight 12%, transparent)\n );\n color: var(--rc-menu-button-trigger-open-color, inherit);\n }\n\n :host([orientation='vertical']) slot[name='trigger']::slotted(button),\n :host([orientation='vertical']) slot[name='trigger']::slotted([role='button']) {\n inline-size: 100%;\n text-align: start;\n }\n\n :host([has-indicator]) slot[name='trigger']::slotted(button),\n :host([has-indicator]) slot[name='trigger']::slotted([role='button']) {\n padding-inline-end: calc(\n var(\n --rc-menu-button-indicator-inset,\n var(--rc-menu-button-trigger-padding-inline, var(--rc-control-padding-inline, 0.5em))\n ) +\n var(--rc-menu-button-indicator-size, 1em) +\n var(--rc-menu-button-trigger-gap, var(--rc-item-gap, 0.5em))\n );\n }\n\n slot[name='indicator'] {\n position: absolute;\n inset-block-start: 50%;\n inset-inline-end: var(\n --rc-menu-button-indicator-inset,\n var(--rc-menu-button-trigger-padding-inline, var(--rc-control-padding-inline, 0.5em))\n );\n display: inline-flex;\n align-items: center;\n justify-content: center;\n inline-size: var(--rc-menu-button-indicator-size, 1em);\n block-size: var(--rc-menu-button-indicator-size, 1em);\n color: var(--rc-menu-button-indicator-color, currentColor);\n pointer-events: none;\n transform: translateY(-50%);\n }\n\n slot[name='indicator']::slotted(*) {\n inline-size: 100%;\n block-size: 100%;\n }\n\n #popup {\n margin: 0;\n padding: 0;\n border: none;\n background: none;\n overflow: visible;\n color: inherit;\n }\n`;\n\nexport default menuButtonStyles;\n","import { LitElement, html } from 'lit';\nimport { property, query, state } from 'lit/decorators.js';\n\nimport {\n AnchorController,\n keyInteraction,\n keyNavigation,\n type AnchorPlacement,\n type KeyboardNavigationAction,\n} from '@rcarls/rc-common';\nimport type { RCMenu } from '@rcarls/rc-menu';\n\nimport menuButtonStyles from './rc-menu-button.styles.js';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'rc-menu-button': RCMenuButton;\n }\n}\n\nconst LIGHT_DOM_CSS = `\n@layer rc-base {\n /*\n * Expands an icon-only trigger's clickable region beyond its visible box\n * up to the accessible touch-target minimum, the same way rc-button and\n * rc-chip do: an absolutely-positioned, invisible pseudo-element on the\n * actual slotted trigger element (not the host) extends the hit area\n * symmetrically. The trigger already has position: relative from the\n * shadow-scoped ::slotted(button) rule. max(100%, size) keeps this a\n * no-op once the visible trigger already meets or exceeds the touch\n * target, rather than shrinking it.\n */\n rc-menu-button[icon-only] > [slot='trigger']::before {\n content: '';\n position: absolute;\n inset-block: calc(\n (\n var(--rc-menu-button-touch-target-block-size, 3rem) -\n max(100%, var(--rc-menu-button-trigger-block-size, 0px))\n ) / -2\n );\n inset-inline: calc(\n (\n var(\n --rc-menu-button-touch-target-inline-size,\n var(--rc-menu-button-touch-target-block-size, 3rem)\n ) -\n max(100%, var(--rc-menu-button-icon-size, var(--rc-menu-button-trigger-block-size, 0px)))\n ) / -2\n );\n }\n}\n`;\n\n/** Detail payload for the `rc-menu-button-toggle` event. */\nexport interface RCMenuButtonToggleEvent {\n /** Whether the menu transitioned to open (`true`) or closed (`false`). */\n open: boolean;\n}\n\n/**\n * Trigger button that opens an rc-menu popup, following the WAI-ARIA Menu Button pattern.\n *\n *\n * @see {@link https://richardcarls.github.io/rc-webcomponents/components/rc-menu-button rc-menu-button docs}\n * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/ WAI-ARIA Menu Button pattern}\n *\n * @slot trigger - The button element that triggers the menu\n * @slot indicator - Optional decorative indicator rendered at the trigger's inline end\n * @slot default - The rc-menu element to display as popup\n *\n * @fires rc-menu-button-toggle - Fired when the menu opens or closes\n *\n * @cssprop [--rc-menu-button-trigger-block-size=var(--rc-control-block-size)] - Minimum block size of the trigger\n * @cssprop [--rc-menu-button-trigger-padding-block=var(--rc-control-padding-block)] - Trigger block-axis padding\n * @cssprop [--rc-menu-button-trigger-padding-inline=var(--rc-control-padding-inline)] - Trigger inline-axis padding\n * @cssprop [--rc-menu-button-trigger-gap=var(--rc-item-gap)] - Gap between flex children in the trigger\n * @cssprop [--rc-menu-button-trigger-border=var(--rc-border)] - Trigger border\n * @cssprop [--rc-menu-button-trigger-radius=var(--rc-control-radius)] - Trigger border radius\n * @cssprop [--rc-menu-button-trigger-background=var(--rc-button-bg)] - Trigger background\n * @cssprop [--rc-menu-button-trigger-color=var(--rc-button-text)] - Trigger text color\n * @cssprop [--rc-menu-button-trigger-transition] - CSS transition applied to the trigger\n * @cssprop [--rc-menu-button-trigger-hover-background=color-mix(in srgb, Highlight 8%, transparent)] - Trigger hover background\n * @cssprop [--rc-menu-button-trigger-hover-color=inherit] - Trigger hover text color\n * @cssprop [--rc-menu-button-trigger-hover-border-color=currentColor] - Trigger hover border color\n * @cssprop [--rc-menu-button-trigger-open-background=color-mix(in srgb, Highlight 12%, transparent)] - Trigger background when the menu is open\n * @cssprop [--rc-menu-button-trigger-open-color=inherit] - Trigger text color when the menu is open\n * @cssprop [--rc-menu-button-trigger-open-border-color=currentColor] - Trigger border color when the menu is open\n * @cssprop [--rc-menu-button-indicator-size=1em] - Inline and block size of the slotted indicator\n * @cssprop [--rc-menu-button-indicator-color=currentColor] - Color of the slotted indicator\n * @cssprop [--rc-menu-button-indicator-inset=var(--rc-menu-button-trigger-padding-inline)] - Indicator distance from the trigger's inline end\n * @cssprop [--rc-menu-button-icon-size] - Inline size of an `icon-only` trigger's visible box.\n * Square by default (equal to `--rc-menu-button-trigger-block-size`); set narrower or wider\n * to change only the trigger's width, independent of its height.\n * @cssprop [--rc-menu-button-touch-target-block-size=3rem] - Minimum accessible touch target\n * block size for an `icon-only` trigger. A floor, not a fixed size: has no effect once\n * `--rc-menu-button-trigger-block-size` already meets or exceeds it. Grows the shadow-DOM\n * trigger wrapper (reserving layout space) and the light-DOM hit-slop (the actual larger\n * clickable region) together; the visible trigger itself stays at its own size, centered.\n * @cssprop [--rc-menu-button-touch-target-inline-size] - Minimum accessible touch target inline\n * size for an `icon-only` trigger. Defers to `--rc-menu-button-touch-target-block-size` when\n * unset.\n * @cssprop [--rc-menu-button-touch-target-overlap-inline-start=0px] - Zero by default. A theme\n * or consumer sets this on an `icon-only` trigger that sits at a real leading edge (no\n * neighbor on that side) to let its touch-target inflation overlap into whatever sits just\n * outside the host, such as a container's own edge padding, instead of also reserving layout\n * space there.\n * @cssprop [--rc-menu-button-touch-target-overlap-inline-end=0px] - The trailing-edge\n * counterpart to `--rc-menu-button-touch-target-overlap-inline-start`.\n *\n * @csspart root - The root container element\n * @csspart popup - The popup container element\n *\n * @attr open - Whether the menu popup is visible. Controlled mode: host writes silently.\n * @attr default-open - Initial open state for uncontrolled mode. Ignored after the first\n * controlled write to `open`.\n * @attr orientation - Arrow-key axis for opening the menu. Inherits from a parent\n * `rc-menubar` or `[role=\"menubar\"]` when unset.\n * @attr placement - Preferred placement of the popup relative to the trigger.\n * @attr icon-only - Hints that the slotted trigger has no visible label, so themes can size\n * it and its touch target as an icon button (see `--rc-menu-button-icon-size` and\n * `--rc-menu-button-touch-target-*` above). Purely a styling hook; RCMenuButton does not read\n * or derive it — set it whenever the trigger is rendered icon-only.\n */\nexport class RCMenuButton extends LitElement {\n static styles = [menuButtonStyles];\n\n /**\n * Enables delegatesFocus so the browser routes focus() on the host element\n * to the slotted trigger button.\n */\n static override shadowRootOptions: ShadowRootInit = {\n ...LitElement.shadowRootOptions,\n\n delegatesFocus: true,\n };\n\n protected static readonly _styledRoots = new Set<Document | ShadowRoot>();\n\n protected static _ensureBaseStyles(root: Document | ShadowRoot): void {\n if (RCMenuButton._styledRoots.has(root)) {\n return;\n }\n\n RCMenuButton._styledRoots.add(root);\n\n const style = document.createElement('style');\n\n style.setAttribute('data-rc-light-dom-base', 'rc-menu-button');\n style.textContent = LIGHT_DOM_CSS;\n\n if (root instanceof Document) {\n root.head.append(style);\n } else {\n root.append(style);\n }\n }\n\n private _defaultOpen = false;\n private _open: boolean | undefined;\n private _uncontrolledOpen: boolean | undefined;\n private _openInitialized = false;\n\n /**\n * Whether the menu is currently open.\n *\n * In controlled mode the host owns this value; writing the property applies\n * the state silently without dispatching `rc-menu-button-toggle`.\n */\n @property({ type: Boolean, reflect: true })\n get open(): boolean {\n return this._open ?? this._uncontrolledOpen ?? this._defaultOpen;\n }\n\n /** Applies open state in controlled mode without dispatching an event. */\n set open(value: boolean | undefined) {\n const oldValue = this.open;\n\n this._open = value;\n this._openInitialized = true;\n this.requestUpdate('open', oldValue);\n this._syncTriggerAria();\n }\n\n /**\n * Initial open state for uncontrolled mode.\n *\n * Ignored after the first controlled write; use `open` to update state\n * programmatically after mount.\n */\n @property({ type: Boolean, attribute: 'default-open' })\n get defaultOpen(): boolean {\n return this._defaultOpen;\n }\n\n /** Applies the uncontrolled default before any controlled write occurs. */\n set defaultOpen(value: boolean) {\n const oldValue = this._defaultOpen;\n\n this._defaultOpen = value;\n\n if (\n !this._openInitialized &&\n this._open === undefined &&\n this._uncontrolledOpen === undefined\n ) {\n this.requestUpdate('open', oldValue);\n }\n\n this.requestUpdate('defaultOpen', oldValue);\n }\n\n /**\n * Orientation of this menu button, affects which arrow keys open/close the menu.\n *\n * If not set, inherits from a parent rc-menubar or element with role=\"menubar\".\n */\n @property({ type: String, reflect: true })\n orientation: 'horizontal' | 'vertical' | undefined;\n\n /** Preferred placement of the popup relative to the trigger button. */\n @property({ reflect: true })\n placement: AnchorPlacement = 'bottom-start';\n\n /**\n * Popup placement adjusted for orientation.\n *\n * Switches from `bottom-start` to `right-start` when the resolved orientation\n * is `vertical`, so vertical menubars open submenus to the side.\n */\n protected get _effectivePlacement(): AnchorPlacement {\n if (this.placement !== 'bottom-start') {\n return this.placement;\n }\n\n return this._resolvedOrientation === 'vertical' ? 'right-start' : this.placement;\n }\n\n /**\n * Resolved orientation, considering inheritance from parent menubar.\n * Falls back to 'horizontal' if no orientation is set or inherited.\n */\n protected get _resolvedOrientation(): 'horizontal' | 'vertical' {\n if (this.orientation) {\n return this.orientation;\n }\n\n const $menubar = this.closest('rc-menubar, [role=\"menubar\"]');\n\n if ($menubar) {\n const orientation =\n $menubar.getAttribute('orientation') ?? $menubar.getAttribute('aria-orientation');\n\n if (orientation === 'vertical') {\n return 'vertical';\n }\n\n if (orientation === 'horizontal') {\n return 'horizontal';\n }\n }\n\n return 'horizontal';\n }\n\n /** Shadow DOM root container. Serves as the anchor element for `_anchorCtrl`. */\n @query('#root') protected _$root!: HTMLElement;\n\n /** Shadow DOM popup container. Hidden when `open` is `false`. */\n @query('#popup') protected _$popup!: HTMLElement;\n\n /** Weak reference to the slotted trigger button. */\n @state()\n protected _$trigger: WeakRef<HTMLElement> | undefined;\n\n /** Weak reference to the slotted `rc-menu` element. */\n @state()\n protected _$menu: WeakRef<RCMenu> | undefined;\n\n /** Positions the popup relative to the trigger using CSS anchor positioning. */\n protected _anchorCtrl = new AnchorController(this, {\n anchor: () => this._$root ?? null,\n floating: () => this._$popup ?? null,\n shadowHost: () => this,\n placement: 'bottom-start',\n offset: 2,\n });\n\n /** Bound handler for document click (light dismiss). Stored for `removeEventListener` pairing. */\n protected _boundHandleDocumentClick = this._handleDocumentClick.bind(this);\n\n /**\n * Watches the host's own `tabindex` attribute so the trigger button's\n * tabindex can be kept in sync.\n *\n * When a parent (e.g. rc-toolbar) places the\n * host under roving-tabindex management it sets/removes tabindex on the\n * host; we mirror that to the trigger so it doesn't become an independent\n * tab stop. When the host has no tabindex the trigger keeps its natural\n * tabindex=0 for standalone usage.\n */\n protected _tabObserver?: MutationObserver;\n\n /** Installs the tabindex mutation observer and the document-level click listener. */\n override connectedCallback() {\n super.connectedCallback();\n RCMenuButton._ensureBaseStyles(this.getRootNode() as Document | ShadowRoot);\n\n this._tabObserver = new MutationObserver(() => this._syncTriggerTabindex());\n this._tabObserver.observe(this, { attributes: true, attributeFilter: ['tabindex'] });\n\n document.addEventListener('click', this._boundHandleDocumentClick, true);\n\n this.requestUpdate('open');\n }\n\n /** Disconnects the tabindex observer and removes the document-level click listener. */\n override disconnectedCallback() {\n this._tabObserver?.disconnect();\n this._tabObserver = undefined;\n\n super.disconnectedCallback();\n document.removeEventListener('click', this._boundHandleDocumentClick, true);\n }\n\n /**\n * Opens the menu and moves focus into it.\n *\n * @param focusTarget - which item receives initial focus when the menu opens\n */\n openMenu(focusTarget: 'first' | 'last' = 'first') {\n if (this.open) {\n return;\n }\n\n this._anchorCtrl.setOptions({ placement: this._effectivePlacement });\n this._setOpen(true, true);\n\n this.updateComplete.then(() => {\n if (!this.open) {\n return;\n }\n\n const $menu = this._$menu?.deref();\n\n focusTarget === 'last' ? $menu?.focusLast() : $menu?.focusFirst();\n });\n }\n\n /**\n * Closes the menu.\n *\n * @param returnFocus - when `true`, returns focus to the trigger button after closing\n */\n closeMenu(returnFocus = true) {\n if (!this.open) {\n return;\n }\n\n this._setOpen(false, true);\n\n if (returnFocus && !this.open) {\n const $trigger = this._$trigger?.deref();\n\n $trigger?.focus();\n }\n }\n\n /** Toggles the menu between open and closed. */\n toggleMenu() {\n if (this.open) {\n this.closeMenu();\n } else {\n this.openMenu();\n }\n }\n\n /** Dispatches the `rc-menu-button-toggle` bubbling composed event with the requested open state. */\n protected _dispatchToggle(open = this.open) {\n this.dispatchEvent(\n new CustomEvent<RCMenuButtonToggleEvent>('rc-menu-button-toggle', {\n bubbles: true,\n composed: true,\n detail: { open },\n }),\n );\n }\n\n /** Caches a weak reference to the first assigned trigger element and syncs its ARIA and tabindex state. */\n protected _handleTriggerSlotChange(e: Event) {\n const $slot = e.currentTarget as HTMLSlotElement;\n const $trigger = $slot.assignedElements()[0] as HTMLElement | undefined;\n\n if ($trigger) {\n this._$trigger = new WeakRef($trigger);\n this._syncTriggerAria();\n this._syncTriggerTabindex();\n }\n }\n\n /** Tracks optional indicator content so the trigger reserves its inline-end space. */\n protected _handleIndicatorSlotChange(e: Event) {\n const $slot = e.currentTarget as HTMLSlotElement;\n\n this.toggleAttribute('has-indicator', $slot.assignedElements().length > 0);\n }\n\n /**\n * Mirrors the host's `tabindex` attribute to the trigger button.\n *\n * When a roving-tabindex parent (e.g. rc-toolbar) marks this host inactive\n * with `tabindex=\"-1\"`, the trigger must also be suppressed so it does not\n * become an independent tab stop. When the host is the active item\n * (`tabindex=\"0\"`) or standalone (no tabindex), the trigger retains its\n * natural focusability so that Chrome's delegatesFocus can route sequential\n * Tab navigation through the host to the trigger.\n */\n protected _syncTriggerTabindex() {\n const $trigger = this._$trigger?.deref();\n\n if (!$trigger) {\n return;\n }\n\n if (this.getAttribute('tabindex') === '-1') {\n $trigger.setAttribute('tabindex', '-1');\n } else {\n $trigger.removeAttribute('tabindex');\n }\n }\n\n /**\n * Overrides the default focus() so that programmatic focus calls (e.g. from\n * a roving-tabindex parent navigating back to this element via arrow keys)\n * always reach the trigger.\n *\n * Chrome's delegatesFocus will not delegate to a tabindex=\"-1\" element, so\n * when the toolbar marks this host inactive it suppresses the trigger — and\n * the next focusItem() call silently fails. Lifting the suppression here and\n * directly calling trigger.focus() bypasses that restriction.\n */\n override focus(options?: FocusOptions) {\n const $trigger = this._$trigger?.deref();\n\n if (!$trigger) {\n super.focus(options);\n\n return;\n }\n\n $trigger.removeAttribute('tabindex');\n $trigger.focus(options);\n }\n\n /** Caches a weak reference to the first assigned `rc-menu` element. */\n protected _handleMenuSlotChange(e: Event) {\n const $slot = e.currentTarget as HTMLSlotElement;\n const $elements = $slot.assignedElements();\n const $menu = $elements.find(($el) => $el.tagName === 'RC-MENU') as RCMenu | undefined;\n\n if ($menu) {\n this._$menu = new WeakRef($menu);\n }\n }\n\n /**\n * Keyboard navigation handler.\n *\n * Opens or closes the menu in response to arrow/Enter/Escape keys.\n **/\n protected _onNavigate = (action: KeyboardNavigationAction) => {\n switch (action) {\n case 'open-to-first':\n case 'activate':\n this.openMenu();\n break;\n\n case 'open-to-last':\n this.openMenu('last');\n break;\n\n case 'escape':\n this.closeMenu();\n break;\n }\n };\n\n /** Prevents the default button action and delegates to `toggleMenu`. */\n protected _handleTriggerClick(e: MouseEvent) {\n e.preventDefault();\n\n this.toggleMenu();\n }\n\n /** Closes the menu when an `rc-menu-close` event bubbles up from the popup. */\n protected _handleMenuClose() {\n this.closeMenu();\n }\n\n /** Closes the menu when an `rc-menu-activate` event bubbles up from the popup. */\n protected _handleMenuActivate() {\n this.closeMenu();\n }\n\n /** Closes the menu on clicks outside this component (light dismiss). */\n protected _handleDocumentClick(e: MouseEvent) {\n if (!this.open) {\n return;\n }\n\n const path = e.composedPath();\n\n if (path.includes(this)) {\n return;\n }\n\n this.closeMenu(false);\n }\n\n /** Syncs trigger ARIA when `open` changes; updates anchor placement when `placement` or `orientation` change. */\n protected override updated(changedProperties: Map<PropertyKey, unknown>) {\n super.updated(changedProperties);\n\n if (changedProperties.has('open')) {\n this._syncTriggerAria();\n\n // A pending update can flush after the host (and its shadow tree) has\n // already been disconnected — e.g. a framework unmounting this element\n // in the same tick as an `open` change. togglePopover() throws\n // InvalidStateError on a disconnected popover, so guard on connectivity\n // rather than letting that reach the caller.\n if (this._$popup?.isConnected) {\n this._$popup.togglePopover(this.open);\n\n if (this.open) {\n this._anchorCtrl.update();\n }\n }\n }\n\n if (changedProperties.has('placement') || changedProperties.has('orientation')) {\n this._anchorCtrl.setOptions({ placement: this._effectivePlacement });\n }\n }\n\n protected _setOpen(open: boolean, dispatch: boolean): void {\n const oldValue = this.open;\n\n if (oldValue === open) {\n return;\n }\n\n if (this._open === undefined) {\n this._uncontrolledOpen = open;\n }\n\n this.requestUpdate('open', oldValue);\n this._syncTriggerAria();\n\n if (dispatch) {\n this._dispatchToggle(open);\n }\n }\n\n /** Writes `aria-haspopup` and `aria-expanded` to the trigger button to match the current open state. */\n protected _syncTriggerAria(): void {\n const $trigger = this._$trigger?.deref();\n\n if (!$trigger?.isConnected) {\n return;\n }\n\n $trigger.setAttribute('aria-haspopup', 'menu');\n $trigger.setAttribute('aria-expanded', String(this.open));\n }\n\n protected override render() {\n return html`\n <div id=\"root\" part=\"root\">\n <div\n id=\"trigger-wrap\"\n ${keyNavigation(this._onNavigate, {\n navigationAxis: this._resolvedOrientation,\n handleNavAxis: false,\n handleOpenAxis: true,\n handleActivate: true,\n handleEscape: this.open,\n })}\n ${keyInteraction()}\n @click=${this._handleTriggerClick}\n >\n <slot name=\"trigger\" @slotchange=${this._handleTriggerSlotChange}></slot>\n <slot\n name=\"indicator\"\n aria-hidden=\"true\"\n @slotchange=${this._handleIndicatorSlotChange}\n ></slot>\n </div>\n\n <div\n id=\"popup\"\n part=\"popup\"\n popover=\"manual\"\n @rc-menu-close=${this._handleMenuClose}\n @rc-menu-activate=${this._handleMenuActivate}\n >\n <slot @slotchange=${this._handleMenuSlotChange}></slot>\n </div>\n </div>\n `;\n }\n}\n\nexport default RCMenuButton;\n"],"names":["menuButtonStyles","css","LIGHT_DOM_CSS","_RCMenuButton","_a","LitElement","AnchorController","action","root","style","value","oldValue","$menubar","orientation","focusTarget","$menu","returnFocus","open","e","$trigger","$slot","options","$el","changedProperties","dispatch","html","keyNavigation","keyInteraction","__decorateClass","property","query","state","RCMenuButton"],"mappings":"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"}
|
package/dist/rc-menu-button.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from './rc-menu-button';
|
|
1
|
+
export * from './rc-menu-button.js';
|
|
@@ -42,6 +42,24 @@ export interface RCMenuButtonToggleEvent {
|
|
|
42
42
|
* @cssprop [--rc-menu-button-indicator-size=1em] - Inline and block size of the slotted indicator
|
|
43
43
|
* @cssprop [--rc-menu-button-indicator-color=currentColor] - Color of the slotted indicator
|
|
44
44
|
* @cssprop [--rc-menu-button-indicator-inset=var(--rc-menu-button-trigger-padding-inline)] - Indicator distance from the trigger's inline end
|
|
45
|
+
* @cssprop [--rc-menu-button-icon-size] - Inline size of an `icon-only` trigger's visible box.
|
|
46
|
+
* Square by default (equal to `--rc-menu-button-trigger-block-size`); set narrower or wider
|
|
47
|
+
* to change only the trigger's width, independent of its height.
|
|
48
|
+
* @cssprop [--rc-menu-button-touch-target-block-size=3rem] - Minimum accessible touch target
|
|
49
|
+
* block size for an `icon-only` trigger. A floor, not a fixed size: has no effect once
|
|
50
|
+
* `--rc-menu-button-trigger-block-size` already meets or exceeds it. Grows the shadow-DOM
|
|
51
|
+
* trigger wrapper (reserving layout space) and the light-DOM hit-slop (the actual larger
|
|
52
|
+
* clickable region) together; the visible trigger itself stays at its own size, centered.
|
|
53
|
+
* @cssprop [--rc-menu-button-touch-target-inline-size] - Minimum accessible touch target inline
|
|
54
|
+
* size for an `icon-only` trigger. Defers to `--rc-menu-button-touch-target-block-size` when
|
|
55
|
+
* unset.
|
|
56
|
+
* @cssprop [--rc-menu-button-touch-target-overlap-inline-start=0px] - Zero by default. A theme
|
|
57
|
+
* or consumer sets this on an `icon-only` trigger that sits at a real leading edge (no
|
|
58
|
+
* neighbor on that side) to let its touch-target inflation overlap into whatever sits just
|
|
59
|
+
* outside the host, such as a container's own edge padding, instead of also reserving layout
|
|
60
|
+
* space there.
|
|
61
|
+
* @cssprop [--rc-menu-button-touch-target-overlap-inline-end=0px] - The trailing-edge
|
|
62
|
+
* counterpart to `--rc-menu-button-touch-target-overlap-inline-start`.
|
|
45
63
|
*
|
|
46
64
|
* @csspart root - The root container element
|
|
47
65
|
* @csspart popup - The popup container element
|
|
@@ -52,6 +70,10 @@ export interface RCMenuButtonToggleEvent {
|
|
|
52
70
|
* @attr orientation - Arrow-key axis for opening the menu. Inherits from a parent
|
|
53
71
|
* `rc-menubar` or `[role="menubar"]` when unset.
|
|
54
72
|
* @attr placement - Preferred placement of the popup relative to the trigger.
|
|
73
|
+
* @attr icon-only - Hints that the slotted trigger has no visible label, so themes can size
|
|
74
|
+
* it and its touch target as an icon button (see `--rc-menu-button-icon-size` and
|
|
75
|
+
* `--rc-menu-button-touch-target-*` above). Purely a styling hook; RCMenuButton does not read
|
|
76
|
+
* or derive it — set it whenever the trigger is rendered icon-only.
|
|
55
77
|
*/
|
|
56
78
|
export declare class RCMenuButton extends LitElement {
|
|
57
79
|
static styles: import('lit').CSSResult[];
|
|
@@ -60,8 +82,11 @@ export declare class RCMenuButton extends LitElement {
|
|
|
60
82
|
* to the slotted trigger button.
|
|
61
83
|
*/
|
|
62
84
|
static shadowRootOptions: ShadowRootInit;
|
|
85
|
+
protected static readonly _styledRoots: Set<Document | ShadowRoot>;
|
|
86
|
+
protected static _ensureBaseStyles(root: Document | ShadowRoot): void;
|
|
63
87
|
private _defaultOpen;
|
|
64
88
|
private _open;
|
|
89
|
+
private _uncontrolledOpen;
|
|
65
90
|
private _openInitialized;
|
|
66
91
|
/**
|
|
67
92
|
* Whether the menu is currently open.
|
|
@@ -142,8 +167,8 @@ export declare class RCMenuButton extends LitElement {
|
|
|
142
167
|
closeMenu(returnFocus?: boolean): void;
|
|
143
168
|
/** Toggles the menu between open and closed. */
|
|
144
169
|
toggleMenu(): void;
|
|
145
|
-
/** Dispatches the `rc-menu-button-toggle` bubbling composed event with the
|
|
146
|
-
protected _dispatchToggle(): void;
|
|
170
|
+
/** Dispatches the `rc-menu-button-toggle` bubbling composed event with the requested open state. */
|
|
171
|
+
protected _dispatchToggle(open?: boolean): void;
|
|
147
172
|
/** Caches a weak reference to the first assigned trigger element and syncs its ARIA and tabindex state. */
|
|
148
173
|
protected _handleTriggerSlotChange(e: Event): void;
|
|
149
174
|
/** Tracks optional indicator content so the trigger reserves its inline-end space. */
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.6.0",
|
|
7
7
|
"description": "Trigger button that opens an rc-menu popup.",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
@@ -45,12 +45,12 @@
|
|
|
45
45
|
"test:browser:firefox": "vitest --run --project=firefox"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@rcarls/rc-common": "0.
|
|
49
|
-
"@rcarls/rc-menu": "0.
|
|
50
|
-
"@types/node": "^25.6.0"
|
|
48
|
+
"@rcarls/rc-common": "0.6.0",
|
|
49
|
+
"@rcarls/rc-menu": "0.6.0"
|
|
51
50
|
},
|
|
52
51
|
"devDependencies": {
|
|
53
52
|
"@custom-elements-manifest/analyzer": "0.11.0",
|
|
53
|
+
"@types/node": "^25.6.0",
|
|
54
54
|
"@vitest/browser-playwright": "4.1.5",
|
|
55
55
|
"lit": "^3.0.0",
|
|
56
56
|
"playwright": "^1.56.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rc-menu-button-BuLMtVMw.js","sources":["../src/rc-menu-button.styles.ts","../src/rc-menu-button.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const menuButtonStyles = css`\n :host {\n display: inline-block;\n }\n\n :host([orientation='vertical']) {\n display: block;\n }\n\n #root {\n display: inline-block;\n }\n\n :host([orientation='vertical']) #root {\n display: block;\n }\n\n #trigger-wrap {\n position: relative;\n display: inline-block;\n }\n\n :host([orientation='vertical']) #trigger-wrap {\n display: block;\n }\n\n slot[name='trigger']::slotted(button),\n slot[name='trigger']::slotted([role='button']) {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--rc-menu-button-trigger-gap, var(--rc-item-gap, 0.5em));\n min-block-size: var(--rc-menu-button-trigger-block-size, var(--rc-control-block-size, 2.25em));\n padding: var(--rc-menu-button-trigger-padding-block, var(--rc-control-padding-block, 0.25em))\n var(--rc-menu-button-trigger-padding-inline, var(--rc-control-padding-inline, 0.5em));\n appearance: none;\n box-sizing: border-box;\n border: var(--rc-menu-button-trigger-border, var(--rc-border, 1px solid ButtonBorder));\n border-radius: var(--rc-menu-button-trigger-radius, var(--rc-control-radius, 0.125em));\n background: var(--rc-menu-button-trigger-background, var(--rc-button-bg, ButtonFace));\n color: var(--rc-menu-button-trigger-color, var(--rc-button-text, ButtonText));\n font: inherit;\n text-decoration: none;\n cursor: default;\n user-select: none;\n transition: var(--rc-menu-button-trigger-transition);\n }\n\n slot[name='trigger']::slotted(button:hover),\n slot[name='trigger']::slotted([role='button']:hover) {\n border-color: var(--rc-menu-button-trigger-hover-border-color, currentColor);\n background: var(\n --rc-menu-button-trigger-hover-background,\n color-mix(in srgb, Highlight 8%, transparent)\n );\n color: var(--rc-menu-button-trigger-hover-color, inherit);\n }\n\n slot[name='trigger']::slotted(button[aria-expanded='true']),\n slot[name='trigger']::slotted([role='button'][aria-expanded='true']) {\n border-color: var(--rc-menu-button-trigger-open-border-color, currentColor);\n background: var(\n --rc-menu-button-trigger-open-background,\n color-mix(in srgb, Highlight 12%, transparent)\n );\n color: var(--rc-menu-button-trigger-open-color, inherit);\n }\n\n :host([orientation='vertical']) slot[name='trigger']::slotted(button),\n :host([orientation='vertical']) slot[name='trigger']::slotted([role='button']) {\n inline-size: 100%;\n text-align: start;\n }\n\n :host([has-indicator]) slot[name='trigger']::slotted(button),\n :host([has-indicator]) slot[name='trigger']::slotted([role='button']) {\n padding-inline-end: calc(\n var(\n --rc-menu-button-indicator-inset,\n var(--rc-menu-button-trigger-padding-inline, var(--rc-control-padding-inline, 0.5em))\n ) +\n var(--rc-menu-button-indicator-size, 1em) +\n var(--rc-menu-button-trigger-gap, var(--rc-item-gap, 0.5em))\n );\n }\n\n slot[name='indicator'] {\n position: absolute;\n inset-block-start: 50%;\n inset-inline-end: var(\n --rc-menu-button-indicator-inset,\n var(--rc-menu-button-trigger-padding-inline, var(--rc-control-padding-inline, 0.5em))\n );\n display: inline-flex;\n align-items: center;\n justify-content: center;\n inline-size: var(--rc-menu-button-indicator-size, 1em);\n block-size: var(--rc-menu-button-indicator-size, 1em);\n color: var(--rc-menu-button-indicator-color, currentColor);\n pointer-events: none;\n transform: translateY(-50%);\n }\n\n slot[name='indicator']::slotted(*) {\n inline-size: 100%;\n block-size: 100%;\n }\n\n #popup {\n margin: 0;\n padding: 0;\n border: none;\n background: none;\n overflow: visible;\n color: inherit;\n }\n`;\n\nexport default menuButtonStyles;\n","import { LitElement, html } from 'lit';\nimport { property, query, state } from 'lit/decorators.js';\n\nimport {\n AnchorController,\n keyInteraction,\n keyNavigation,\n type AnchorPlacement,\n type KeyboardNavigationAction,\n} from '@rcarls/rc-common';\nimport type { RCMenu } from '@rcarls/rc-menu';\n\nimport menuButtonStyles from './rc-menu-button.styles';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'rc-menu-button': RCMenuButton;\n }\n}\n\n/** Detail payload for the `rc-menu-button-toggle` event. */\nexport interface RCMenuButtonToggleEvent {\n /** Whether the menu transitioned to open (`true`) or closed (`false`). */\n open: boolean;\n}\n\n/**\n * Trigger button that opens an rc-menu popup, following the WAI-ARIA Menu Button pattern.\n *\n *\n * @see {@link https://richardcarls.github.io/rc-webcomponents/components/rc-menu-button rc-menu-button docs}\n * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/ WAI-ARIA Menu Button pattern}\n *\n * @slot trigger - The button element that triggers the menu\n * @slot indicator - Optional decorative indicator rendered at the trigger's inline end\n * @slot default - The rc-menu element to display as popup\n *\n * @fires rc-menu-button-toggle - Fired when the menu opens or closes\n *\n * @cssprop [--rc-menu-button-trigger-block-size=var(--rc-control-block-size)] - Minimum block size of the trigger\n * @cssprop [--rc-menu-button-trigger-padding-block=var(--rc-control-padding-block)] - Trigger block-axis padding\n * @cssprop [--rc-menu-button-trigger-padding-inline=var(--rc-control-padding-inline)] - Trigger inline-axis padding\n * @cssprop [--rc-menu-button-trigger-gap=var(--rc-item-gap)] - Gap between flex children in the trigger\n * @cssprop [--rc-menu-button-trigger-border=var(--rc-border)] - Trigger border\n * @cssprop [--rc-menu-button-trigger-radius=var(--rc-control-radius)] - Trigger border radius\n * @cssprop [--rc-menu-button-trigger-background=var(--rc-button-bg)] - Trigger background\n * @cssprop [--rc-menu-button-trigger-color=var(--rc-button-text)] - Trigger text color\n * @cssprop [--rc-menu-button-trigger-transition] - CSS transition applied to the trigger\n * @cssprop [--rc-menu-button-trigger-hover-background=color-mix(in srgb, Highlight 8%, transparent)] - Trigger hover background\n * @cssprop [--rc-menu-button-trigger-hover-color=inherit] - Trigger hover text color\n * @cssprop [--rc-menu-button-trigger-hover-border-color=currentColor] - Trigger hover border color\n * @cssprop [--rc-menu-button-trigger-open-background=color-mix(in srgb, Highlight 12%, transparent)] - Trigger background when the menu is open\n * @cssprop [--rc-menu-button-trigger-open-color=inherit] - Trigger text color when the menu is open\n * @cssprop [--rc-menu-button-trigger-open-border-color=currentColor] - Trigger border color when the menu is open\n * @cssprop [--rc-menu-button-indicator-size=1em] - Inline and block size of the slotted indicator\n * @cssprop [--rc-menu-button-indicator-color=currentColor] - Color of the slotted indicator\n * @cssprop [--rc-menu-button-indicator-inset=var(--rc-menu-button-trigger-padding-inline)] - Indicator distance from the trigger's inline end\n *\n * @csspart root - The root container element\n * @csspart popup - The popup container element\n *\n * @attr open - Whether the menu popup is visible. Controlled mode: host writes silently.\n * @attr default-open - Initial open state for uncontrolled mode. Ignored after the first\n * controlled write to `open`.\n * @attr orientation - Arrow-key axis for opening the menu. Inherits from a parent\n * `rc-menubar` or `[role=\"menubar\"]` when unset.\n * @attr placement - Preferred placement of the popup relative to the trigger.\n */\nexport class RCMenuButton extends LitElement {\n static styles = [menuButtonStyles];\n\n /**\n * Enables delegatesFocus so the browser routes focus() on the host element\n * to the slotted trigger button.\n */\n static override shadowRootOptions: ShadowRootInit = {\n ...LitElement.shadowRootOptions,\n\n delegatesFocus: true,\n };\n\n private _defaultOpen = false;\n private _open = false;\n private _openInitialized = false;\n\n /**\n * Whether the menu is currently open.\n *\n * In controlled mode the host owns this value; writing the property applies\n * the state silently without dispatching `rc-menu-button-toggle`.\n */\n @property({ type: Boolean, reflect: true })\n get open(): boolean {\n return this._open;\n }\n\n /** Applies open state in controlled mode without dispatching an event. */\n set open(value: boolean | undefined) {\n const oldValue = this._open;\n\n if (value === undefined) {\n return;\n }\n\n this._openInitialized = true;\n this._setOpen(value, false);\n this.requestUpdate('open', oldValue);\n }\n\n /**\n * Initial open state for uncontrolled mode.\n *\n * Ignored after the first controlled write; use `open` to update state\n * programmatically after mount.\n */\n @property({ type: Boolean, attribute: 'default-open' })\n get defaultOpen(): boolean {\n return this._defaultOpen;\n }\n\n /** Applies the uncontrolled default before any controlled write occurs. */\n set defaultOpen(value: boolean) {\n const oldValue = this._defaultOpen;\n\n this._defaultOpen = value;\n\n if (value && !this._openInitialized) {\n this._setOpen(true, false);\n }\n\n this.requestUpdate('defaultOpen', oldValue);\n }\n\n /**\n * Orientation of this menu button, affects which arrow keys open/close the menu.\n *\n * If not set, inherits from a parent rc-menubar or element with role=\"menubar\".\n */\n @property({ type: String, reflect: true })\n orientation: 'horizontal' | 'vertical' | undefined;\n\n /** Preferred placement of the popup relative to the trigger button. */\n @property({ reflect: true })\n placement: AnchorPlacement = 'bottom-start';\n\n /**\n * Popup placement adjusted for orientation.\n *\n * Switches from `bottom-start` to `right-start` when the resolved orientation\n * is `vertical`, so vertical menubars open submenus to the side.\n */\n protected get _effectivePlacement(): AnchorPlacement {\n if (this.placement !== 'bottom-start') {\n return this.placement;\n }\n\n return this._resolvedOrientation === 'vertical' ? 'right-start' : this.placement;\n }\n\n /**\n * Resolved orientation, considering inheritance from parent menubar.\n * Falls back to 'horizontal' if no orientation is set or inherited.\n */\n protected get _resolvedOrientation(): 'horizontal' | 'vertical' {\n if (this.orientation) {\n return this.orientation;\n }\n\n const $menubar = this.closest('rc-menubar, [role=\"menubar\"]');\n\n if ($menubar) {\n const orientation =\n $menubar.getAttribute('orientation') ?? $menubar.getAttribute('aria-orientation');\n\n if (orientation === 'vertical') {\n return 'vertical';\n }\n\n if (orientation === 'horizontal') {\n return 'horizontal';\n }\n }\n\n return 'horizontal';\n }\n\n /** Shadow DOM root container. Serves as the anchor element for `_anchorCtrl`. */\n @query('#root') protected _$root!: HTMLElement;\n\n /** Shadow DOM popup container. Hidden when `open` is `false`. */\n @query('#popup') protected _$popup!: HTMLElement;\n\n /** Weak reference to the slotted trigger button. */\n @state()\n protected _$trigger: WeakRef<HTMLElement> | undefined;\n\n /** Weak reference to the slotted `rc-menu` element. */\n @state()\n protected _$menu: WeakRef<RCMenu> | undefined;\n\n /** Positions the popup relative to the trigger using CSS anchor positioning. */\n protected _anchorCtrl = new AnchorController(this, {\n anchor: () => this._$root ?? null,\n floating: () => this._$popup ?? null,\n shadowHost: () => this,\n placement: 'bottom-start',\n offset: 2,\n });\n\n /** Bound handler for document click (light dismiss). Stored for `removeEventListener` pairing. */\n protected _boundHandleDocumentClick = this._handleDocumentClick.bind(this);\n\n /**\n * Watches the host's own `tabindex` attribute so the trigger button's\n * tabindex can be kept in sync.\n *\n * When a parent (e.g. rc-toolbar) places the\n * host under roving-tabindex management it sets/removes tabindex on the\n * host; we mirror that to the trigger so it doesn't become an independent\n * tab stop. When the host has no tabindex the trigger keeps its natural\n * tabindex=0 for standalone usage.\n */\n protected _tabObserver?: MutationObserver;\n\n /** Installs the tabindex mutation observer and the document-level click listener. */\n override connectedCallback() {\n super.connectedCallback();\n\n this._tabObserver = new MutationObserver(() => this._syncTriggerTabindex());\n this._tabObserver.observe(this, { attributes: true, attributeFilter: ['tabindex'] });\n\n document.addEventListener('click', this._boundHandleDocumentClick, true);\n\n if (this.defaultOpen) {\n this._setOpen(true, false);\n }\n }\n\n /** Disconnects the tabindex observer and removes the document-level click listener. */\n override disconnectedCallback() {\n this._tabObserver?.disconnect();\n this._tabObserver = undefined;\n\n super.disconnectedCallback();\n document.removeEventListener('click', this._boundHandleDocumentClick, true);\n }\n\n /**\n * Opens the menu and moves focus into it.\n *\n * @param focusTarget - which item receives initial focus when the menu opens\n */\n openMenu(focusTarget: 'first' | 'last' = 'first') {\n if (this.open) {\n return;\n }\n\n this._anchorCtrl.setOptions({ placement: this._effectivePlacement });\n this._setOpen(true, true);\n this._anchorCtrl.update();\n\n this.updateComplete.then(() => {\n const $menu = this._$menu?.deref();\n\n focusTarget === 'last' ? $menu?.focusLast() : $menu?.focusFirst();\n });\n }\n\n /**\n * Closes the menu.\n *\n * @param returnFocus - when `true`, returns focus to the trigger button after closing\n */\n closeMenu(returnFocus = true) {\n if (!this.open) {\n return;\n }\n\n this._setOpen(false, true);\n\n if (returnFocus) {\n const $trigger = this._$trigger?.deref();\n\n $trigger?.focus();\n }\n }\n\n /** Toggles the menu between open and closed. */\n toggleMenu() {\n if (this.open) {\n this.closeMenu();\n } else {\n this.openMenu();\n }\n }\n\n /** Dispatches the `rc-menu-button-toggle` bubbling composed event with the current open state. */\n protected _dispatchToggle() {\n this.dispatchEvent(\n new CustomEvent<RCMenuButtonToggleEvent>('rc-menu-button-toggle', {\n bubbles: true,\n composed: true,\n detail: { open: this.open },\n }),\n );\n }\n\n /** Caches a weak reference to the first assigned trigger element and syncs its ARIA and tabindex state. */\n protected _handleTriggerSlotChange(e: Event) {\n const $slot = e.currentTarget as HTMLSlotElement;\n const $trigger = $slot.assignedElements()[0] as HTMLElement | undefined;\n\n if ($trigger) {\n this._$trigger = new WeakRef($trigger);\n this._syncTriggerAria();\n this._syncTriggerTabindex();\n }\n }\n\n /** Tracks optional indicator content so the trigger reserves its inline-end space. */\n protected _handleIndicatorSlotChange(e: Event) {\n const $slot = e.currentTarget as HTMLSlotElement;\n\n this.toggleAttribute('has-indicator', $slot.assignedElements().length > 0);\n }\n\n /**\n * Mirrors the host's `tabindex` attribute to the trigger button.\n *\n * When a roving-tabindex parent (e.g. rc-toolbar) marks this host inactive\n * with `tabindex=\"-1\"`, the trigger must also be suppressed so it does not\n * become an independent tab stop. When the host is the active item\n * (`tabindex=\"0\"`) or standalone (no tabindex), the trigger retains its\n * natural focusability so that Chrome's delegatesFocus can route sequential\n * Tab navigation through the host to the trigger.\n */\n protected _syncTriggerTabindex() {\n const $trigger = this._$trigger?.deref();\n\n if (!$trigger) {\n return;\n }\n\n if (this.getAttribute('tabindex') === '-1') {\n $trigger.setAttribute('tabindex', '-1');\n } else {\n $trigger.removeAttribute('tabindex');\n }\n }\n\n /**\n * Overrides the default focus() so that programmatic focus calls (e.g. from\n * a roving-tabindex parent navigating back to this element via arrow keys)\n * always reach the trigger.\n *\n * Chrome's delegatesFocus will not delegate to a tabindex=\"-1\" element, so\n * when the toolbar marks this host inactive it suppresses the trigger — and\n * the next focusItem() call silently fails. Lifting the suppression here and\n * directly calling trigger.focus() bypasses that restriction.\n */\n override focus(options?: FocusOptions) {\n const $trigger = this._$trigger?.deref();\n\n if (!$trigger) {\n super.focus(options);\n\n return;\n }\n\n $trigger.removeAttribute('tabindex');\n $trigger.focus(options);\n }\n\n /** Caches a weak reference to the first assigned `rc-menu` element. */\n protected _handleMenuSlotChange(e: Event) {\n const $slot = e.currentTarget as HTMLSlotElement;\n const $elements = $slot.assignedElements();\n const $menu = $elements.find(($el) => $el.tagName === 'RC-MENU') as RCMenu | undefined;\n\n if ($menu) {\n this._$menu = new WeakRef($menu);\n }\n }\n\n /**\n * Keyboard navigation handler.\n *\n * Opens or closes the menu in response to arrow/Enter/Escape keys.\n **/\n protected _onNavigate = (action: KeyboardNavigationAction) => {\n switch (action) {\n case 'open-to-first':\n case 'activate':\n this.openMenu();\n break;\n\n case 'open-to-last':\n this.openMenu('last');\n break;\n\n case 'escape':\n this.closeMenu();\n break;\n }\n };\n\n /** Prevents the default button action and delegates to `toggleMenu`. */\n protected _handleTriggerClick(e: MouseEvent) {\n e.preventDefault();\n\n this.toggleMenu();\n }\n\n /** Closes the menu when an `rc-menu-close` event bubbles up from the popup. */\n protected _handleMenuClose() {\n this.closeMenu();\n }\n\n /** Closes the menu when an `rc-menu-activate` event bubbles up from the popup. */\n protected _handleMenuActivate() {\n this.closeMenu();\n }\n\n /** Closes the menu on clicks outside this component (light dismiss). */\n protected _handleDocumentClick(e: MouseEvent) {\n if (!this.open) {\n return;\n }\n\n const path = e.composedPath();\n\n if (path.includes(this)) {\n return;\n }\n\n this.closeMenu(false);\n }\n\n /** Syncs trigger ARIA when `open` changes; updates anchor placement when `placement` or `orientation` change. */\n protected override updated(changedProperties: Map<PropertyKey, unknown>) {\n super.updated(changedProperties);\n\n if (changedProperties.has('open')) {\n this._syncTriggerAria();\n\n // A pending update can flush after the host (and its shadow tree) has\n // already been disconnected — e.g. a framework unmounting this element\n // in the same tick as an `open` change. togglePopover() throws\n // InvalidStateError on a disconnected popover, so guard on connectivity\n // rather than letting that reach the caller.\n if (this._$popup?.isConnected) {\n this._$popup.togglePopover(this.open);\n }\n }\n\n if (changedProperties.has('placement') || changedProperties.has('orientation')) {\n this._anchorCtrl.setOptions({ placement: this._effectivePlacement });\n }\n }\n\n protected _setOpen(open: boolean, dispatch: boolean): void {\n if (this._open === open) {\n return;\n }\n\n const oldValue = this._open;\n\n this._open = open;\n\n this.requestUpdate('open', oldValue);\n this._syncTriggerAria();\n\n if (dispatch) {\n this._dispatchToggle();\n }\n }\n\n /** Writes `aria-haspopup` and `aria-expanded` to the trigger button to match the current open state. */\n protected _syncTriggerAria(): void {\n const $trigger = this._$trigger?.deref();\n\n if (!$trigger?.isConnected) {\n return;\n }\n\n $trigger.setAttribute('aria-haspopup', 'menu');\n $trigger.setAttribute('aria-expanded', String(this.open));\n }\n\n protected override render() {\n return html`\n <div id=\"root\" part=\"root\">\n <div\n id=\"trigger-wrap\"\n ${keyNavigation(this._onNavigate, {\n navigationAxis: this._resolvedOrientation,\n handleNavAxis: false,\n handleOpenAxis: true,\n handleActivate: true,\n handleEscape: this.open,\n })}\n ${keyInteraction()}\n @click=${this._handleTriggerClick}\n >\n <slot name=\"trigger\" @slotchange=${this._handleTriggerSlotChange}></slot>\n <slot\n name=\"indicator\"\n aria-hidden=\"true\"\n @slotchange=${this._handleIndicatorSlotChange}\n ></slot>\n </div>\n\n <div\n id=\"popup\"\n part=\"popup\"\n popover=\"manual\"\n @rc-menu-close=${this._handleMenuClose}\n @rc-menu-activate=${this._handleMenuActivate}\n >\n <slot @slotchange=${this._handleMenuSlotChange}></slot>\n </div>\n </div>\n `;\n }\n}\n\nexport default RCMenuButton;\n"],"names":["menuButtonStyles","css","_RCMenuButton","LitElement","AnchorController","action","value","oldValue","$menubar","orientation","focusTarget","$menu","returnFocus","e","$trigger","$slot","options","$el","changedProperties","open","dispatch","html","keyNavigation","keyInteraction","RCMenuButton","__decorateClass","property","query","state"],"mappings":"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"}
|
|
File without changes
|