@genesislcap/foundation-ui 15.58.0 → 15.58.1-FUI-2629.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/custom-elements.json +424 -327
- package/dist/dts/actions-menu/actions-menu.d.ts +34 -2
- package/dist/dts/actions-menu/actions-menu.d.ts.map +1 -1
- package/dist/dts/actions-menu/actions-menu.styles.d.ts.map +1 -1
- package/dist/dts/actions-menu/actions-menu.template.d.ts.map +1 -1
- package/dist/dts/filter-bar/filter-bar.utils.d.ts +1 -1
- package/dist/dts/react.d.ts +8 -8
- package/dist/dts/utils/popover-position.d.ts +26 -0
- package/dist/dts/utils/popover-position.d.ts.map +1 -0
- package/dist/esm/actions-menu/actions-menu.js +74 -12
- package/dist/esm/actions-menu/actions-menu.styles.js +74 -5
- package/dist/esm/actions-menu/actions-menu.template.js +49 -5
- package/dist/esm/utils/popover-position.js +70 -0
- package/dist/foundation-ui.api.json +276 -10
- package/dist/foundation-ui.d.ts +34 -3
- package/dist/react.cjs +6 -6
- package/dist/react.mjs +4 -4
- package/package.json +17 -17
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import type { IconStyle } from '@fortawesome/fontawesome-svg-core';
|
|
1
2
|
import { FoundationElement } from '@microsoft/fast-foundation';
|
|
3
|
+
import type { FaSize } from '../icon';
|
|
2
4
|
/**
|
|
3
5
|
* The Action Menu Item component.
|
|
4
6
|
* @remarks Used within the Action Menu component.
|
|
@@ -7,20 +9,37 @@ import { FoundationElement } from '@microsoft/fast-foundation';
|
|
|
7
9
|
export type ActionMenuItem = {
|
|
8
10
|
name: string | ((rowData: any) => string);
|
|
9
11
|
callback: (rowData: any) => void | any;
|
|
10
|
-
|
|
12
|
+
/** A fixed flag, or a function of the row data (the grid row from the cell params). */
|
|
13
|
+
isDisabled?: boolean | ((rowData: any) => boolean);
|
|
11
14
|
color?: string;
|
|
15
|
+
icon?: {
|
|
16
|
+
variant?: IconStyle;
|
|
17
|
+
name: string;
|
|
18
|
+
size?: FaSize;
|
|
19
|
+
};
|
|
12
20
|
};
|
|
21
|
+
/**
|
|
22
|
+
* The actions shown by the Actions Menu: a fixed array, or a function of the row data returning
|
|
23
|
+
* one (for row-scoped eligibility/permission filtering).
|
|
24
|
+
* @public
|
|
25
|
+
*/
|
|
26
|
+
export type ActionMenuItems = ActionMenuItem[] | ((rowData: any) => ActionMenuItem[]);
|
|
13
27
|
/**
|
|
14
28
|
* @tagname %%prefix%%-actions-menu
|
|
15
29
|
*/
|
|
16
30
|
export declare class ActionsMenu extends FoundationElement {
|
|
17
|
-
actions:
|
|
31
|
+
actions: ActionMenuItems;
|
|
18
32
|
isVertical: boolean;
|
|
19
33
|
addDefaultActions: boolean;
|
|
20
34
|
autoCloseOnAction: boolean;
|
|
21
35
|
classNames: string;
|
|
22
36
|
definition: any;
|
|
23
37
|
name: string;
|
|
38
|
+
/**
|
|
39
|
+
* When set, the opener renders this icon instead of the `name` text (e.g. `ellipsis`
|
|
40
|
+
* for an icon-only "kebab" opener).
|
|
41
|
+
*/
|
|
42
|
+
iconName: string;
|
|
24
43
|
open: boolean;
|
|
25
44
|
buttonAppearance: string;
|
|
26
45
|
hideDisabled: boolean;
|
|
@@ -28,12 +47,25 @@ export declare class ActionsMenu extends FoundationElement {
|
|
|
28
47
|
singleOption: ActionMenuItem;
|
|
29
48
|
actionsMenu: HTMLElement;
|
|
30
49
|
actionsOpener: HTMLElement;
|
|
50
|
+
private positionTracker?;
|
|
31
51
|
disconnectedCallback(): void;
|
|
32
52
|
private updateMenuPosition;
|
|
53
|
+
private startTrackingPosition;
|
|
54
|
+
private stopTrackingPosition;
|
|
33
55
|
protected definitionChanged(oldValue: any, newValue: any): void;
|
|
34
56
|
protected openChanged(): void;
|
|
35
57
|
toggleActionsMenuVisibility(): void;
|
|
58
|
+
/**
|
|
59
|
+
* Syncs `open` when the native `popover="auto"` light-dismiss (outside click / Escape) closes
|
|
60
|
+
* the vertical menu without going through `toggleActionsMenuVisibility()`.
|
|
61
|
+
*/
|
|
62
|
+
onPopoverToggle(event: Event): void;
|
|
63
|
+
/** Opens the icon-only opener from the keyboard, as a native button would. */
|
|
64
|
+
onIconOpenerKeydown(event: KeyboardEvent): boolean;
|
|
36
65
|
onActionMenuItemClick(callback: (rowData: any) => void | any): void;
|
|
66
|
+
/** Resolves an action's `isDisabled` flag or row-data function for the current row. */
|
|
67
|
+
isActionDisabled(action: ActionMenuItem): boolean;
|
|
68
|
+
get resolvedActions(): ActionMenuItem[];
|
|
37
69
|
get allActions(): ActionMenuItem[];
|
|
38
70
|
get rowData(): any;
|
|
39
71
|
getLabel(name: string | ((rowData: any) => string)): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions-menu.d.ts","sourceRoot":"","sources":["../../../src/actions-menu/actions-menu.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"actions-menu.d.ts","sourceRoot":"","sources":["../../../src/actions-menu/actions-menu.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAEnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAE/D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAStC;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,GAAG,KAAK,MAAM,CAAC,CAAC;IAC1C,QAAQ,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,GAAG,GAAG,CAAC;IACvC,uFAAuF;IACvF,UAAU,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,OAAO,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE;QACL,OAAO,CAAC,EAAE,SAAS,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;CACH,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,cAAc,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,GAAG,KAAK,cAAc,EAAE,CAAC,CAAC;AAEtF;;GAEG;AACH,qBAAa,WAAY,SAAQ,iBAAiB;IACpC,OAAO,EAAE,eAAe,CAAC;IACgB,UAAU,EAAE,OAAO,CAAS;IACpB,iBAAiB,EAAE,OAAO,CAAQ;IACjC,iBAAiB,EAAE,OAAO,CAAQ;IACpF,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,GAAG,CAAC;IACtB,IAAI,SAAa;IACvB;;;OAGG;IAC+B,QAAQ,EAAE,MAAM,CAAC;IACL,IAAI,EAAE,OAAO,CAAS;IAC9D,gBAAgB,EAAE,MAAM,CAAC;IACwB,YAAY,EAAE,OAAO,CAAS;IACpB,oBAAoB,EAAE,OAAO,CACtF;IACI,YAAY,EAAE,cAAc,CAAC;IAEzC,WAAW,EAAG,WAAW,CAAC;IAC1B,aAAa,EAAG,WAAW,CAAC;IAE5B,OAAO,CAAC,eAAe,CAAC,CAAiC;IAEzD,oBAAoB,IAAI,IAAI;IAQ5B,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,qBAAqB;IAS7B,OAAO,CAAC,oBAAoB;IAK5B,SAAS,CAAC,iBAAiB,CAAC,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG;IA0CxD,SAAS,CAAC,WAAW;IAerB,2BAA2B;IAI3B;;;OAGG;IACH,eAAe,CAAC,KAAK,EAAE,KAAK;IAO5B,8EAA8E;IAC9E,mBAAmB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO;IAMlD,qBAAqB,CAAC,QAAQ,EAAE,CAAC,OAAO,KAAA,KAAK,IAAI,GAAG,GAAG;IAKvD,uFAAuF;IACvF,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO;IAKjD,IAAI,eAAe,IAAI,cAAc,EAAE,CAGtC;IAED,IAAI,UAAU,IAAI,cAAc,EAAE,CAWjC;IAED,IAAI,OAAO,QAKV;IAED,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,GAAG,KAAK,MAAM,CAAC;IAQlD,WAAW,CAAC,MAAM,EAAE,MAAM;CAyB3B;AAED;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,2TAIhC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions-menu.styles.d.ts","sourceRoot":"","sources":["../../../src/actions-menu/actions-menu.styles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,KAAK,EACV,wBAAwB,EACxB,2BAA2B,EAC5B,MAAM,4BAA4B,CAAC;AAEpC,eAAO,MAAM,qBAAqB,GAChC,SAAS,wBAAwB,EACjC,YAAY,2BAA2B,KACtC,
|
|
1
|
+
{"version":3,"file":"actions-menu.styles.d.ts","sourceRoot":"","sources":["../../../src/actions-menu/actions-menu.styles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,KAAK,EACV,wBAAwB,EACxB,2BAA2B,EAC5B,MAAM,4BAA4B,CAAC;AAEpC,eAAO,MAAM,qBAAqB,GAChC,SAAS,wBAAwB,EACjC,YAAY,2BAA2B,KACtC,aAiKF,CAAC;AAEF,eAAO,MAAM,2BAA2B,GACtC,SAAS,wBAAwB,EACjC,YAAY,2BAA2B,KACtC,aAEF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions-menu.template.d.ts","sourceRoot":"","sources":["../../../src/actions-menu/actions-menu.template.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAG9E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"actions-menu.template.d.ts","sourceRoot":"","sources":["../../../src/actions-menu/actions-menu.template.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAG9E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAwClD,eAAO,MAAM,YAAY,GAAI,QAAQ,MAAM,mCAiE1C,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,QAAQ,MAAM,mCAclD,CAAC;AAEF,eAAO,MAAM,6BAA6B,EAAE,YAAY,CAAC,WAAW,CAOnE,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const mapType: (TYPE: string) => "boolean" | "number" | "
|
|
1
|
+
export declare const mapType: (TYPE: string) => "boolean" | "number" | "text" | "date" | "enum";
|
|
2
2
|
//# sourceMappingURL=filter-bar.utils.d.ts.map
|
package/dist/dts/react.d.ts
CHANGED
|
@@ -133,14 +133,14 @@ interface HTMLWCProps extends React.AriaAttributes {
|
|
|
133
133
|
onInput?(e: Event): void;
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
export declare const
|
|
136
|
+
export declare const Accordion: React.ForwardRefExoticComponent<
|
|
137
137
|
React.PropsWithChildren<
|
|
138
|
-
Omit<PublicOf<
|
|
138
|
+
Omit<PublicOf<AccordionWC>, 'children' | 'style'> &
|
|
139
139
|
HTMLWCProps & {
|
|
140
140
|
}
|
|
141
|
-
> & React.RefAttributes<
|
|
141
|
+
> & React.RefAttributes<AccordionWC>
|
|
142
142
|
>;
|
|
143
|
-
export type
|
|
143
|
+
export type AccordionRef = AccordionWC;
|
|
144
144
|
|
|
145
145
|
export declare const ActionsMenu: React.ForwardRefExoticComponent<
|
|
146
146
|
React.PropsWithChildren<
|
|
@@ -151,14 +151,14 @@ export declare const ActionsMenu: React.ForwardRefExoticComponent<
|
|
|
151
151
|
>;
|
|
152
152
|
export type ActionsMenuRef = ActionsMenuWC;
|
|
153
153
|
|
|
154
|
-
export declare const
|
|
154
|
+
export declare const AccordionItem: React.ForwardRefExoticComponent<
|
|
155
155
|
React.PropsWithChildren<
|
|
156
|
-
Omit<PublicOf<
|
|
156
|
+
Omit<PublicOf<AccordionItemWC>, 'children' | 'style'> &
|
|
157
157
|
HTMLWCProps & {
|
|
158
158
|
}
|
|
159
|
-
> & React.RefAttributes<
|
|
159
|
+
> & React.RefAttributes<AccordionItemWC>
|
|
160
160
|
>;
|
|
161
|
-
export type
|
|
161
|
+
export type AccordionItemRef = AccordionItemWC;
|
|
162
162
|
|
|
163
163
|
export declare const AiCriteriaSearch: React.ForwardRefExoticComponent<
|
|
164
164
|
React.PropsWithChildren<
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Walks up from `element`, crossing shadow-root boundaries via `.host`, collecting every
|
|
3
|
+
* scrollable ancestor (including the anchor's own document).
|
|
4
|
+
* @remarks Native `scroll` events are not `composed`, so they don't cross shadow-DOM boundaries
|
|
5
|
+
* the way `click`/`keydown` do — a listener on `document` never sees a shadow-DOM-nested
|
|
6
|
+
* viewport's own scroll. Callers must listen on each returned ancestor directly.
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
export declare function findScrollableAncestors(element: HTMLElement): (HTMLElement | Document)[];
|
|
10
|
+
/**
|
|
11
|
+
* Keeps a Popover-API element anchored to its trigger while any of the trigger's scrollable
|
|
12
|
+
* ancestors scroll, and reports back when the trigger has been removed from the DOM (e.g. AG
|
|
13
|
+
* Grid row virtualization recycling the row that owns it).
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
export declare class AnchoredPopoverPositionTracker {
|
|
17
|
+
private readonly anchor;
|
|
18
|
+
private readonly onReposition;
|
|
19
|
+
private readonly onAnchorDetached;
|
|
20
|
+
private ancestors;
|
|
21
|
+
private readonly handleScroll;
|
|
22
|
+
constructor(anchor: HTMLElement, onReposition: () => void, onAnchorDetached: () => void);
|
|
23
|
+
start(): void;
|
|
24
|
+
stop(): void;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=popover-position.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"popover-position.d.ts","sourceRoot":"","sources":["../../../src/utils/popover-position.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,WAAW,GAAG,CAAC,WAAW,GAAG,QAAQ,CAAC,EAAE,CA8BxF;AAED;;;;;GAKG;AACH,qBAAa,8BAA8B;IAYvC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IAbnC,OAAO,CAAC,SAAS,CAAkC;IAEnD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAM3B;gBAGiB,MAAM,EAAE,WAAW,EACnB,YAAY,EAAE,MAAM,IAAI,EACxB,gBAAgB,EAAE,MAAM,IAAI;IAG/C,KAAK,IAAI,IAAI;IAQb,IAAI,IAAI,IAAI;CAMb"}
|
|
@@ -2,6 +2,7 @@ import { __decorate } from "tslib";
|
|
|
2
2
|
import { attr, observable } from '@microsoft/fast-element';
|
|
3
3
|
import { FoundationElement } from '@microsoft/fast-foundation';
|
|
4
4
|
import { classNames } from '@microsoft/fast-web-utilities';
|
|
5
|
+
import { AnchoredPopoverPositionTracker } from '../utils/popover-position';
|
|
5
6
|
import { foundationActionsMenuStyles as styles } from './actions-menu.styles';
|
|
6
7
|
import { singleOptionTemplate, menuTemplate, foundationActionsMenuTemplate as template, } from './actions-menu.template';
|
|
7
8
|
/**
|
|
@@ -20,6 +21,7 @@ export class ActionsMenu extends FoundationElement {
|
|
|
20
21
|
}
|
|
21
22
|
disconnectedCallback() {
|
|
22
23
|
var _a;
|
|
24
|
+
this.stopTrackingPosition();
|
|
23
25
|
if ((_a = this.actionsMenu) === null || _a === void 0 ? void 0 : _a.matches(':popover-open')) {
|
|
24
26
|
this.actionsMenu.hidePopover();
|
|
25
27
|
}
|
|
@@ -28,13 +30,25 @@ export class ActionsMenu extends FoundationElement {
|
|
|
28
30
|
updateMenuPosition() {
|
|
29
31
|
const rect = this.actionsOpener.getBoundingClientRect();
|
|
30
32
|
this.actionsMenu.style.position = 'fixed';
|
|
31
|
-
|
|
33
|
+
// The vertical menu drops down below its opener; the horizontal one overlays it.
|
|
34
|
+
this.actionsMenu.style.top = `${this.isVertical ? rect.bottom : rect.top}px`;
|
|
32
35
|
this.actionsMenu.style.left = 'auto';
|
|
33
36
|
this.actionsMenu.style.right = `${window.innerWidth - rect.right}px`;
|
|
34
37
|
}
|
|
38
|
+
startTrackingPosition() {
|
|
39
|
+
this.positionTracker = new AnchoredPopoverPositionTracker(this.actionsOpener, () => this.updateMenuPosition(), () => (this.open = false));
|
|
40
|
+
this.positionTracker.start();
|
|
41
|
+
}
|
|
42
|
+
stopTrackingPosition() {
|
|
43
|
+
var _a;
|
|
44
|
+
(_a = this.positionTracker) === null || _a === void 0 ? void 0 : _a.stop();
|
|
45
|
+
this.positionTracker = undefined;
|
|
46
|
+
}
|
|
35
47
|
definitionChanged(oldValue, newValue) {
|
|
36
48
|
var _a;
|
|
37
|
-
|
|
49
|
+
if (!newValue)
|
|
50
|
+
return;
|
|
51
|
+
this.actions = (_a = newValue.actions) !== null && _a !== void 0 ? _a : [];
|
|
38
52
|
delete this.definition.actions;
|
|
39
53
|
if (newValue.buttonText) {
|
|
40
54
|
this.name = newValue.buttonText;
|
|
@@ -44,6 +58,18 @@ export class ActionsMenu extends FoundationElement {
|
|
|
44
58
|
this.isVertical = newValue.isVertical;
|
|
45
59
|
delete this.definition.isVertical;
|
|
46
60
|
}
|
|
61
|
+
if (newValue.iconName) {
|
|
62
|
+
this.iconName = newValue.iconName;
|
|
63
|
+
delete this.definition.iconName;
|
|
64
|
+
}
|
|
65
|
+
if (newValue.addDefaultActions !== undefined) {
|
|
66
|
+
this.addDefaultActions = newValue.addDefaultActions;
|
|
67
|
+
delete this.definition.addDefaultActions;
|
|
68
|
+
}
|
|
69
|
+
if (newValue.hideDisabled !== undefined) {
|
|
70
|
+
this.hideDisabled = newValue.hideDisabled;
|
|
71
|
+
delete this.definition.hideDisabled;
|
|
72
|
+
}
|
|
47
73
|
if (newValue.buttonAppearance) {
|
|
48
74
|
this.buttonAppearance = newValue.buttonAppearance;
|
|
49
75
|
delete this.definition.buttonAppearance;
|
|
@@ -59,28 +85,59 @@ export class ActionsMenu extends FoundationElement {
|
|
|
59
85
|
if (this.open) {
|
|
60
86
|
this.updateMenuPosition();
|
|
61
87
|
this.actionsMenu.showPopover();
|
|
88
|
+
this.startTrackingPosition();
|
|
62
89
|
}
|
|
63
|
-
else
|
|
64
|
-
this.
|
|
90
|
+
else {
|
|
91
|
+
this.stopTrackingPosition();
|
|
92
|
+
if ((_a = this.actionsMenu) === null || _a === void 0 ? void 0 : _a.matches(':popover-open')) {
|
|
93
|
+
this.actionsMenu.hidePopover();
|
|
94
|
+
}
|
|
65
95
|
}
|
|
66
96
|
}
|
|
67
97
|
toggleActionsMenuVisibility() {
|
|
68
98
|
this.open = !this.open;
|
|
69
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Syncs `open` when the native `popover="auto"` light-dismiss (outside click / Escape) closes
|
|
102
|
+
* the vertical menu without going through `toggleActionsMenuVisibility()`.
|
|
103
|
+
*/
|
|
104
|
+
onPopoverToggle(event) {
|
|
105
|
+
const newState = event.newState;
|
|
106
|
+
if (newState) {
|
|
107
|
+
this.open = newState === 'open';
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/** Opens the icon-only opener from the keyboard, as a native button would. */
|
|
111
|
+
onIconOpenerKeydown(event) {
|
|
112
|
+
if (event.key !== 'Enter' && event.key !== ' ')
|
|
113
|
+
return true;
|
|
114
|
+
this.toggleActionsMenuVisibility();
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
70
117
|
onActionMenuItemClick(callback) {
|
|
71
118
|
if (this.autoCloseOnAction)
|
|
72
119
|
this.open = false;
|
|
73
120
|
callback(this.rowData);
|
|
74
121
|
}
|
|
122
|
+
/** Resolves an action's `isDisabled` flag or row-data function for the current row. */
|
|
123
|
+
isActionDisabled(action) {
|
|
124
|
+
const { isDisabled } = action;
|
|
125
|
+
return typeof isDisabled === 'function' ? !!isDisabled(this.rowData) : !!isDisabled;
|
|
126
|
+
}
|
|
127
|
+
get resolvedActions() {
|
|
128
|
+
const actions = typeof this.actions === 'function' ? this.actions(this.rowData) : this.actions;
|
|
129
|
+
return actions !== null && actions !== void 0 ? actions : [];
|
|
130
|
+
}
|
|
75
131
|
get allActions() {
|
|
76
|
-
var _a;
|
|
77
132
|
const defaultActions = [
|
|
78
133
|
{
|
|
79
134
|
name: '✖',
|
|
80
135
|
callback: () => (this.open = false),
|
|
81
136
|
},
|
|
82
137
|
];
|
|
83
|
-
return this.addDefaultActions
|
|
138
|
+
return this.addDefaultActions
|
|
139
|
+
? [...this.resolvedActions, ...defaultActions]
|
|
140
|
+
: this.resolvedActions;
|
|
84
141
|
}
|
|
85
142
|
get rowData() {
|
|
86
143
|
if (!this.definition)
|
|
@@ -95,15 +152,17 @@ export class ActionsMenu extends FoundationElement {
|
|
|
95
152
|
return name;
|
|
96
153
|
}
|
|
97
154
|
getTemplate(prefix) {
|
|
155
|
+
const enabledRows = this.resolvedActions.filter((action) => !this.isActionDisabled(action));
|
|
156
|
+
// The vertical menu hides its opener entirely rather than open onto nothing actionable.
|
|
157
|
+
const hasVisibleActions = this.hideDisabled
|
|
158
|
+
? enabledRows.length > 0
|
|
159
|
+
: this.resolvedActions.length > 0;
|
|
160
|
+
if (this.isVertical && !hasVisibleActions) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
98
163
|
if (!this.hideMenuSingleOption) {
|
|
99
164
|
return menuTemplate(prefix);
|
|
100
165
|
}
|
|
101
|
-
const enabledRows = this.actions.filter((action) => {
|
|
102
|
-
if (!action.isDisabled) {
|
|
103
|
-
return true;
|
|
104
|
-
}
|
|
105
|
-
return !action.isDisabled(this.rowData);
|
|
106
|
-
});
|
|
107
166
|
this.singleOption = null;
|
|
108
167
|
if (enabledRows.length === 0) {
|
|
109
168
|
return;
|
|
@@ -136,6 +195,9 @@ __decorate([
|
|
|
136
195
|
__decorate([
|
|
137
196
|
attr
|
|
138
197
|
], ActionsMenu.prototype, "name", void 0);
|
|
198
|
+
__decorate([
|
|
199
|
+
attr({ attribute: 'icon-name' })
|
|
200
|
+
], ActionsMenu.prototype, "iconName", void 0);
|
|
139
201
|
__decorate([
|
|
140
202
|
attr({ attribute: 'open', mode: 'boolean' })
|
|
141
203
|
], ActionsMenu.prototype, "open", void 0);
|
|
@@ -21,10 +21,17 @@ export const actionsMenuBaseStyles = (context, definition) => css `
|
|
|
21
21
|
margin: 0;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
/* The vertical menu follows AG Grid's context menu (ag-menu / ag-menu-list / ag-menu-option),
|
|
25
|
+
so it matches the grid it usually sits in. Outside a grid the --ag-* vars are unset and the
|
|
26
|
+
design system's own tokens apply. */
|
|
24
27
|
.actions-vertical .actions-menu {
|
|
25
|
-
padding:
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
padding: var(--ag-spacing, 4px) 0;
|
|
29
|
+
background-color: var(--ag-menu-background-color, var(--fill-color));
|
|
30
|
+
border: var(--ag-menu-border, calc(var(--stroke-width) * 1px) solid var(--neutral-stroke-rest));
|
|
31
|
+
border-radius: var(--ag-border-radius, calc(var(--control-corner-radius) * 1px));
|
|
32
|
+
box-shadow: var(--ag-menu-shadow, var(--ag-popup-shadow, 0 2px 8px rgb(0 0 0 / 30%)));
|
|
33
|
+
color: var(--ag-menu-text-color, var(--neutral-foreground-rest));
|
|
34
|
+
font-family: var(--ag-font-family, var(--body-font));
|
|
28
35
|
}
|
|
29
36
|
|
|
30
37
|
.actions-menu:not(.hidden):hover {
|
|
@@ -48,6 +55,31 @@ export const actionsMenuBaseStyles = (context, definition) => css `
|
|
|
48
55
|
);
|
|
49
56
|
}
|
|
50
57
|
|
|
58
|
+
:host([icon-name]) .actions-container {
|
|
59
|
+
justify-content: center;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/* The icon-only opener mirrors grid-pro's icon renderer: a bare icon with a hover chip. */
|
|
63
|
+
.actions-opener.icon-only {
|
|
64
|
+
align-items: center;
|
|
65
|
+
justify-content: center;
|
|
66
|
+
height: auto;
|
|
67
|
+
padding: 5px;
|
|
68
|
+
border-radius: 5px;
|
|
69
|
+
line-height: 1;
|
|
70
|
+
color: inherit;
|
|
71
|
+
cursor: pointer;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.actions-opener.icon-only:hover,
|
|
75
|
+
.actions-opener.icon-only.opened {
|
|
76
|
+
background-color: var(--neutral-stroke-hover);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.actions-opener.icon-only:focus-visible {
|
|
80
|
+
outline: calc(var(--focus-stroke-width) * 1px) solid var(--accent-fill-rest);
|
|
81
|
+
}
|
|
82
|
+
|
|
51
83
|
svg {
|
|
52
84
|
width: 100%;
|
|
53
85
|
height: 100%;
|
|
@@ -80,10 +112,47 @@ export const actionsMenuBaseStyles = (context, definition) => css `
|
|
|
80
112
|
min-height: 0;
|
|
81
113
|
}
|
|
82
114
|
|
|
115
|
+
/* The open menu is a flex column, so a flex-basis would override the AG row height. */
|
|
83
116
|
.actions-vertical .menu-item {
|
|
84
|
-
flex:
|
|
117
|
+
flex: none;
|
|
118
|
+
box-sizing: border-box;
|
|
119
|
+
height: calc(var(--ag-icon-size, 16px) + (var(--ag-spacing, 4px) + 2px) * 2);
|
|
120
|
+
max-height: none;
|
|
121
|
+
margin: 0;
|
|
122
|
+
background: transparent;
|
|
123
|
+
border: none;
|
|
124
|
+
border-radius: 0;
|
|
125
|
+
color: inherit;
|
|
126
|
+
font-family: inherit;
|
|
127
|
+
font-size: var(--ag-font-size, var(--type-ramp-base-font-size));
|
|
128
|
+
font-weight: 500;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.actions-vertical .menu-item:hover,
|
|
132
|
+
.actions-vertical .menu-item:focus {
|
|
133
|
+
background: var(--ag-row-hover-color, var(--neutral-fill-stealth-hover));
|
|
134
|
+
border: none;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.actions-vertical .menu-item[disabled] {
|
|
138
|
+
background: transparent;
|
|
139
|
+
opacity: 50%;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.actions-vertical .menu-item::part(start) {
|
|
143
|
+
padding-left: calc(var(--ag-spacing, 4px) * 2);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.actions-vertical .menu-item [slot='start'] {
|
|
85
147
|
justify-content: center;
|
|
86
|
-
|
|
148
|
+
width: var(--ag-icon-size, 16px);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/* AG's trailing shortcut and popup-pointer cells add 2 more spacings on the right. */
|
|
152
|
+
.actions-vertical .menu-item::part(content) {
|
|
153
|
+
margin-inline: 0;
|
|
154
|
+
padding-inline: calc(var(--ag-spacing, 4px) * 2) calc(var(--ag-spacing, 4px) * 4);
|
|
155
|
+
line-height: var(--ag-icon-size, 16px);
|
|
87
156
|
}
|
|
88
157
|
|
|
89
158
|
.actions-vertical .visible,
|
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
import { html, ref, repeat, when } from '@microsoft/fast-element';
|
|
2
2
|
import { getPrefix } from '../utils';
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* A bare icon opener (e.g. a "kebab"), styled like grid-pro's icon renderer rather than a button.
|
|
5
|
+
*/
|
|
6
|
+
const iconOpenerTemplate = (prefix) => html `
|
|
7
|
+
<div
|
|
8
|
+
${ref('actionsOpener')}
|
|
9
|
+
class="actions-opener icon-only${(x) => (x.open ? ' opened' : '')}"
|
|
10
|
+
part="icon-opener"
|
|
11
|
+
role="button"
|
|
12
|
+
tabindex="0"
|
|
13
|
+
aria-label="${(x) => x.name}"
|
|
14
|
+
aria-haspopup="menu"
|
|
15
|
+
aria-expanded="${(x) => String(x.open)}"
|
|
16
|
+
@click=${(x) => x.toggleActionsMenuVisibility()}
|
|
17
|
+
@keydown=${(x, c) => x.onIconOpenerKeydown(c.event)}
|
|
18
|
+
>
|
|
19
|
+
<${prefix}-icon name="${(x) => x.iconName}" size="lg"></${prefix}-icon>
|
|
20
|
+
</div>
|
|
21
|
+
`;
|
|
22
|
+
const buttonOpenerTemplate = (prefix) => html `
|
|
4
23
|
<${prefix}-button
|
|
5
24
|
${ref('actionsOpener')}
|
|
6
25
|
id="actiosnMenuTrigger"
|
|
@@ -15,25 +34,50 @@ export const menuTemplate = (prefix) => html `
|
|
|
15
34
|
${x.name}
|
|
16
35
|
`}
|
|
17
36
|
</${prefix}-button>
|
|
18
|
-
|
|
37
|
+
`;
|
|
38
|
+
export const menuTemplate = (prefix) => html `
|
|
39
|
+
${(x) => (x.iconName ? iconOpenerTemplate(prefix) : buttonOpenerTemplate(prefix))}
|
|
40
|
+
<${prefix}-menu
|
|
41
|
+
${ref('actionsMenu')}
|
|
42
|
+
popover="${(x) => (x.isVertical ? 'auto' : 'manual')}"
|
|
43
|
+
class="actions-menu ${(x) => x.classNames}"
|
|
44
|
+
part="actions-menu"
|
|
45
|
+
@toggle=${(x, c) => x.onPopoverToggle(c.event)}
|
|
46
|
+
>
|
|
19
47
|
${repeat((x) => x.allActions, html `
|
|
20
|
-
${when((x, context) =>
|
|
48
|
+
${when((x, context) => context.parent.isActionDisabled(x), html `
|
|
21
49
|
<${prefix}-menu-item
|
|
22
50
|
class="menu-item"
|
|
23
51
|
tabindex="${(x, context) => context.index}"
|
|
24
52
|
disabled
|
|
25
53
|
style=${(x, ctx) => (ctx.parent.hideDisabled ? 'display:none' : '')}
|
|
26
54
|
>
|
|
55
|
+
${when((x) => x.icon, html `
|
|
56
|
+
<${prefix}-icon
|
|
57
|
+
name=${(x) => x.icon.name}
|
|
58
|
+
size=${(x) => x.icon.size}
|
|
59
|
+
variant=${(x) => x.icon.variant}
|
|
60
|
+
slot="start"
|
|
61
|
+
></${prefix}-icon>
|
|
62
|
+
`)}
|
|
27
63
|
${(x, ctx) => ctx.parent.getLabel(x.name)}
|
|
28
64
|
</${prefix}-menu-item>
|
|
29
65
|
`)}
|
|
30
|
-
${when((x, context) => !
|
|
66
|
+
${when((x, context) => !context.parent.isActionDisabled(x), html `
|
|
31
67
|
<${prefix}-menu-item
|
|
32
68
|
class="menu-item"
|
|
33
69
|
tabindex="${(x, context) => context.index}"
|
|
34
70
|
@click=${(x, context) => context.parent.onActionMenuItemClick(x.callback)}
|
|
35
71
|
style="${(x) => (x.color ? `color: ${x.color};` : '')}"
|
|
36
72
|
>
|
|
73
|
+
${when((x) => x.icon, html `
|
|
74
|
+
<${prefix}-icon
|
|
75
|
+
name=${(x) => x.icon.name}
|
|
76
|
+
size=${(x) => x.icon.size}
|
|
77
|
+
variant=${(x) => x.icon.variant}
|
|
78
|
+
slot="start"
|
|
79
|
+
></${prefix}-icon>
|
|
80
|
+
`)}
|
|
37
81
|
${(x, ctx) => ctx.parent.getLabel(x.name)}
|
|
38
82
|
</${prefix}-menu-item>
|
|
39
83
|
`)}
|
|
@@ -49,7 +93,7 @@ export const singleOptionTemplate = (prefix) => html `
|
|
|
49
93
|
return x === null || x === void 0 ? void 0 : x.singleOption.callback(x.rowData);
|
|
50
94
|
}}
|
|
51
95
|
?disabled=${(x) => {
|
|
52
|
-
return
|
|
96
|
+
return x.isActionDisabled(x.singleOption);
|
|
53
97
|
}}
|
|
54
98
|
>
|
|
55
99
|
${(x) => x.getLabel(x === null || x === void 0 ? void 0 : x.singleOption.name)}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Walks up from `element`, crossing shadow-root boundaries via `.host`, collecting every
|
|
3
|
+
* scrollable ancestor (including the anchor's own document).
|
|
4
|
+
* @remarks Native `scroll` events are not `composed`, so they don't cross shadow-DOM boundaries
|
|
5
|
+
* the way `click`/`keydown` do — a listener on `document` never sees a shadow-DOM-nested
|
|
6
|
+
* viewport's own scroll. Callers must listen on each returned ancestor directly.
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
export function findScrollableAncestors(element) {
|
|
10
|
+
var _a;
|
|
11
|
+
const ancestors = [];
|
|
12
|
+
let node = element.parentNode;
|
|
13
|
+
while (node) {
|
|
14
|
+
if (node instanceof ShadowRoot) {
|
|
15
|
+
node = node.host;
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
if (node instanceof Document) {
|
|
19
|
+
ancestors.push(node);
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
if (node instanceof HTMLElement) {
|
|
23
|
+
const style = (_a = node.ownerDocument.defaultView) === null || _a === void 0 ? void 0 : _a.getComputedStyle(node);
|
|
24
|
+
if (!style) {
|
|
25
|
+
node = node.parentNode;
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (/(auto|scroll|overlay)/.test(style.overflowY) ||
|
|
29
|
+
/(auto|scroll|overlay)/.test(style.overflowX)) {
|
|
30
|
+
ancestors.push(node);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
node = node.parentNode;
|
|
34
|
+
}
|
|
35
|
+
return ancestors;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Keeps a Popover-API element anchored to its trigger while any of the trigger's scrollable
|
|
39
|
+
* ancestors scroll, and reports back when the trigger has been removed from the DOM (e.g. AG
|
|
40
|
+
* Grid row virtualization recycling the row that owns it).
|
|
41
|
+
* @internal
|
|
42
|
+
*/
|
|
43
|
+
export class AnchoredPopoverPositionTracker {
|
|
44
|
+
constructor(anchor, onReposition, onAnchorDetached) {
|
|
45
|
+
this.anchor = anchor;
|
|
46
|
+
this.onReposition = onReposition;
|
|
47
|
+
this.onAnchorDetached = onAnchorDetached;
|
|
48
|
+
this.ancestors = [];
|
|
49
|
+
this.handleScroll = () => {
|
|
50
|
+
if (!this.anchor.isConnected) {
|
|
51
|
+
this.onAnchorDetached();
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
this.onReposition();
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
start() {
|
|
58
|
+
this.stop();
|
|
59
|
+
this.ancestors = findScrollableAncestors(this.anchor);
|
|
60
|
+
for (const ancestor of this.ancestors) {
|
|
61
|
+
ancestor.addEventListener('scroll', this.handleScroll, { passive: true });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
stop() {
|
|
65
|
+
for (const ancestor of this.ancestors) {
|
|
66
|
+
ancestor.removeEventListener('scroll', this.handleScroll);
|
|
67
|
+
}
|
|
68
|
+
this.ancestors = [];
|
|
69
|
+
}
|
|
70
|
+
}
|