@cloudscape-design/components 3.0.709 → 3.0.711
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/app-layout/visual-refresh-toolbar/skeleton/styles.css.js +16 -16
- package/app-layout/visual-refresh-toolbar/skeleton/styles.scoped.css +28 -31
- package/app-layout/visual-refresh-toolbar/skeleton/styles.selectors.js +16 -16
- package/app-layout/visual-refresh-toolbar/toolbar/index.d.ts.map +1 -1
- package/app-layout/visual-refresh-toolbar/toolbar/index.js +20 -1
- package/app-layout/visual-refresh-toolbar/toolbar/index.js.map +1 -1
- package/button/internal.d.ts +2 -0
- package/button/internal.d.ts.map +1 -1
- package/button/internal.js +2 -2
- package/button/internal.js.map +1 -1
- package/button-dropdown/interfaces.d.ts +1 -1
- package/button-dropdown/interfaces.js.map +1 -1
- package/button-group/icon-button-item.d.ts +12 -0
- package/button-group/icon-button-item.d.ts.map +1 -0
- package/button-group/icon-button-item.js +21 -0
- package/button-group/icon-button-item.js.map +1 -0
- package/button-group/index.d.ts +6 -0
- package/button-group/index.d.ts.map +1 -0
- package/button-group/index.js +24 -0
- package/button-group/index.js.map +1 -0
- package/button-group/interfaces.d.ts +111 -0
- package/button-group/interfaces.d.ts.map +1 -0
- package/button-group/interfaces.js +4 -0
- package/button-group/interfaces.js.map +1 -0
- package/button-group/internal.d.ts +5 -0
- package/button-group/internal.d.ts.map +1 -0
- package/button-group/internal.js +123 -0
- package/button-group/internal.js.map +1 -0
- package/button-group/item-element.d.ts +20 -0
- package/button-group/item-element.d.ts.map +1 -0
- package/button-group/item-element.js +74 -0
- package/button-group/item-element.js.map +1 -0
- package/button-group/menu-dropdown-item.d.ts +13 -0
- package/button-group/menu-dropdown-item.d.ts.map +1 -0
- package/button-group/menu-dropdown-item.js +20 -0
- package/button-group/menu-dropdown-item.js.map +1 -0
- package/button-group/styles.css.js +9 -0
- package/button-group/styles.scoped.css +149 -0
- package/button-group/styles.selectors.js +10 -0
- package/button-group/test-classes/styles.css.js +10 -0
- package/button-group/test-classes/styles.scoped.css +23 -0
- package/button-group/test-classes/styles.selectors.js +11 -0
- package/index.d.ts +1 -0
- package/index.d.ts.map +1 -1
- package/index.js +1 -0
- package/index.js.map +1 -1
- package/internal/components/dropdown/interfaces.d.ts +1 -1
- package/internal/components/dropdown/interfaces.js.map +1 -1
- package/internal/context/single-tab-stop-navigation-context.js +1 -1
- package/internal/context/single-tab-stop-navigation-context.js.map +1 -1
- package/internal/environment.js +1 -1
- package/internal/environment.json +1 -1
- package/internal/manifest.json +1 -1
- package/package.json +2 -1
- package/test-utils/dom/button-group/index.d.ts +22 -0
- package/test-utils/dom/button-group/index.js +42 -0
- package/test-utils/dom/button-group/index.js.map +1 -0
- package/test-utils/dom/index.d.ts +3 -0
- package/test-utils/dom/index.js +10 -2
- package/test-utils/dom/index.js.map +1 -1
- package/test-utils/selectors/button-group/index.d.ts +22 -0
- package/test-utils/selectors/button-group/index.js +42 -0
- package/test-utils/selectors/button-group/index.js.map +1 -0
- package/test-utils/selectors/index.d.ts +3 -0
- package/test-utils/selectors/index.js +10 -2
- package/test-utils/selectors/index.js.map +1 -1
- package/test-utils/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icon-button-item.js","sourceRoot":"","sources":["../../../src/button-group/icon-button-item.tsx"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,sCAAsC;AACtC,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,QAAQ,EAAE,MAAM,+CAA+C,CAAC;AAGzE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,UAAU,MAAM,6CAA6C,CAAC;AACrE,OAAO,OAAO,MAAM,yCAAyC,CAAC;AAI9D,OAAO,cAAc,MAAM,8BAA8B,CAAC;AAE1D,MAAM,cAAc,GAAG,UAAU,CAC/B,CACE,EACE,IAAI,EACJ,WAAW,EACX,YAAY,EACZ,WAAW,GAMZ,EACD,GAA+B,EAC/B,EAAE;IACF,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAiB,IAAI,CAAC,CAAC;IACxD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC;IAE9D,IAAI,CAAC,OAAO,EAAE;QACZ,QAAQ,CAAC,aAAa,EAAE,kCAAkC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;KACtE;IAED,OAAO,CACL,6BAAK,GAAG,EAAE,YAAY;QACpB,oBAAC,cAAc,IACb,OAAO,EAAC,MAAM,EACd,OAAO,EAAE,IAAI,CAAC,OAAO,EACrB,WAAW,EAAE,IAAI,CAAC,WAAW,EAC7B,QAAQ,EAAE,IAAI,CAAC,QAAQ,EACvB,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,EAC3C,OAAO,EAAE,IAAI,CAAC,IAAI,EAClB,OAAO,EAAE,IAAI,CAAC,OAAO,EACrB,SAAS,EAAE,IAAI,CAAC,IAAI,EACpB,OAAO,EAAE,WAAW,EACpB,GAAG,EAAE,GAAG,iBACK,IAAI,CAAC,EAAE,iBACP,IAAI,CAAC,EAAE,EACpB,SAAS,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,cAAc,CAAC,mBAAmB,CAAC,CAAC,EACzE,OAAO,EAAC,EAAE,IAET,IAAI,CAAC,IAAI,CACK;QAChB,WAAW,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,YAAY,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI,CAC5F,oBAAC,OAAO,IACN,QAAQ,EAAE,YAAY,EACtB,QAAQ,EAAE,IAAI,CAAC,EAAE,EACjB,KAAK,EAAE,CAAC,YAAY,IAAI,oBAAC,UAAU,IAAC,OAAO,EAAE,IAAI,IAAG,IAAI,CAAC,eAAe,CAAc,CAAC,IAAI,IAAI,CAAC,IAAI,EACpG,SAAS,EAAE,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,cAAc,CAAC,sBAAsB,CAAC,CAAC,GAC/E,CACH,CACG,CACP,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,eAAe,cAAc,CAAC","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport React, { forwardRef } from 'react';\nimport clsx from 'clsx';\n\nimport { warnOnce } from '@cloudscape-design/component-toolkit/internal';\n\nimport { ButtonProps } from '../button/interfaces.js';\nimport { InternalButton } from '../button/internal.js';\nimport LiveRegion from '../internal/components/live-region/index.js';\nimport Tooltip from '../internal/components/tooltip/index.js';\nimport { CancelableEventHandler, ClickDetail } from '../internal/events/index.js';\nimport { ButtonGroupProps } from './interfaces.js';\n\nimport testUtilStyles from './test-classes/styles.css.js';\n\nconst IconButtonItem = forwardRef(\n (\n {\n item,\n showTooltip,\n showFeedback,\n onItemClick,\n }: {\n item: ButtonGroupProps.IconButton;\n showTooltip: boolean;\n showFeedback: boolean;\n onItemClick?: CancelableEventHandler<ClickDetail>;\n },\n ref: React.Ref<ButtonProps.Ref>\n ) => {\n const containerRef = React.useRef<HTMLDivElement>(null);\n const hasIcon = item.iconName || item.iconUrl || item.iconSvg;\n\n if (!hasIcon) {\n warnOnce('ButtonGroup', `Missing icon for item with id: ${item.id}`);\n }\n\n return (\n <div ref={containerRef}>\n <InternalButton\n variant=\"icon\"\n loading={item.loading}\n loadingText={item.loadingText}\n disabled={item.disabled}\n iconName={hasIcon ? item.iconName : 'close'}\n iconAlt={item.text}\n iconSvg={item.iconSvg}\n ariaLabel={item.text}\n onClick={onItemClick}\n ref={ref}\n data-testid={item.id}\n data-itemid={item.id}\n className={clsx(testUtilStyles.item, testUtilStyles['button-group-item'])}\n __title=\"\"\n >\n {item.text}\n </InternalButton>\n {showTooltip && !item.disabled && !item.loading && (!showFeedback || item.popoverFeedback) && (\n <Tooltip\n trackRef={containerRef}\n trackKey={item.id}\n value={(showFeedback && <LiveRegion visible={true}>{item.popoverFeedback}</LiveRegion>) || item.text}\n className={clsx(testUtilStyles.tooltip, testUtilStyles['button-group-tooltip'])}\n />\n )}\n </div>\n );\n }\n);\n\nexport default IconButtonItem;\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ButtonGroupProps } from './interfaces';
|
|
3
|
+
export { ButtonGroupProps };
|
|
4
|
+
declare const ButtonGroup: React.ForwardRefExoticComponent<ButtonGroupProps & React.RefAttributes<ButtonGroupProps.Ref>>;
|
|
5
|
+
export default ButtonGroup;
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/button-group/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGhD,OAAO,EAAE,gBAAgB,EAAE,CAAC;AAE5B,QAAA,MAAM,WAAW,+FAsBhB,CAAC;AAGF,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { __rest } from "tslib";
|
|
2
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import { getBaseProps } from '../internal/base-component';
|
|
6
|
+
import useBaseComponent from '../internal/hooks/use-base-component';
|
|
7
|
+
import { applyDisplayName } from '../internal/utils/apply-display-name';
|
|
8
|
+
import { getExternalProps } from '../internal/utils/external-props';
|
|
9
|
+
import InternalButtonGroup from './internal';
|
|
10
|
+
const ButtonGroup = React.forwardRef((_a, ref) => {
|
|
11
|
+
var { variant, dropdownExpandToViewport } = _a, rest = __rest(_a, ["variant", "dropdownExpandToViewport"]);
|
|
12
|
+
const baseProps = getBaseProps(rest);
|
|
13
|
+
const baseComponentProps = useBaseComponent('ButtonGroup', {
|
|
14
|
+
props: {
|
|
15
|
+
variant,
|
|
16
|
+
dropdownExpandToViewport,
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
const externalProps = getExternalProps(rest);
|
|
20
|
+
return (React.createElement(InternalButtonGroup, Object.assign({}, baseProps, baseComponentProps, externalProps, { ref: ref, variant: variant, dropdownExpandToViewport: dropdownExpandToViewport })));
|
|
21
|
+
});
|
|
22
|
+
applyDisplayName(ButtonGroup, 'ButtonGroup');
|
|
23
|
+
export default ButtonGroup;
|
|
24
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/button-group/index.tsx"],"names":[],"mappings":";AAAA,qEAAqE;AACrE,sCAAsC;AACtC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,gBAAgB,MAAM,sCAAsC,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEpE,OAAO,mBAAmB,MAAM,YAAY,CAAC;AAI7C,MAAM,WAAW,GAAG,KAAK,CAAC,UAAU,CAClC,CAAC,EAAgE,EAAE,GAAoC,EAAE,EAAE;QAA1G,EAAE,OAAO,EAAE,wBAAwB,OAA6B,EAAxB,IAAI,cAA5C,uCAA8C,CAAF;IAC3C,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,kBAAkB,GAAG,gBAAgB,CAAC,aAAa,EAAE;QACzD,KAAK,EAAE;YACL,OAAO;YACP,wBAAwB;SACzB;KACF,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAC7C,OAAO,CACL,oBAAC,mBAAmB,oBACd,SAAS,EACT,kBAAkB,EAClB,aAAa,IACjB,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,OAAO,EAChB,wBAAwB,EAAE,wBAAwB,IAClD,CACH,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,gBAAgB,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;AAC7C,eAAe,WAAW,CAAC","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport React from 'react';\n\nimport { getBaseProps } from '../internal/base-component';\nimport useBaseComponent from '../internal/hooks/use-base-component';\nimport { applyDisplayName } from '../internal/utils/apply-display-name';\nimport { getExternalProps } from '../internal/utils/external-props';\nimport { ButtonGroupProps } from './interfaces';\nimport InternalButtonGroup from './internal';\n\nexport { ButtonGroupProps };\n\nconst ButtonGroup = React.forwardRef(\n ({ variant, dropdownExpandToViewport, ...rest }: ButtonGroupProps, ref: React.Ref<ButtonGroupProps.Ref>) => {\n const baseProps = getBaseProps(rest);\n const baseComponentProps = useBaseComponent('ButtonGroup', {\n props: {\n variant,\n dropdownExpandToViewport,\n },\n });\n\n const externalProps = getExternalProps(rest);\n return (\n <InternalButtonGroup\n {...baseProps}\n {...baseComponentProps}\n {...externalProps}\n ref={ref}\n variant={variant}\n dropdownExpandToViewport={dropdownExpandToViewport}\n />\n );\n }\n);\n\napplyDisplayName(ButtonGroup, 'ButtonGroup');\nexport default ButtonGroup;\n"]}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { ButtonDropdownProps } from '../button-dropdown/interfaces';
|
|
3
|
+
import { IconProps } from '../icon/interfaces';
|
|
4
|
+
import { BaseComponentProps } from '../internal/base-component';
|
|
5
|
+
import { NonCancelableEventHandler } from '../internal/events';
|
|
6
|
+
import { InternalBaseComponentProps } from '../internal/hooks/use-base-component';
|
|
7
|
+
export interface ButtonGroupProps extends BaseComponentProps {
|
|
8
|
+
/**
|
|
9
|
+
* Adds `aria-label` to the button group toolbar element.
|
|
10
|
+
* Use this to provide a unique accessible name for each button group on the page.
|
|
11
|
+
*/
|
|
12
|
+
ariaLabel?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Determines the general styling of the button dropdown.
|
|
15
|
+
* * `icon` for icon buttons.
|
|
16
|
+
*/
|
|
17
|
+
variant: ButtonGroupProps.Variant;
|
|
18
|
+
/**
|
|
19
|
+
* Use this property to determine dropdown placement strategy for all menu dropdown items.
|
|
20
|
+
*
|
|
21
|
+
* By default, the dropdown height is constrained to fit inside the height of its next scrollable container element.
|
|
22
|
+
* Enabling this property will allow the dropdown to extend beyond that container by using fixed positioning and
|
|
23
|
+
* [React Portals](https://reactjs.org/docs/portals.html).
|
|
24
|
+
*
|
|
25
|
+
* Set this property if the dropdown would otherwise be constrained by a scrollable container,
|
|
26
|
+
* for example inside table and split view layouts.
|
|
27
|
+
*
|
|
28
|
+
* We recommend you use discretion, and don't enable this property unless necessary
|
|
29
|
+
* because fixed positioning results in a slight, visible lag when scrolling complex pages.
|
|
30
|
+
*/
|
|
31
|
+
dropdownExpandToViewport?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Array of objects with a number of supported types.
|
|
34
|
+
*
|
|
35
|
+
* ### icon-button
|
|
36
|
+
*
|
|
37
|
+
* * `id` (string) - The unique identifier of the button, used as detail in `onItemClick` handler and to focus the button using `ref.focus(id)`.
|
|
38
|
+
* * `text` (string) - The name shown as a tooltip or menu text for this button.
|
|
39
|
+
* * `disabled` (optional, boolean) - The disabled state indication for the button.
|
|
40
|
+
* * `loading` (optional, boolean) - The loading state indication for the button.
|
|
41
|
+
* * `loadingText` (optional, string) - The loading text announced to screen readers.
|
|
42
|
+
* * `iconName` (optional, string) - Specifies the name of the icon, used with the [icon component](/components/icon/).
|
|
43
|
+
* * `iconAlt` (optional, string) - Specifies alternate text for the icon when using `iconUrl`.
|
|
44
|
+
* * `iconUrl` (optional, string) - Specifies the URL of a custom icon.
|
|
45
|
+
* * `iconSvg` (optional, ReactNode) - Custom SVG icon. Equivalent to the `svg` slot of the [icon component](/components/icon/).
|
|
46
|
+
* * `popoverFeedback` (optional, string) - Text that appears when the user clicks the button. Use to provide feedback to the user.
|
|
47
|
+
*
|
|
48
|
+
* ### menu-dropdown
|
|
49
|
+
*
|
|
50
|
+
* * `id` (string) - The unique identifier of the button, used as detail in `onItemClick`.
|
|
51
|
+
* * `text` (string) - The name of the menu button shown as a tooltip.
|
|
52
|
+
* * `disabled` (optional, boolean) - The disabled state indication for the menu button.
|
|
53
|
+
* * `loading` (optional, boolean) - The loading state indication for the menu button.
|
|
54
|
+
* * `loadingText` (optional, string) - The loading text announced to screen readers.
|
|
55
|
+
* * `items` (ButtonDropdownProps.ItemOrGroup[]) - The array of dropdown items that belong to this menu.
|
|
56
|
+
*
|
|
57
|
+
* group
|
|
58
|
+
*
|
|
59
|
+
* * `text` (string) - The name of the group rendered as ARIA label for this group.
|
|
60
|
+
* * `items` ((ButtonGroupProps.IconButton | ButtonGroupProps.MenuDropdown)[]) - The array of items that belong to this group.
|
|
61
|
+
*/
|
|
62
|
+
items: ReadonlyArray<ButtonGroupProps.ItemOrGroup>;
|
|
63
|
+
/**
|
|
64
|
+
* Called when the user clicks on an item, and the item is not disabled. The event detail object contains the id of the clicked item.
|
|
65
|
+
*/
|
|
66
|
+
onItemClick?: NonCancelableEventHandler<ButtonGroupProps.ItemClickDetails>;
|
|
67
|
+
}
|
|
68
|
+
export interface InternalButtonGroupProps extends ButtonGroupProps, InternalBaseComponentProps {
|
|
69
|
+
}
|
|
70
|
+
export declare namespace ButtonGroupProps {
|
|
71
|
+
type Variant = 'icon';
|
|
72
|
+
type ItemOrGroup = Item | Group;
|
|
73
|
+
type Item = IconButton | MenuDropdown;
|
|
74
|
+
interface IconButton {
|
|
75
|
+
type: 'icon-button';
|
|
76
|
+
id: string;
|
|
77
|
+
text: string;
|
|
78
|
+
disabled?: boolean;
|
|
79
|
+
loading?: boolean;
|
|
80
|
+
loadingText?: string;
|
|
81
|
+
iconName?: IconProps.Name;
|
|
82
|
+
iconAlt?: string;
|
|
83
|
+
iconUrl?: string;
|
|
84
|
+
iconSvg?: React.ReactNode;
|
|
85
|
+
popoverFeedback?: React.ReactNode;
|
|
86
|
+
}
|
|
87
|
+
interface MenuDropdown {
|
|
88
|
+
type: 'menu-dropdown';
|
|
89
|
+
id: string;
|
|
90
|
+
text: string;
|
|
91
|
+
disabled?: boolean;
|
|
92
|
+
loading?: boolean;
|
|
93
|
+
loadingText?: string;
|
|
94
|
+
items: ReadonlyArray<ButtonDropdownProps.ItemOrGroup>;
|
|
95
|
+
}
|
|
96
|
+
interface Group {
|
|
97
|
+
type: 'group';
|
|
98
|
+
text: string;
|
|
99
|
+
items: ReadonlyArray<ButtonGroupProps.Item>;
|
|
100
|
+
}
|
|
101
|
+
interface ItemClickDetails {
|
|
102
|
+
id: string;
|
|
103
|
+
}
|
|
104
|
+
interface Ref {
|
|
105
|
+
/**
|
|
106
|
+
* Focuses button group item by id.
|
|
107
|
+
*/
|
|
108
|
+
focus(itemId: string): void;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=interfaces.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../../src/button-group/interfaces.ts"],"names":[],"mappings":";AAGA,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AAElF,MAAM,WAAW,gBAAiB,SAAQ,kBAAkB;IAC1D;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC;IAClC;;;;;;;;;;;;OAYG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACH,KAAK,EAAE,aAAa,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;IACnD;;OAEG;IACH,WAAW,CAAC,EAAE,yBAAyB,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;CAC5E;AAED,MAAM,WAAW,wBAAyB,SAAQ,gBAAgB,EAAE,0BAA0B;CAAG;AAEjG,yBAAiB,gBAAgB,CAAC;IAChC,KAAY,OAAO,GAAG,MAAM,CAAC;IAE7B,KAAY,WAAW,GAAG,IAAI,GAAG,KAAK,CAAC;IACvC,KAAY,IAAI,GAAG,UAAU,GAAG,YAAY,CAAC;IAE7C,UAAiB,UAAU;QACzB,IAAI,EAAE,aAAa,CAAC;QACpB,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC;QAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;QAC1B,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;KACnC;IAED,UAAiB,YAAY;QAC3B,IAAI,EAAE,eAAe,CAAC;QACtB,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,KAAK,EAAE,aAAa,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC;KACvD;IAED,UAAiB,KAAK;QACpB,IAAI,EAAE,OAAO,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,aAAa,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;KAC7C;IAED,UAAiB,gBAAgB;QAC/B,EAAE,EAAE,MAAM,CAAC;KACZ;IAED,UAAiB,GAAG;QAClB;;WAEG;QACH,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;KAC7B;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../../src/button-group/interfaces.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,sCAAsC","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { ButtonDropdownProps } from '../button-dropdown/interfaces';\nimport { IconProps } from '../icon/interfaces';\nimport { BaseComponentProps } from '../internal/base-component';\nimport { NonCancelableEventHandler } from '../internal/events';\nimport { InternalBaseComponentProps } from '../internal/hooks/use-base-component';\n\nexport interface ButtonGroupProps extends BaseComponentProps {\n /**\n * Adds `aria-label` to the button group toolbar element.\n * Use this to provide a unique accessible name for each button group on the page.\n */\n ariaLabel?: string;\n /**\n * Determines the general styling of the button dropdown.\n * * `icon` for icon buttons.\n */\n variant: ButtonGroupProps.Variant;\n /**\n * Use this property to determine dropdown placement strategy for all menu dropdown items.\n *\n * By default, the dropdown height is constrained to fit inside the height of its next scrollable container element.\n * Enabling this property will allow the dropdown to extend beyond that container by using fixed positioning and\n * [React Portals](https://reactjs.org/docs/portals.html).\n *\n * Set this property if the dropdown would otherwise be constrained by a scrollable container,\n * for example inside table and split view layouts.\n *\n * We recommend you use discretion, and don't enable this property unless necessary\n * because fixed positioning results in a slight, visible lag when scrolling complex pages.\n */\n dropdownExpandToViewport?: boolean;\n /**\n * Array of objects with a number of supported types.\n *\n * ### icon-button\n *\n * * `id` (string) - The unique identifier of the button, used as detail in `onItemClick` handler and to focus the button using `ref.focus(id)`.\n * * `text` (string) - The name shown as a tooltip or menu text for this button.\n * * `disabled` (optional, boolean) - The disabled state indication for the button.\n * * `loading` (optional, boolean) - The loading state indication for the button.\n * * `loadingText` (optional, string) - The loading text announced to screen readers.\n * * `iconName` (optional, string) - Specifies the name of the icon, used with the [icon component](/components/icon/).\n * * `iconAlt` (optional, string) - Specifies alternate text for the icon when using `iconUrl`.\n * * `iconUrl` (optional, string) - Specifies the URL of a custom icon.\n * * `iconSvg` (optional, ReactNode) - Custom SVG icon. Equivalent to the `svg` slot of the [icon component](/components/icon/).\n * * `popoverFeedback` (optional, string) - Text that appears when the user clicks the button. Use to provide feedback to the user.\n *\n * ### menu-dropdown\n *\n * * `id` (string) - The unique identifier of the button, used as detail in `onItemClick`.\n * * `text` (string) - The name of the menu button shown as a tooltip.\n * * `disabled` (optional, boolean) - The disabled state indication for the menu button.\n * * `loading` (optional, boolean) - The loading state indication for the menu button.\n * * `loadingText` (optional, string) - The loading text announced to screen readers.\n * * `items` (ButtonDropdownProps.ItemOrGroup[]) - The array of dropdown items that belong to this menu.\n *\n * group\n *\n * * `text` (string) - The name of the group rendered as ARIA label for this group.\n * * `items` ((ButtonGroupProps.IconButton | ButtonGroupProps.MenuDropdown)[]) - The array of items that belong to this group.\n */\n items: ReadonlyArray<ButtonGroupProps.ItemOrGroup>;\n /**\n * Called when the user clicks on an item, and the item is not disabled. The event detail object contains the id of the clicked item.\n */\n onItemClick?: NonCancelableEventHandler<ButtonGroupProps.ItemClickDetails>;\n}\n\nexport interface InternalButtonGroupProps extends ButtonGroupProps, InternalBaseComponentProps {}\n\nexport namespace ButtonGroupProps {\n export type Variant = 'icon';\n\n export type ItemOrGroup = Item | Group;\n export type Item = IconButton | MenuDropdown;\n\n export interface IconButton {\n type: 'icon-button';\n id: string;\n text: string;\n disabled?: boolean;\n loading?: boolean;\n loadingText?: string;\n iconName?: IconProps.Name;\n iconAlt?: string;\n iconUrl?: string;\n iconSvg?: React.ReactNode;\n popoverFeedback?: React.ReactNode;\n }\n\n export interface MenuDropdown {\n type: 'menu-dropdown';\n id: string;\n text: string;\n disabled?: boolean;\n loading?: boolean;\n loadingText?: string;\n items: ReadonlyArray<ButtonDropdownProps.ItemOrGroup>;\n }\n\n export interface Group {\n type: 'group';\n text: string;\n items: ReadonlyArray<ButtonGroupProps.Item>;\n }\n\n export interface ItemClickDetails {\n id: string;\n }\n\n export interface Ref {\n /**\n * Focuses button group item by id.\n */\n focus(itemId: string): void;\n }\n}\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ButtonGroupProps, InternalButtonGroupProps } from './interfaces';
|
|
3
|
+
declare const InternalButtonGroup: React.ForwardRefExoticComponent<InternalButtonGroupProps & React.RefAttributes<ButtonGroupProps.Ref>>;
|
|
4
|
+
export default InternalButtonGroup;
|
|
5
|
+
//# sourceMappingURL=internal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../../src/button-group/internal.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAuE,MAAM,OAAO,CAAC;AAiB5F,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAM1E,QAAA,MAAM,mBAAmB,uGAoKxB,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { __rest } from "tslib";
|
|
2
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
import React, { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
|
|
5
|
+
import clsx from 'clsx';
|
|
6
|
+
import { warnOnce } from '@cloudscape-design/component-toolkit/internal';
|
|
7
|
+
import { getBaseProps } from '../internal/base-component';
|
|
8
|
+
import { getAllFocusables } from '../internal/components/focus-lock/utils';
|
|
9
|
+
import { SingleTabStopNavigationProvider, } from '../internal/context/single-tab-stop-navigation-context';
|
|
10
|
+
import { hasModifierKeys } from '../internal/events';
|
|
11
|
+
import { useMergeRefs } from '../internal/hooks/use-merge-refs';
|
|
12
|
+
import { KeyCode } from '../internal/keycode';
|
|
13
|
+
import { circleIndex } from '../internal/utils/circle-index';
|
|
14
|
+
import handleKey from '../internal/utils/handle-key';
|
|
15
|
+
import ItemElement from './item-element.js';
|
|
16
|
+
import styles from './styles.css.js';
|
|
17
|
+
import testUtilStyles from './test-classes/styles.css.js';
|
|
18
|
+
const InternalButtonGroup = forwardRef((_a, ref) => {
|
|
19
|
+
var { items = [], onItemClick, ariaLabel, dropdownExpandToViewport, __internalRootRef = null } = _a, props = __rest(_a, ["items", "onItemClick", "ariaLabel", "dropdownExpandToViewport", "__internalRootRef"]);
|
|
20
|
+
const baseProps = getBaseProps(props);
|
|
21
|
+
const focusedIdRef = useRef(null);
|
|
22
|
+
const navigationAPI = useRef(null);
|
|
23
|
+
const containerObjectRef = useRef(null);
|
|
24
|
+
const containerRef = useMergeRefs(containerObjectRef, __internalRootRef);
|
|
25
|
+
const itemsRef = useRef({});
|
|
26
|
+
const [tooltip, setTooltip] = useState(null);
|
|
27
|
+
useImperativeHandle(ref, () => ({
|
|
28
|
+
focus: id => {
|
|
29
|
+
var _a;
|
|
30
|
+
(_a = itemsRef.current[id]) === null || _a === void 0 ? void 0 : _a.focus();
|
|
31
|
+
},
|
|
32
|
+
}));
|
|
33
|
+
function getNextFocusTarget() {
|
|
34
|
+
var _a, _b;
|
|
35
|
+
if (containerObjectRef.current) {
|
|
36
|
+
const buttons = Array.from(containerObjectRef.current.querySelectorAll(`.${testUtilStyles.item}`));
|
|
37
|
+
const activeButtons = buttons.filter(button => !button.disabled);
|
|
38
|
+
return (_b = (_a = activeButtons.find(button => button.dataset.itemid === focusedIdRef.current)) !== null && _a !== void 0 ? _a : activeButtons[0]) !== null && _b !== void 0 ? _b : null;
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
function onUnregisterActive(focusableElement) {
|
|
43
|
+
var _a;
|
|
44
|
+
// Only refocus when the node is actually removed (no such ID anymore).
|
|
45
|
+
const target = (_a = navigationAPI.current) === null || _a === void 0 ? void 0 : _a.getFocusTarget();
|
|
46
|
+
if (target && target.dataset.itemid !== focusableElement.dataset.itemid) {
|
|
47
|
+
target.focus();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
var _a;
|
|
52
|
+
(_a = navigationAPI.current) === null || _a === void 0 ? void 0 : _a.updateFocusTarget();
|
|
53
|
+
});
|
|
54
|
+
function onFocus(event) {
|
|
55
|
+
var _a;
|
|
56
|
+
if (event.target instanceof HTMLElement && event.target.dataset.itemid) {
|
|
57
|
+
focusedIdRef.current = event.target.dataset.itemid;
|
|
58
|
+
}
|
|
59
|
+
(_a = navigationAPI.current) === null || _a === void 0 ? void 0 : _a.updateFocusTarget();
|
|
60
|
+
}
|
|
61
|
+
function onBlur() {
|
|
62
|
+
var _a;
|
|
63
|
+
(_a = navigationAPI.current) === null || _a === void 0 ? void 0 : _a.updateFocusTarget();
|
|
64
|
+
}
|
|
65
|
+
function onKeyDown(event) {
|
|
66
|
+
var _a;
|
|
67
|
+
const focusTarget = (_a = navigationAPI.current) === null || _a === void 0 ? void 0 : _a.getFocusTarget();
|
|
68
|
+
const specialKeys = [KeyCode.right, KeyCode.left, KeyCode.end, KeyCode.home, KeyCode.pageUp, KeyCode.pageDown];
|
|
69
|
+
if (hasModifierKeys(event) || specialKeys.indexOf(event.keyCode) === -1) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (!containerObjectRef.current || !focusTarget) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
// Ignore navigation when the focused element is not an item.
|
|
76
|
+
if (document.activeElement && !document.activeElement.matches(`.${testUtilStyles.item}`)) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
event.preventDefault();
|
|
80
|
+
const focusables = getFocusablesFrom(containerObjectRef.current);
|
|
81
|
+
const activeIndex = focusables.indexOf(focusTarget);
|
|
82
|
+
handleKey(event, {
|
|
83
|
+
onHome: () => focusElement(focusables[0]),
|
|
84
|
+
onEnd: () => focusElement(focusables[focusables.length - 1]),
|
|
85
|
+
onInlineStart: () => focusElement(focusables[circleIndex(activeIndex - 1, [0, focusables.length - 1])]),
|
|
86
|
+
onInlineEnd: () => focusElement(focusables[circleIndex(activeIndex + 1, [0, focusables.length - 1])]),
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
function focusElement(element) {
|
|
90
|
+
element.focus();
|
|
91
|
+
}
|
|
92
|
+
// List all non-disabled and registered focusables: those are eligible for keyboard navigation.
|
|
93
|
+
function getFocusablesFrom(target) {
|
|
94
|
+
function isElementRegistered(element) {
|
|
95
|
+
var _a, _b;
|
|
96
|
+
return (_b = (_a = navigationAPI.current) === null || _a === void 0 ? void 0 : _a.isRegistered(element)) !== null && _b !== void 0 ? _b : false;
|
|
97
|
+
}
|
|
98
|
+
function isElementDisabled(element) {
|
|
99
|
+
if (element instanceof HTMLButtonElement) {
|
|
100
|
+
return element.disabled;
|
|
101
|
+
}
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
return getAllFocusables(target).filter(el => isElementRegistered(el) && !isElementDisabled(el));
|
|
105
|
+
}
|
|
106
|
+
return (React.createElement("div", Object.assign({}, baseProps, { className: clsx(styles.root, testUtilStyles['button-group'], baseProps.className), ref: containerRef, role: "toolbar", "aria-label": ariaLabel, onFocus: onFocus, onBlur: onBlur, onKeyDown: onKeyDown }),
|
|
107
|
+
React.createElement(SingleTabStopNavigationProvider, { ref: navigationAPI, navigationActive: true, getNextFocusTarget: getNextFocusTarget, onUnregisterActive: onUnregisterActive }, items.map((itemOrGroup, index) => {
|
|
108
|
+
var _a;
|
|
109
|
+
const itemContent = (item) => (React.createElement(ItemElement, { key: item.id, item: item, dropdownExpandToViewport: dropdownExpandToViewport, tooltip: tooltip, setTooltip: setTooltip, onItemClick: onItemClick, ref: element => (itemsRef.current[item.id] = element) }));
|
|
110
|
+
const isGroupBefore = ((_a = items[index - 1]) === null || _a === void 0 ? void 0 : _a.type) === 'group';
|
|
111
|
+
const currentItem = items[index];
|
|
112
|
+
const isGroupNow = (currentItem === null || currentItem === void 0 ? void 0 : currentItem.type) === 'group';
|
|
113
|
+
const shouldAddDivider = isGroupBefore || (!isGroupBefore && isGroupNow && index !== 0);
|
|
114
|
+
if (isGroupNow && currentItem.items.length === 0) {
|
|
115
|
+
warnOnce('ButtonGroup', 'Empty group detected. Empty groups are not allowed.');
|
|
116
|
+
}
|
|
117
|
+
return (React.createElement(React.Fragment, { key: itemOrGroup.type === 'group' ? index : itemOrGroup.id },
|
|
118
|
+
shouldAddDivider && React.createElement("div", { className: styles.divider }),
|
|
119
|
+
itemOrGroup.type === 'group' ? (React.createElement("div", { key: index, role: "group", "aria-label": itemOrGroup.text, className: styles.group }, itemOrGroup.items.map(item => itemContent(item)))) : (itemContent(itemOrGroup))));
|
|
120
|
+
}))));
|
|
121
|
+
});
|
|
122
|
+
export default InternalButtonGroup;
|
|
123
|
+
//# sourceMappingURL=internal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal.js","sourceRoot":"","sources":["../../../src/button-group/internal.tsx"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport React, { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';\nimport clsx from 'clsx';\n\nimport { warnOnce } from '@cloudscape-design/component-toolkit/internal';\n\nimport { ButtonProps } from '../button/interfaces';\nimport { getBaseProps } from '../internal/base-component';\nimport { getAllFocusables } from '../internal/components/focus-lock/utils';\nimport {\n SingleTabStopNavigationAPI,\n SingleTabStopNavigationProvider,\n} from '../internal/context/single-tab-stop-navigation-context';\nimport { hasModifierKeys } from '../internal/events';\nimport { useMergeRefs } from '../internal/hooks/use-merge-refs';\nimport { KeyCode } from '../internal/keycode';\nimport { circleIndex } from '../internal/utils/circle-index';\nimport handleKey from '../internal/utils/handle-key';\nimport { ButtonGroupProps, InternalButtonGroupProps } from './interfaces';\nimport ItemElement from './item-element.js';\n\nimport styles from './styles.css.js';\nimport testUtilStyles from './test-classes/styles.css.js';\n\nconst InternalButtonGroup = forwardRef(\n (\n {\n items = [],\n onItemClick,\n ariaLabel,\n dropdownExpandToViewport,\n __internalRootRef = null,\n ...props\n }: InternalButtonGroupProps,\n ref: React.Ref<ButtonGroupProps.Ref>\n ) => {\n const baseProps = getBaseProps(props);\n const focusedIdRef = useRef<null | string>(null);\n const navigationAPI = useRef<SingleTabStopNavigationAPI>(null);\n const containerObjectRef = useRef<HTMLDivElement>(null);\n const containerRef = useMergeRefs(containerObjectRef, __internalRootRef);\n const itemsRef = useRef<Record<string, ButtonProps.Ref | null>>({});\n const [tooltip, setTooltip] = useState<null | { item: string; feedback: boolean }>(null);\n\n useImperativeHandle(ref, () => ({\n focus: id => {\n itemsRef.current[id]?.focus();\n },\n }));\n\n function getNextFocusTarget(): null | HTMLElement {\n if (containerObjectRef.current) {\n const buttons: HTMLButtonElement[] = Array.from(\n containerObjectRef.current.querySelectorAll(`.${testUtilStyles.item}`)\n );\n const activeButtons = buttons.filter(button => !button.disabled);\n return activeButtons.find(button => button.dataset.itemid === focusedIdRef.current) ?? activeButtons[0] ?? null;\n }\n return null;\n }\n\n function onUnregisterActive(focusableElement: HTMLElement) {\n // Only refocus when the node is actually removed (no such ID anymore).\n const target = navigationAPI.current?.getFocusTarget();\n\n if (target && target.dataset.itemid !== focusableElement.dataset.itemid) {\n target.focus();\n }\n }\n\n useEffect(() => {\n navigationAPI.current?.updateFocusTarget();\n });\n\n function onFocus(event: React.FocusEvent) {\n if (event.target instanceof HTMLElement && event.target.dataset.itemid) {\n focusedIdRef.current = event.target.dataset.itemid;\n }\n\n navigationAPI.current?.updateFocusTarget();\n }\n\n function onBlur() {\n navigationAPI.current?.updateFocusTarget();\n }\n\n function onKeyDown(event: React.KeyboardEvent) {\n const focusTarget = navigationAPI.current?.getFocusTarget();\n const specialKeys = [KeyCode.right, KeyCode.left, KeyCode.end, KeyCode.home, KeyCode.pageUp, KeyCode.pageDown];\n if (hasModifierKeys(event) || specialKeys.indexOf(event.keyCode) === -1) {\n return;\n }\n if (!containerObjectRef.current || !focusTarget) {\n return;\n }\n // Ignore navigation when the focused element is not an item.\n if (document.activeElement && !document.activeElement.matches(`.${testUtilStyles.item}`)) {\n return;\n }\n event.preventDefault();\n\n const focusables = getFocusablesFrom(containerObjectRef.current);\n const activeIndex = focusables.indexOf(focusTarget);\n handleKey(event as any, {\n onHome: () => focusElement(focusables[0]),\n onEnd: () => focusElement(focusables[focusables.length - 1]),\n onInlineStart: () => focusElement(focusables[circleIndex(activeIndex - 1, [0, focusables.length - 1])]),\n onInlineEnd: () => focusElement(focusables[circleIndex(activeIndex + 1, [0, focusables.length - 1])]),\n });\n }\n\n function focusElement(element: HTMLElement) {\n element.focus();\n }\n\n // List all non-disabled and registered focusables: those are eligible for keyboard navigation.\n function getFocusablesFrom(target: HTMLElement) {\n function isElementRegistered(element: HTMLElement) {\n return navigationAPI.current?.isRegistered(element) ?? false;\n }\n\n function isElementDisabled(element: HTMLElement) {\n if (element instanceof HTMLButtonElement) {\n return element.disabled;\n }\n\n return false;\n }\n\n return getAllFocusables(target).filter(el => isElementRegistered(el) && !isElementDisabled(el));\n }\n\n return (\n <div\n {...baseProps}\n className={clsx(styles.root, testUtilStyles['button-group'], baseProps.className)}\n ref={containerRef}\n role=\"toolbar\"\n aria-label={ariaLabel}\n onFocus={onFocus}\n onBlur={onBlur}\n onKeyDown={onKeyDown}\n >\n <SingleTabStopNavigationProvider\n ref={navigationAPI}\n navigationActive={true}\n getNextFocusTarget={getNextFocusTarget}\n onUnregisterActive={onUnregisterActive}\n >\n {items.map((itemOrGroup, index) => {\n const itemContent = (item: ButtonGroupProps.Item) => (\n <ItemElement\n key={item.id}\n item={item}\n dropdownExpandToViewport={dropdownExpandToViewport}\n tooltip={tooltip}\n setTooltip={setTooltip}\n onItemClick={onItemClick}\n ref={element => (itemsRef.current[item.id] = element)}\n />\n );\n\n const isGroupBefore = items[index - 1]?.type === 'group';\n const currentItem = items[index];\n const isGroupNow = currentItem?.type === 'group';\n const shouldAddDivider = isGroupBefore || (!isGroupBefore && isGroupNow && index !== 0);\n\n if (isGroupNow && currentItem.items.length === 0) {\n warnOnce('ButtonGroup', 'Empty group detected. Empty groups are not allowed.');\n }\n\n return (\n <React.Fragment key={itemOrGroup.type === 'group' ? index : itemOrGroup.id}>\n {shouldAddDivider && <div className={styles.divider} />}\n {itemOrGroup.type === 'group' ? (\n <div key={index} role=\"group\" aria-label={itemOrGroup.text} className={styles.group}>\n {itemOrGroup.items.map(item => itemContent(item))}\n </div>\n ) : (\n itemContent(itemOrGroup)\n )}\n </React.Fragment>\n );\n })}\n </SingleTabStopNavigationProvider>\n </div>\n );\n }\n);\n\nexport default InternalButtonGroup;\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ButtonProps } from '../button/interfaces.js';
|
|
3
|
+
import { NonCancelableEventHandler } from '../internal/events';
|
|
4
|
+
import { ButtonGroupProps } from './interfaces';
|
|
5
|
+
interface ItemElementProps {
|
|
6
|
+
item: ButtonGroupProps.Item;
|
|
7
|
+
dropdownExpandToViewport?: boolean;
|
|
8
|
+
tooltip: null | {
|
|
9
|
+
item: string;
|
|
10
|
+
feedback: boolean;
|
|
11
|
+
};
|
|
12
|
+
setTooltip: (tooltip: null | {
|
|
13
|
+
item: string;
|
|
14
|
+
feedback: boolean;
|
|
15
|
+
}) => void;
|
|
16
|
+
onItemClick?: NonCancelableEventHandler<ButtonGroupProps.ItemClickDetails> | undefined;
|
|
17
|
+
}
|
|
18
|
+
declare const ItemElement: React.ForwardRefExoticComponent<ItemElementProps & React.RefAttributes<ButtonProps.Ref>>;
|
|
19
|
+
export default ItemElement;
|
|
20
|
+
//# sourceMappingURL=item-element.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"item-element.d.ts","sourceRoot":"","sources":["../../../src/button-group/item-element.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA6D,MAAM,OAAO,CAAC;AAElF,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAoC,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAGjG,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAKhD,UAAU,gBAAgB;IACxB,IAAI,EAAE,gBAAgB,CAAC,IAAI,CAAC;IAC5B,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,OAAO,EAAE,IAAI,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IACpD,UAAU,EAAE,CAAC,OAAO,EAAE,IAAI,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;IAC1E,WAAW,CAAC,EAAE,yBAAyB,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,GAAG,SAAS,CAAC;CACxF;AAED,QAAA,MAAM,WAAW,0FA4GhB,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import React, { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';
|
|
4
|
+
import { fireCancelableEvent } from '../internal/events';
|
|
5
|
+
import { nodeBelongs } from '../internal/utils/node-belongs';
|
|
6
|
+
import IconButtonItem from './icon-button-item';
|
|
7
|
+
import MenuDropdownItem from './menu-dropdown-item';
|
|
8
|
+
import styles from './styles.css.js';
|
|
9
|
+
const ItemElement = forwardRef(({ item, dropdownExpandToViewport, tooltip, setTooltip, onItemClick }, ref) => {
|
|
10
|
+
const containerRef = useRef(null);
|
|
11
|
+
const buttonRef = useRef(null);
|
|
12
|
+
useImperativeHandle(ref, () => ({
|
|
13
|
+
focus: () => {
|
|
14
|
+
var _a;
|
|
15
|
+
(_a = buttonRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
16
|
+
},
|
|
17
|
+
}));
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
if ((tooltip === null || tooltip === void 0 ? void 0 : tooltip.item) !== item.id) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const close = () => {
|
|
23
|
+
setTooltip(null);
|
|
24
|
+
};
|
|
25
|
+
const handlePointerDownEvent = (event) => {
|
|
26
|
+
var _a;
|
|
27
|
+
if (event.target && ((_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.contains(event.target))) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
close();
|
|
31
|
+
};
|
|
32
|
+
const handleKeyDownEvent = (event) => {
|
|
33
|
+
if (event.key === 'Escape') {
|
|
34
|
+
close();
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
window.addEventListener('pointerdown', handlePointerDownEvent);
|
|
38
|
+
window.addEventListener('keydown', handleKeyDownEvent);
|
|
39
|
+
return () => {
|
|
40
|
+
window.removeEventListener('pointerdown', handlePointerDownEvent);
|
|
41
|
+
window.removeEventListener('keydown', handleKeyDownEvent);
|
|
42
|
+
};
|
|
43
|
+
}, [item.id, tooltip, setTooltip]);
|
|
44
|
+
const onShowTooltipSoft = (show) => {
|
|
45
|
+
if (!(tooltip === null || tooltip === void 0 ? void 0 : tooltip.feedback)) {
|
|
46
|
+
setTooltip(show ? { item: item.id, feedback: false } : null);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
const onShowTooltipHard = (show) => {
|
|
50
|
+
if (!show && item.id !== (tooltip === null || tooltip === void 0 ? void 0 : tooltip.item)) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
setTooltip(show ? { item: item.id, feedback: false } : null);
|
|
54
|
+
};
|
|
55
|
+
const onClickHandler = (event) => {
|
|
56
|
+
const hasPopoverFeedback = 'popoverFeedback' in item && item.popoverFeedback;
|
|
57
|
+
if (hasPopoverFeedback) {
|
|
58
|
+
setTooltip({ item: item.id, feedback: true });
|
|
59
|
+
}
|
|
60
|
+
fireCancelableEvent(onItemClick, { id: 'id' in event.detail ? event.detail.id : item.id }, event);
|
|
61
|
+
};
|
|
62
|
+
return (React.createElement("div", { key: item.id, className: styles['item-wrapper'], ref: containerRef, onPointerEnter: () => onShowTooltipSoft(true), onPointerLeave: () => onShowTooltipSoft(false), onFocus: event => {
|
|
63
|
+
// Showing no tooltip when the focus comes from inside the container.
|
|
64
|
+
// This is needed to prevent the tooltip after a menu closes with item selection or Escape.
|
|
65
|
+
if (event && event.relatedTarget && nodeBelongs(containerRef.current, event.relatedTarget)) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
onShowTooltipHard(true);
|
|
69
|
+
}, onBlur: () => onShowTooltipHard(false) },
|
|
70
|
+
item.type === 'icon-button' && (React.createElement(IconButtonItem, { ref: buttonRef, item: item, onItemClick: onClickHandler, showTooltip: (tooltip === null || tooltip === void 0 ? void 0 : tooltip.item) === item.id, showFeedback: !!(tooltip === null || tooltip === void 0 ? void 0 : tooltip.feedback) })),
|
|
71
|
+
item.type === 'menu-dropdown' && (React.createElement(MenuDropdownItem, { ref: buttonRef, item: item, showTooltip: (tooltip === null || tooltip === void 0 ? void 0 : tooltip.item) === item.id, onItemClick: onClickHandler, expandToViewport: dropdownExpandToViewport }))));
|
|
72
|
+
});
|
|
73
|
+
export default ItemElement;
|
|
74
|
+
//# sourceMappingURL=item-element.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"item-element.js","sourceRoot":"","sources":["../../../src/button-group/item-element.tsx"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,sCAAsC;AACtC,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAGlF,OAAO,EAAe,mBAAmB,EAA6B,MAAM,oBAAoB,CAAC;AACjG,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,cAAc,MAAM,oBAAoB,CAAC;AAEhD,OAAO,gBAAgB,MAAM,sBAAsB,CAAC;AAEpD,OAAO,MAAM,MAAM,iBAAiB,CAAC;AAUrC,MAAM,WAAW,GAAG,UAAU,CAC5B,CACE,EAAE,IAAI,EAAE,wBAAwB,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAoB,EACtF,GAA+B,EAC/B,EAAE;IACF,MAAM,YAAY,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,MAAM,CAAoB,IAAI,CAAC,CAAC;IAElD,mBAAmB,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;QAC9B,KAAK,EAAE,GAAG,EAAE;;YACV,MAAA,SAAS,CAAC,OAAO,0CAAE,KAAK,EAAE,CAAC;QAC7B,CAAC;KACF,CAAC,CAAC,CAAC;IAEJ,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,IAAI,MAAK,IAAI,CAAC,EAAE,EAAE;YAC7B,OAAO;SACR;QAED,MAAM,KAAK,GAAG,GAAG,EAAE;YACjB,UAAU,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC,CAAC;QAEF,MAAM,sBAAsB,GAAG,CAAC,KAAmB,EAAE,EAAE;;YACrD,IAAI,KAAK,CAAC,MAAM,KAAI,MAAA,YAAY,CAAC,OAAO,0CAAE,QAAQ,CAAC,KAAK,CAAC,MAAqB,CAAC,CAAA,EAAE;gBAC/E,OAAO;aACR;YAED,KAAK,EAAE,CAAC;QACV,CAAC,CAAC;QAEF,MAAM,kBAAkB,GAAG,CAAC,KAAoB,EAAE,EAAE;YAClD,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ,EAAE;gBAC1B,KAAK,EAAE,CAAC;aACT;QACH,CAAC,CAAC;QAEF,MAAM,CAAC,gBAAgB,CAAC,aAAa,EAAE,sBAAsB,CAAC,CAAC;QAC/D,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;QAEvD,OAAO,GAAG,EAAE;YACV,MAAM,CAAC,mBAAmB,CAAC,aAAa,EAAE,sBAAsB,CAAC,CAAC;YAClE,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;QAC5D,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;IAEnC,MAAM,iBAAiB,GAAG,CAAC,IAAa,EAAE,EAAE;QAC1C,IAAI,CAAC,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,QAAQ,CAAA,EAAE;YACtB,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;SAC9D;IACH,CAAC,CAAC;IAEF,MAAM,iBAAiB,GAAG,CAAC,IAAa,EAAE,EAAE;QAC1C,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE,MAAK,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,IAAI,CAAA,EAAE;YACtC,OAAO;SACR;QAED,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC/D,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,CAAC,KAAmE,EAAE,EAAE;QAC7F,MAAM,kBAAkB,GAAG,iBAAiB,IAAI,IAAI,IAAI,IAAI,CAAC,eAAe,CAAC;QAE7E,IAAI,kBAAkB,EAAE;YACtB,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;SAC/C;QAED,mBAAmB,CAAC,WAAW,EAAE,EAAE,EAAE,EAAE,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;IACpG,CAAC,CAAC;IAEF,OAAO,CACL,6BACE,GAAG,EAAE,IAAI,CAAC,EAAE,EACZ,SAAS,EAAE,MAAM,CAAC,cAAc,CAAC,EACjC,GAAG,EAAE,YAAY,EACjB,cAAc,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAC7C,cAAc,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAC9C,OAAO,EAAE,KAAK,CAAC,EAAE;YACf,qEAAqE;YACrE,2FAA2F;YAC3F,IAAI,KAAK,IAAI,KAAK,CAAC,aAAa,IAAI,WAAW,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,aAAa,CAAC,EAAE;gBAC1F,OAAO;aACR;YACD,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC,EACD,MAAM,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,KAAK,CAAC;QAErC,IAAI,CAAC,IAAI,KAAK,aAAa,IAAI,CAC9B,oBAAC,cAAc,IACb,GAAG,EAAE,SAAS,EACd,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,cAAc,EAC3B,WAAW,EAAE,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,IAAI,MAAK,IAAI,CAAC,EAAE,EACtC,YAAY,EAAE,CAAC,CAAC,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,QAAQ,CAAA,GACjC,CACH;QACA,IAAI,CAAC,IAAI,KAAK,eAAe,IAAI,CAChC,oBAAC,gBAAgB,IACf,GAAG,EAAE,SAAS,EACd,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,IAAI,MAAK,IAAI,CAAC,EAAE,EACtC,WAAW,EAAE,cAAc,EAC3B,gBAAgB,EAAE,wBAAwB,GAC1C,CACH,CACG,CACP,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,eAAe,WAAW,CAAC","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport React, { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';\n\nimport { ButtonProps } from '../button/interfaces.js';\nimport { ClickDetail, fireCancelableEvent, NonCancelableEventHandler } from '../internal/events';\nimport { nodeBelongs } from '../internal/utils/node-belongs';\nimport IconButtonItem from './icon-button-item';\nimport { ButtonGroupProps } from './interfaces';\nimport MenuDropdownItem from './menu-dropdown-item';\n\nimport styles from './styles.css.js';\n\ninterface ItemElementProps {\n item: ButtonGroupProps.Item;\n dropdownExpandToViewport?: boolean;\n tooltip: null | { item: string; feedback: boolean };\n setTooltip: (tooltip: null | { item: string; feedback: boolean }) => void;\n onItemClick?: NonCancelableEventHandler<ButtonGroupProps.ItemClickDetails> | undefined;\n}\n\nconst ItemElement = forwardRef(\n (\n { item, dropdownExpandToViewport, tooltip, setTooltip, onItemClick }: ItemElementProps,\n ref: React.Ref<ButtonProps.Ref>\n ) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const buttonRef = useRef<HTMLButtonElement>(null);\n\n useImperativeHandle(ref, () => ({\n focus: () => {\n buttonRef.current?.focus();\n },\n }));\n\n useEffect(() => {\n if (tooltip?.item !== item.id) {\n return;\n }\n\n const close = () => {\n setTooltip(null);\n };\n\n const handlePointerDownEvent = (event: PointerEvent) => {\n if (event.target && containerRef.current?.contains(event.target as HTMLElement)) {\n return;\n }\n\n close();\n };\n\n const handleKeyDownEvent = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n close();\n }\n };\n\n window.addEventListener('pointerdown', handlePointerDownEvent);\n window.addEventListener('keydown', handleKeyDownEvent);\n\n return () => {\n window.removeEventListener('pointerdown', handlePointerDownEvent);\n window.removeEventListener('keydown', handleKeyDownEvent);\n };\n }, [item.id, tooltip, setTooltip]);\n\n const onShowTooltipSoft = (show: boolean) => {\n if (!tooltip?.feedback) {\n setTooltip(show ? { item: item.id, feedback: false } : null);\n }\n };\n\n const onShowTooltipHard = (show: boolean) => {\n if (!show && item.id !== tooltip?.item) {\n return;\n }\n\n setTooltip(show ? { item: item.id, feedback: false } : null);\n };\n\n const onClickHandler = (event: CustomEvent<ButtonGroupProps.ItemClickDetails | ClickDetail>) => {\n const hasPopoverFeedback = 'popoverFeedback' in item && item.popoverFeedback;\n\n if (hasPopoverFeedback) {\n setTooltip({ item: item.id, feedback: true });\n }\n\n fireCancelableEvent(onItemClick, { id: 'id' in event.detail ? event.detail.id : item.id }, event);\n };\n\n return (\n <div\n key={item.id}\n className={styles['item-wrapper']}\n ref={containerRef}\n onPointerEnter={() => onShowTooltipSoft(true)}\n onPointerLeave={() => onShowTooltipSoft(false)}\n onFocus={event => {\n // Showing no tooltip when the focus comes from inside the container.\n // This is needed to prevent the tooltip after a menu closes with item selection or Escape.\n if (event && event.relatedTarget && nodeBelongs(containerRef.current, event.relatedTarget)) {\n return;\n }\n onShowTooltipHard(true);\n }}\n onBlur={() => onShowTooltipHard(false)}\n >\n {item.type === 'icon-button' && (\n <IconButtonItem\n ref={buttonRef}\n item={item}\n onItemClick={onClickHandler}\n showTooltip={tooltip?.item === item.id}\n showFeedback={!!tooltip?.feedback}\n />\n )}\n {item.type === 'menu-dropdown' && (\n <MenuDropdownItem\n ref={buttonRef}\n item={item}\n showTooltip={tooltip?.item === item.id}\n onItemClick={onClickHandler}\n expandToViewport={dropdownExpandToViewport}\n />\n )}\n </div>\n );\n }\n);\n\nexport default ItemElement;\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ButtonDropdownProps } from '../button-dropdown/interfaces';
|
|
3
|
+
import { CancelableEventHandler } from '../internal/events';
|
|
4
|
+
import { ButtonGroupProps } from './interfaces';
|
|
5
|
+
interface MenuDropdownItemProps {
|
|
6
|
+
item: ButtonGroupProps.MenuDropdown;
|
|
7
|
+
showTooltip: boolean;
|
|
8
|
+
onItemClick?: CancelableEventHandler<ButtonGroupProps.ItemClickDetails>;
|
|
9
|
+
expandToViewport?: boolean;
|
|
10
|
+
}
|
|
11
|
+
declare const MenuDropdownItem: React.ForwardRefExoticComponent<MenuDropdownItemProps & React.RefAttributes<ButtonDropdownProps.Ref>>;
|
|
12
|
+
export default MenuDropdownItem;
|
|
13
|
+
//# sourceMappingURL=menu-dropdown-item.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"menu-dropdown-item.d.ts","sourceRoot":"","sources":["../../../src/button-group/menu-dropdown-item.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAGpE,OAAO,EAAE,sBAAsB,EAAuB,MAAM,oBAAoB,CAAC;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAIhD,UAAU,qBAAqB;IAC7B,IAAI,EAAE,gBAAgB,CAAC,YAAY,CAAC;IACpC,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,sBAAsB,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IACxE,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,QAAA,MAAM,gBAAgB,uGAiDrB,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import clsx from 'clsx';
|
|
5
|
+
import InternalButton from '../button/internal';
|
|
6
|
+
import ButtonDropdown from '../button-dropdown/internal';
|
|
7
|
+
import Tooltip from '../internal/components/tooltip';
|
|
8
|
+
import { fireCancelableEvent } from '../internal/events';
|
|
9
|
+
import testUtilStyles from './test-classes/styles.css.js';
|
|
10
|
+
const MenuDropdownItem = React.forwardRef(({ item, showTooltip, onItemClick, expandToViewport }, ref) => {
|
|
11
|
+
const containerRef = React.useRef(null);
|
|
12
|
+
const onClickHandler = (event) => {
|
|
13
|
+
fireCancelableEvent(onItemClick, { id: event.detail.id }, event);
|
|
14
|
+
};
|
|
15
|
+
return (React.createElement(ButtonDropdown, { ref: ref, variant: "icon", loading: item.loading, loadingText: item.loadingText, disabled: item.disabled, items: item.items, onItemClick: onClickHandler, expandToViewport: expandToViewport, ariaLabel: item.text, className: testUtilStyles['button-group-item'], "data-testid": item.id, customTriggerBuilder: ({ onClick, isOpen, triggerRef, ariaLabel, ariaExpanded, testUtilsClass }) => (React.createElement("div", { ref: containerRef },
|
|
16
|
+
!isOpen && showTooltip && !item.disabled && !item.loading && (React.createElement(Tooltip, { trackRef: containerRef, trackKey: item.id, value: item.text, className: clsx(testUtilStyles.tooltip, testUtilStyles['button-group-tooltip']) })),
|
|
17
|
+
React.createElement(InternalButton, { ref: triggerRef, variant: "icon", ariaLabel: ariaLabel, "data-itemid": item.id, ariaExpanded: ariaExpanded, className: clsx(testUtilStyles.item, testUtilsClass), iconName: "ellipsis", onClick: onClick, __title: "" }))) }));
|
|
18
|
+
});
|
|
19
|
+
export default MenuDropdownItem;
|
|
20
|
+
//# sourceMappingURL=menu-dropdown-item.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"menu-dropdown-item.js","sourceRoot":"","sources":["../../../src/button-group/menu-dropdown-item.tsx"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,sCAAsC;AACtC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,cAAc,MAAM,oBAAoB,CAAC;AAEhD,OAAO,cAAc,MAAM,6BAA6B,CAAC;AACzD,OAAO,OAAO,MAAM,gCAAgC,CAAC;AACrD,OAAO,EAA0B,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAGjF,OAAO,cAAc,MAAM,8BAA8B,CAAC;AAS1D,MAAM,gBAAgB,GAAG,KAAK,CAAC,UAAU,CACvC,CACE,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,gBAAgB,EAAyB,EAC3E,GAAuC,EACvC,EAAE;IACF,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAiB,IAAI,CAAC,CAAC;IACxD,MAAM,cAAc,GAAG,CAAC,KAAwD,EAAE,EAAE;QAClF,mBAAmB,CAAC,WAAW,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;IACnE,CAAC,CAAC;IAEF,OAAO,CACL,oBAAC,cAAc,IACb,GAAG,EAAE,GAAG,EACR,OAAO,EAAC,MAAM,EACd,OAAO,EAAE,IAAI,CAAC,OAAO,EACrB,WAAW,EAAE,IAAI,CAAC,WAAW,EAC7B,QAAQ,EAAE,IAAI,CAAC,QAAQ,EACvB,KAAK,EAAE,IAAI,CAAC,KAAK,EACjB,WAAW,EAAE,cAAc,EAC3B,gBAAgB,EAAE,gBAAgB,EAClC,SAAS,EAAE,IAAI,CAAC,IAAI,EACpB,SAAS,EAAE,cAAc,CAAC,mBAAmB,CAAC,iBACjC,IAAI,CAAC,EAAE,EACpB,oBAAoB,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC,CAClG,6BAAK,GAAG,EAAE,YAAY;YACnB,CAAC,MAAM,IAAI,WAAW,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAC5D,oBAAC,OAAO,IACN,QAAQ,EAAE,YAAY,EACtB,QAAQ,EAAE,IAAI,CAAC,EAAE,EACjB,KAAK,EAAE,IAAI,CAAC,IAAI,EAChB,SAAS,EAAE,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,cAAc,CAAC,sBAAsB,CAAC,CAAC,GAC/E,CACH;YACD,oBAAC,cAAc,IACb,GAAG,EAAE,UAAU,EACf,OAAO,EAAC,MAAM,EACd,SAAS,EAAE,SAAS,iBACP,IAAI,CAAC,EAAE,EACpB,YAAY,EAAE,YAAY,EAC1B,SAAS,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,cAAc,CAAC,EACpD,QAAQ,EAAC,UAAU,EACnB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAC,EAAE,GACV,CACE,CACP,GACD,CACH,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,eAAe,gBAAgB,CAAC","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport React from 'react';\nimport clsx from 'clsx';\n\nimport InternalButton from '../button/internal';\nimport { ButtonDropdownProps } from '../button-dropdown/interfaces';\nimport ButtonDropdown from '../button-dropdown/internal';\nimport Tooltip from '../internal/components/tooltip';\nimport { CancelableEventHandler, fireCancelableEvent } from '../internal/events';\nimport { ButtonGroupProps } from './interfaces';\n\nimport testUtilStyles from './test-classes/styles.css.js';\n\ninterface MenuDropdownItemProps {\n item: ButtonGroupProps.MenuDropdown;\n showTooltip: boolean;\n onItemClick?: CancelableEventHandler<ButtonGroupProps.ItemClickDetails>;\n expandToViewport?: boolean;\n}\n\nconst MenuDropdownItem = React.forwardRef(\n (\n { item, showTooltip, onItemClick, expandToViewport }: MenuDropdownItemProps,\n ref: React.Ref<ButtonDropdownProps.Ref>\n ) => {\n const containerRef = React.useRef<HTMLDivElement>(null);\n const onClickHandler = (event: CustomEvent<ButtonDropdownProps.ItemClickDetails>) => {\n fireCancelableEvent(onItemClick, { id: event.detail.id }, event);\n };\n\n return (\n <ButtonDropdown\n ref={ref}\n variant=\"icon\"\n loading={item.loading}\n loadingText={item.loadingText}\n disabled={item.disabled}\n items={item.items}\n onItemClick={onClickHandler}\n expandToViewport={expandToViewport}\n ariaLabel={item.text}\n className={testUtilStyles['button-group-item']}\n data-testid={item.id}\n customTriggerBuilder={({ onClick, isOpen, triggerRef, ariaLabel, ariaExpanded, testUtilsClass }) => (\n <div ref={containerRef}>\n {!isOpen && showTooltip && !item.disabled && !item.loading && (\n <Tooltip\n trackRef={containerRef}\n trackKey={item.id}\n value={item.text}\n className={clsx(testUtilStyles.tooltip, testUtilStyles['button-group-tooltip'])}\n />\n )}\n <InternalButton\n ref={triggerRef}\n variant=\"icon\"\n ariaLabel={ariaLabel}\n data-itemid={item.id}\n ariaExpanded={ariaExpanded}\n className={clsx(testUtilStyles.item, testUtilsClass)}\n iconName=\"ellipsis\"\n onClick={onClick}\n __title=\"\"\n />\n </div>\n )}\n />\n );\n }\n);\n\nexport default MenuDropdownItem;\n"]}
|