@box/blueprint-web 12.113.0 → 12.115.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib-esm/grid-list-v2/grid-list-v2.d.ts +5 -0
- package/dist/lib-esm/grid-list-v2/grid-list-v2.js +21 -0
- package/dist/lib-esm/grid-list-v2/index.d.ts +11 -0
- package/dist/lib-esm/grid-list-v2/index.js +17 -0
- package/dist/lib-esm/grid-list-v2/types.d.ts +12 -0
- package/dist/lib-esm/index.css +390 -101
- package/dist/lib-esm/index.d.ts +1 -0
- package/dist/lib-esm/index.js +1 -0
- package/dist/lib-esm/modal/alert-modal.d.ts +1 -1
- package/dist/lib-esm/modal/alert-modal.js +5 -2
- package/dist/lib-esm/modal/alert-modal.types.d.ts +2 -0
- package/dist/lib-esm/types/file-category.d.ts +11 -0
- package/dist/lib-esm/util-components/base-grid-list-item/base-grid-list-item-actions.js +19 -5
- package/dist/lib-esm/util-components/base-grid-list-item/base-grid-list-item-header.js +5 -2
- package/dist/lib-esm/util-components/base-grid-list-item/base-grid-list-item-subtitle.js +5 -2
- package/dist/lib-esm/util-components/base-grid-list-item/base-grid-list-item-thumbnail.js +106 -4
- package/dist/lib-esm/util-components/base-grid-list-item/base-grid-list-item.js +58 -6
- package/dist/lib-esm/util-components/base-grid-list-item/base-grid-list-item.module.js +1 -1
- package/dist/lib-esm/util-components/base-grid-list-item/base-grid-list.js +12 -2
- package/dist/lib-esm/util-components/base-grid-list-item/index.d.ts +1 -1
- package/dist/lib-esm/util-components/base-grid-list-item/types.d.ts +91 -3
- package/package.json +3 -3
package/dist/lib-esm/index.d.ts
CHANGED
|
@@ -25,6 +25,7 @@ export * from './empty-state';
|
|
|
25
25
|
export * from './focusable';
|
|
26
26
|
export * from './ghost';
|
|
27
27
|
export * from './grid-list-item';
|
|
28
|
+
export * from './grid-list-v2';
|
|
28
29
|
export * from './guided-tooltip';
|
|
29
30
|
export * from './icon-dual-state-button';
|
|
30
31
|
export * from './icon-toggle-button';
|
package/dist/lib-esm/index.js
CHANGED
|
@@ -32,6 +32,7 @@ export { EmptyState } from './empty-state/empty-state.js';
|
|
|
32
32
|
export { Focusable } from './focusable/focusable.js';
|
|
33
33
|
export { Ghost } from './ghost/ghost.js';
|
|
34
34
|
export { GridList } from './grid-list-item/index.js';
|
|
35
|
+
export { GridListV2 } from './grid-list-v2/index.js';
|
|
35
36
|
export { GuidedTooltip } from './guided-tooltip/guided-tooltip.js';
|
|
36
37
|
export { GuidedTooltipContext } from './guided-tooltip/utils/guided-tooltip-context.js';
|
|
37
38
|
export { IconDualStateButton } from './icon-dual-state-button/icon-dual-state-button.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type AlertModalProps } from './alert-modal.types';
|
|
2
2
|
export declare const AlertModal: {
|
|
3
|
-
({ children, closeButtonAriaLabel, container, heading, onOpenChange, open, size, textContent, ...props }: AlertModalProps): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
({ children, closeButtonAriaLabel, closeButtonDisabled, container, heading, onOpenChange, open, size, textContent, ...props }: AlertModalProps): import("react/jsx-runtime").JSX.Element;
|
|
4
4
|
displayName: string;
|
|
5
5
|
} & {
|
|
6
6
|
PrimaryButton: import("react").ForwardRefExoticComponent<(Omit<import("../primitives/base-button").BaseButtonInterface & Required<Pick<import("../primitives/base-button").Loading, keyof import("../primitives/base-button").Loading>> & Omit<import("../primitives/base-button").Loading, keyof import("../primitives/base-button").Loading> & {
|
|
@@ -25,13 +25,14 @@ const validateChildren = children => {
|
|
|
25
25
|
* - Only accepts text as content
|
|
26
26
|
* - Has role="alertdialog" for accessibility
|
|
27
27
|
* - Announces the content of the modal to the user when it is opened
|
|
28
|
-
* - Always includes a close button with i18n support
|
|
28
|
+
* - Always includes a close button with i18n support (disabled state can be controlled via closeButtonDisabled prop)
|
|
29
29
|
*
|
|
30
30
|
* @example
|
|
31
31
|
* <AlertModal
|
|
32
32
|
* open={isOpen}
|
|
33
33
|
* onOpenChange={setIsOpen}
|
|
34
34
|
* heading="Delete Item"
|
|
35
|
+
* closeButtonDisabled={isSubmittingRequest}
|
|
35
36
|
* textContent="Are you sure you want to delete this item?"
|
|
36
37
|
* closeButtonAriaLabel={formatMessage(commonMessages.closeButtonText)}
|
|
37
38
|
* >
|
|
@@ -46,6 +47,7 @@ const validateChildren = children => {
|
|
|
46
47
|
const AlertModalComponent = ({
|
|
47
48
|
children,
|
|
48
49
|
closeButtonAriaLabel,
|
|
50
|
+
closeButtonDisabled = false,
|
|
49
51
|
container,
|
|
50
52
|
heading,
|
|
51
53
|
onOpenChange,
|
|
@@ -75,7 +77,8 @@ const AlertModalComponent = ({
|
|
|
75
77
|
}), jsx(Modal.Footer, {
|
|
76
78
|
children: children
|
|
77
79
|
}), jsx(Modal.Close, {
|
|
78
|
-
"aria-label": closeButtonAriaLabel
|
|
80
|
+
"aria-label": closeButtonAriaLabel,
|
|
81
|
+
disabled: closeButtonDisabled
|
|
79
82
|
})]
|
|
80
83
|
})
|
|
81
84
|
});
|
|
@@ -12,4 +12,6 @@ export interface AlertModalProps extends Omit<DialogProps, 'modal'>, Pick<Dialog
|
|
|
12
12
|
size?: ModalContentSize;
|
|
13
13
|
/** Aria label for the close button. Should be an i18n string. */
|
|
14
14
|
closeButtonAriaLabel: string;
|
|
15
|
+
/** Whether to disable the close button. Defaults to false. */
|
|
16
|
+
closeButtonDisabled?: boolean;
|
|
15
17
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File category type for categorizing files by their type/format.
|
|
3
|
+
*
|
|
4
|
+
* These categories match those returned by `getFileIconType` from `@box/item-icon`.
|
|
5
|
+
* Due to circular dependency constraints, `@box/blueprint-web` cannot directly import
|
|
6
|
+
* `@box/item-icon`, so consumers should use `getFileIconType` in their own code to
|
|
7
|
+
* map file extensions to categories.
|
|
8
|
+
*
|
|
9
|
+
* @see {@link https://git.dev.box.net/Box/frontend-mono/tree/master/packages/group-shared-features/item-icon | @box/item-icon}
|
|
10
|
+
*/
|
|
11
|
+
export type FileCategory = 'audio' | 'boxcanvas' | 'boxnote' | 'code' | 'document' | 'docuworks-binder' | 'docuworks-file' | 'dwg' | 'excel-spreadsheet' | 'google-docs' | 'google-sheets' | 'google-slides' | 'illustrator' | 'image' | 'indesign' | 'keynote' | 'numbers' | 'pages' | 'pdf' | 'photoshop' | 'powerpoint-presentation' | 'presentation' | 'spreadsheet' | 'text' | 'threed' | 'vector' | 'video' | 'word-document' | 'zip';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import { Pin } from '@box/blueprint-web-assets/icons/Fill';
|
|
3
3
|
import clsx from 'clsx';
|
|
4
|
-
import { forwardRef, useCallback, useRef } from 'react';
|
|
4
|
+
import { forwardRef, useCallback, useRef, useEffect } from 'react';
|
|
5
5
|
import { mergeProps } from 'react-aria';
|
|
6
6
|
import { TooltipTrigger } from 'react-aria-components';
|
|
7
7
|
import { IconButton } from '../../primitives/icon-button/icon-button.js';
|
|
@@ -37,14 +37,23 @@ const BaseListActions = ({
|
|
|
37
37
|
const GridListActions = ({
|
|
38
38
|
children,
|
|
39
39
|
selectionEnabled,
|
|
40
|
-
isSelectionCheckboxDisabled
|
|
40
|
+
isSelectionCheckboxDisabled,
|
|
41
|
+
centerText,
|
|
42
|
+
setHasActions
|
|
41
43
|
}) => {
|
|
44
|
+
const hasChildren = children !== null && children !== undefined && children !== false;
|
|
45
|
+
// Communicate action button presence to parent context for subtitle visibility logic
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
setHasActions(hasChildren);
|
|
48
|
+
}, [hasChildren, setHasActions]);
|
|
42
49
|
return jsxs(Fragment, {
|
|
43
50
|
children: [selectionEnabled && jsx(ListCheckbox, {
|
|
44
51
|
className: styles.selection,
|
|
45
52
|
isDisabled: isSelectionCheckboxDisabled
|
|
46
53
|
}), jsx("div", {
|
|
47
|
-
className: styles.inner,
|
|
54
|
+
className: clsx(styles.inner, {
|
|
55
|
+
[styles.innerCentered]: centerText
|
|
56
|
+
}),
|
|
48
57
|
children: children
|
|
49
58
|
})]
|
|
50
59
|
});
|
|
@@ -90,7 +99,8 @@ const BaseGridListActionIconButton = /*#__PURE__*/forwardRef(function BaseGridLi
|
|
|
90
99
|
const BaseGridListActions = /*#__PURE__*/forwardRef(function BaseGridListActions(props, forwardedRef) {
|
|
91
100
|
const {
|
|
92
101
|
layoutStyle,
|
|
93
|
-
selectionMode
|
|
102
|
+
selectionMode,
|
|
103
|
+
centerText
|
|
94
104
|
} = useBaseGridListContext();
|
|
95
105
|
const {
|
|
96
106
|
children,
|
|
@@ -102,7 +112,8 @@ const BaseGridListActions = /*#__PURE__*/forwardRef(function BaseGridListActions
|
|
|
102
112
|
loading,
|
|
103
113
|
pinned,
|
|
104
114
|
pinAriaLabel,
|
|
105
|
-
setIsItemInteracted
|
|
115
|
+
setIsItemInteracted,
|
|
116
|
+
setHasActions
|
|
106
117
|
} = useBaseGridListItemContext();
|
|
107
118
|
const divRef = useRef(null);
|
|
108
119
|
const forkRef = useForkRef(divRef, forwardedRef);
|
|
@@ -110,6 +121,7 @@ const BaseGridListActions = /*#__PURE__*/forwardRef(function BaseGridListActions
|
|
|
110
121
|
return null;
|
|
111
122
|
}
|
|
112
123
|
const isList = layoutStyle === 'list' || layoutStyle === 'small-list';
|
|
124
|
+
const isGridV2 = layoutStyle === 'grid-v2';
|
|
113
125
|
const isSelectionEnabled = selectionMode === 'multiple';
|
|
114
126
|
const isRenderPropUsed = typeof children === 'function';
|
|
115
127
|
return jsxs(Fragment, {
|
|
@@ -122,8 +134,10 @@ const BaseGridListActions = /*#__PURE__*/forwardRef(function BaseGridListActions
|
|
|
122
134
|
selectionEnabled: isSelectionEnabled,
|
|
123
135
|
children: isRenderPropUsed ? children(setIsItemInteracted) : children
|
|
124
136
|
}) : jsx(GridListActions, {
|
|
137
|
+
centerText: isGridV2 && centerText,
|
|
125
138
|
isSelectionCheckboxDisabled: isSelectionCheckboxDisabled,
|
|
126
139
|
selectionEnabled: isSelectionEnabled,
|
|
140
|
+
setHasActions: setHasActions,
|
|
127
141
|
children: isRenderPropUsed ? children(setIsItemInteracted) : children
|
|
128
142
|
})
|
|
129
143
|
}), pinned && jsx(Status, {
|
|
@@ -20,7 +20,8 @@ const BaseGridListHeader = /*#__PURE__*/forwardRef(function BaseGridListHeader(p
|
|
|
20
20
|
loading
|
|
21
21
|
} = useBaseGridListItemContext();
|
|
22
22
|
const {
|
|
23
|
-
layoutStyle
|
|
23
|
+
layoutStyle,
|
|
24
|
+
centerText
|
|
24
25
|
} = useBaseGridListContext();
|
|
25
26
|
const {
|
|
26
27
|
Wrapper,
|
|
@@ -33,6 +34,7 @@ const BaseGridListHeader = /*#__PURE__*/forwardRef(function BaseGridListHeader(p
|
|
|
33
34
|
});
|
|
34
35
|
const isLargeItem = layoutStyle === 'list';
|
|
35
36
|
const isSmallListItem = layoutStyle === 'small-list';
|
|
37
|
+
const isGridV2 = layoutStyle === 'grid-v2';
|
|
36
38
|
return (
|
|
37
39
|
// @ts-expect-error Fix this type error
|
|
38
40
|
jsx(Wrapper, {
|
|
@@ -41,7 +43,8 @@ const BaseGridListHeader = /*#__PURE__*/forwardRef(function BaseGridListHeader(p
|
|
|
41
43
|
...rest,
|
|
42
44
|
ref: useForkRef(ref, forwardedRef),
|
|
43
45
|
className: clsx(styles.header, {
|
|
44
|
-
[styles.loading]: loading
|
|
46
|
+
[styles.loading]: loading,
|
|
47
|
+
[styles.textCentered]: isGridV2 && centerText
|
|
45
48
|
}, className),
|
|
46
49
|
children: loading ? jsx(Ghost, {
|
|
47
50
|
borderRadius: isSmallListItem ? '2rem' : undefined,
|
|
@@ -19,7 +19,8 @@ const BaseGridListSubtitle = /*#__PURE__*/forwardRef(function BaseGridListSubtit
|
|
|
19
19
|
loading
|
|
20
20
|
} = useBaseGridListItemContext();
|
|
21
21
|
const {
|
|
22
|
-
layoutStyle
|
|
22
|
+
layoutStyle,
|
|
23
|
+
centerText
|
|
23
24
|
} = useBaseGridListContext();
|
|
24
25
|
const {
|
|
25
26
|
Wrapper,
|
|
@@ -30,6 +31,7 @@ const BaseGridListSubtitle = /*#__PURE__*/forwardRef(function BaseGridListSubtit
|
|
|
30
31
|
skipOverflowCheck: loading
|
|
31
32
|
});
|
|
32
33
|
const isGridItem = layoutStyle === 'grid';
|
|
34
|
+
const isGridV2 = layoutStyle === 'grid-v2';
|
|
33
35
|
const isSmallListItem = layoutStyle === 'small-list';
|
|
34
36
|
const forkRef = useForkRef(ref, forwardedRef);
|
|
35
37
|
if (isSmallListItem && loading) {
|
|
@@ -44,7 +46,8 @@ const BaseGridListSubtitle = /*#__PURE__*/forwardRef(function BaseGridListSubtit
|
|
|
44
46
|
...rest,
|
|
45
47
|
ref: forkRef,
|
|
46
48
|
className: clsx(styles.subtitle, {
|
|
47
|
-
[styles.loading]: loading
|
|
49
|
+
[styles.loading]: loading,
|
|
50
|
+
[styles.textCentered]: isGridV2 && centerText
|
|
48
51
|
}, className),
|
|
49
52
|
children: loading ? jsx(Ghost, {
|
|
50
53
|
variant: "rectangle",
|
|
@@ -1,21 +1,108 @@
|
|
|
1
|
-
import { jsx } from 'react/jsx-runtime';
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
3
|
import { forwardRef } from 'react';
|
|
4
4
|
import { Ghost } from '../../ghost/ghost.js';
|
|
5
|
+
import { Text } from '../../text/text.js';
|
|
5
6
|
import { useBaseGridListItemContext } from './base-grid-list-item.js';
|
|
6
7
|
import styles from './base-grid-list-item.module.js';
|
|
7
8
|
|
|
9
|
+
// Color tokens grouped by visual color to minimize bundle size
|
|
10
|
+
// Each token uses Blueprint variable with legacy fallback
|
|
11
|
+
const C = {
|
|
12
|
+
// Watermelon Red 120 (#BE2C46) - pdf, powerpoint-presentation, code
|
|
13
|
+
red: 'var(--bp-watermelon-red-120, var(--watermelon-red-120))',
|
|
14
|
+
// Orange 130 (#A95A12) - boxcanvas, threed, vector, pages, google-slides, illustrator, presentation
|
|
15
|
+
orange: 'var(--bp-orange-130, var(--orange-120))',
|
|
16
|
+
// Green Light 135 (#197E54) - image, excel-spreadsheet, numbers, google-sheets, spreadsheet
|
|
17
|
+
green: 'var(--bp-green-light-135, var(--green-light-120))',
|
|
18
|
+
// Light Blue 115 (#1F72D6) - photoshop, dwg, keynote, video
|
|
19
|
+
lightBlue: 'var(--bp-light-blue-115, var(--light-blue-110))',
|
|
20
|
+
// Light Blue 135 (#1757A4) - word-document, google-docs, text
|
|
21
|
+
darkBlue: 'var(--bp-light-blue-135, var(--light-blue-120))',
|
|
22
|
+
// Purple Rain 100 (#9F3FED) - audio
|
|
23
|
+
purple: 'var(--bp-purple-rain-100, var(--purple-rain-100))',
|
|
24
|
+
// Text on Light (#222222) - default for unspecified categories
|
|
25
|
+
gray: 'var(--bp-gray-100, var(--gray-100))'
|
|
26
|
+
};
|
|
27
|
+
/** Color mapping for file categories, optimized for bundle size */
|
|
28
|
+
const FILE_CATEGORY_COLORS = {
|
|
29
|
+
// Purple Rain 100
|
|
30
|
+
audio: C.purple,
|
|
31
|
+
// Orange 130
|
|
32
|
+
boxcanvas: C.orange,
|
|
33
|
+
// Default (text-on-light)
|
|
34
|
+
boxnote: C.gray,
|
|
35
|
+
// Watermelon Red 120
|
|
36
|
+
code: C.red,
|
|
37
|
+
// Default (text-on-light)
|
|
38
|
+
document: C.gray,
|
|
39
|
+
// Default (text-on-light)
|
|
40
|
+
'docuworks-binder': C.gray,
|
|
41
|
+
// Green Light 135
|
|
42
|
+
'docuworks-file': C.green,
|
|
43
|
+
// Light Blue 115
|
|
44
|
+
dwg: C.lightBlue,
|
|
45
|
+
// Green Light 135
|
|
46
|
+
'excel-spreadsheet': C.green,
|
|
47
|
+
// Light Blue 135
|
|
48
|
+
'google-docs': C.darkBlue,
|
|
49
|
+
// Green Light 135
|
|
50
|
+
'google-sheets': C.green,
|
|
51
|
+
// Orange 130
|
|
52
|
+
'google-slides': C.orange,
|
|
53
|
+
// Orange 130
|
|
54
|
+
illustrator: C.orange,
|
|
55
|
+
// Green Light 135
|
|
56
|
+
image: C.green,
|
|
57
|
+
// Default (text-on-light)
|
|
58
|
+
indesign: C.gray,
|
|
59
|
+
// Light Blue 115
|
|
60
|
+
keynote: C.lightBlue,
|
|
61
|
+
// Green Light 135
|
|
62
|
+
numbers: C.green,
|
|
63
|
+
// Orange 130
|
|
64
|
+
pages: C.orange,
|
|
65
|
+
// Watermelon Red 120
|
|
66
|
+
pdf: C.red,
|
|
67
|
+
// Light Blue 115
|
|
68
|
+
photoshop: C.lightBlue,
|
|
69
|
+
// Watermelon Red 120
|
|
70
|
+
'powerpoint-presentation': C.red,
|
|
71
|
+
// Orange 130
|
|
72
|
+
presentation: C.orange,
|
|
73
|
+
// Green Light 135
|
|
74
|
+
spreadsheet: C.green,
|
|
75
|
+
// Light Blue 135
|
|
76
|
+
text: C.darkBlue,
|
|
77
|
+
// Orange 130
|
|
78
|
+
threed: C.orange,
|
|
79
|
+
// Orange 130
|
|
80
|
+
vector: C.orange,
|
|
81
|
+
// Light Blue 115
|
|
82
|
+
video: C.lightBlue,
|
|
83
|
+
// Light Blue 135
|
|
84
|
+
'word-document': C.darkBlue,
|
|
85
|
+
// Default (text-on-light)
|
|
86
|
+
zip: C.gray
|
|
87
|
+
};
|
|
8
88
|
const BaseGridListThumbnail = /*#__PURE__*/forwardRef(function BaseGridListThumbnail(props, forwardedRef) {
|
|
9
89
|
const {
|
|
10
90
|
children,
|
|
11
91
|
className,
|
|
12
92
|
hasCustomSize,
|
|
93
|
+
fileExtension,
|
|
94
|
+
fileCategory,
|
|
95
|
+
statusBadge,
|
|
13
96
|
...rest
|
|
14
97
|
} = props;
|
|
15
98
|
const {
|
|
16
99
|
loading
|
|
17
100
|
} = useBaseGridListItemContext();
|
|
18
|
-
|
|
101
|
+
// Normalize file extension to uppercase for display (e.g., "pdf" → "PDF")
|
|
102
|
+
const normalizedExtension = fileExtension?.toUpperCase();
|
|
103
|
+
const extensionColor = fileCategory ? FILE_CATEGORY_COLORS[fileCategory] : undefined;
|
|
104
|
+
const hasBadges = !loading && (statusBadge || normalizedExtension);
|
|
105
|
+
return jsxs("div", {
|
|
19
106
|
...rest,
|
|
20
107
|
ref: forwardedRef,
|
|
21
108
|
className: clsx(styles.thumbnail, {
|
|
@@ -23,10 +110,25 @@ const BaseGridListThumbnail = /*#__PURE__*/forwardRef(function BaseGridListThumb
|
|
|
23
110
|
}, {
|
|
24
111
|
[styles.thumbnailContent]: !hasCustomSize
|
|
25
112
|
}, className),
|
|
26
|
-
children: loading ? jsx(Ghost, {
|
|
113
|
+
children: [loading ? jsx(Ghost, {
|
|
27
114
|
borderRadius: "0.5rem",
|
|
28
115
|
height: "100%"
|
|
29
|
-
}) : children
|
|
116
|
+
}) : children, hasBadges && jsxs("div", {
|
|
117
|
+
className: styles.thumbnailBadges,
|
|
118
|
+
children: [statusBadge && jsx("span", {
|
|
119
|
+
className: styles.statusBadge,
|
|
120
|
+
children: statusBadge
|
|
121
|
+
}), normalizedExtension && jsx(Text, {
|
|
122
|
+
as: "span",
|
|
123
|
+
className: styles.fileTypePill,
|
|
124
|
+
"data-file-type": normalizedExtension,
|
|
125
|
+
style: extensionColor ? {
|
|
126
|
+
color: extensionColor
|
|
127
|
+
} : undefined,
|
|
128
|
+
variant: "caption",
|
|
129
|
+
children: normalizedExtension
|
|
130
|
+
})]
|
|
131
|
+
})]
|
|
30
132
|
});
|
|
31
133
|
});
|
|
32
134
|
|
|
@@ -4,20 +4,28 @@ import noop from 'lodash/noop';
|
|
|
4
4
|
import { forwardRef, useState, useMemo, createContext, useContext } from 'react';
|
|
5
5
|
import { GridListItem } from 'react-aria-components';
|
|
6
6
|
import { useDebounce } from '../../utils/use-debounce.js';
|
|
7
|
-
import { StaticGridListItem } from './static-grid-list-item.js';
|
|
8
7
|
import { useBaseGridListContext } from './base-grid-list.js';
|
|
9
8
|
import styles from './base-grid-list-item.module.js';
|
|
9
|
+
import { StaticGridListItem } from './static-grid-list-item.js';
|
|
10
10
|
|
|
11
11
|
const BaseGridListItemContext = /*#__PURE__*/createContext({
|
|
12
12
|
loading: false,
|
|
13
13
|
pinned: false,
|
|
14
14
|
pinAriaLabel: undefined,
|
|
15
15
|
setIsItemInteracted: noop,
|
|
16
|
-
isItemInteracted: false
|
|
16
|
+
isItemInteracted: false,
|
|
17
|
+
hasActions: false,
|
|
18
|
+
setHasActions: noop
|
|
17
19
|
});
|
|
18
20
|
const useBaseGridListItemContext = () => {
|
|
19
21
|
return useContext(BaseGridListItemContext);
|
|
20
22
|
};
|
|
23
|
+
/**
|
|
24
|
+
* CSS selectors for grid-v2 click handling (defined outside component to save bundle size).
|
|
25
|
+
* Combined into single strings to reduce .closest() calls.
|
|
26
|
+
*/
|
|
27
|
+
const CHECKBOX_SELECTOR = '[class*="selection"], input[type="checkbox"]';
|
|
28
|
+
const INTERACTIVE_SELECTOR = 'button, a, input, [role="button"], [class*="actions"]';
|
|
21
29
|
const BaseGridListItem = /*#__PURE__*/forwardRef(function BaseGridListItem(props, forwardedRef) {
|
|
22
30
|
const {
|
|
23
31
|
children,
|
|
@@ -29,10 +37,12 @@ const BaseGridListItem = /*#__PURE__*/forwardRef(function BaseGridListItem(props
|
|
|
29
37
|
} = props;
|
|
30
38
|
const {
|
|
31
39
|
layoutStyle,
|
|
32
|
-
isInteractive
|
|
40
|
+
isInteractive,
|
|
41
|
+
onAction
|
|
33
42
|
} = useBaseGridListContext();
|
|
34
43
|
const textValue = typeof rest.textValue === 'string' ? rest.textValue : undefined;
|
|
35
44
|
const [isItemInteracted, setIsItemInteracted] = useState(false);
|
|
45
|
+
const [hasActions, setHasActions] = useState(false);
|
|
36
46
|
// Use debounce with a small delay to make sure there is style flashing finishing interaction (e.g. closing dropdown)
|
|
37
47
|
const debouncedIsItemInteracted = useDebounce(isItemInteracted, 50);
|
|
38
48
|
const context = useMemo(() => ({
|
|
@@ -40,8 +50,10 @@ const BaseGridListItem = /*#__PURE__*/forwardRef(function BaseGridListItem(props
|
|
|
40
50
|
pinned,
|
|
41
51
|
pinAriaLabel,
|
|
42
52
|
isItemInteracted,
|
|
43
|
-
setIsItemInteracted
|
|
44
|
-
|
|
53
|
+
setIsItemInteracted,
|
|
54
|
+
hasActions,
|
|
55
|
+
setHasActions
|
|
56
|
+
}), [loading, pinned, pinAriaLabel, isItemInteracted, hasActions]);
|
|
45
57
|
let layoutStyleClass;
|
|
46
58
|
switch (layoutStyle) {
|
|
47
59
|
case 'list':
|
|
@@ -50,10 +62,42 @@ const BaseGridListItem = /*#__PURE__*/forwardRef(function BaseGridListItem(props
|
|
|
50
62
|
case 'grid':
|
|
51
63
|
layoutStyleClass = styles.gridListItem;
|
|
52
64
|
break;
|
|
65
|
+
case 'grid-v2':
|
|
66
|
+
layoutStyleClass = styles.gridListV2Item;
|
|
67
|
+
break;
|
|
53
68
|
case 'small-list':
|
|
54
69
|
layoutStyleClass = styles.smallListItem;
|
|
55
70
|
}
|
|
56
71
|
const GridListItem$1 = isInteractive ? GridListItem : StaticGridListItem;
|
|
72
|
+
const isGridV2 = layoutStyle === 'grid-v2';
|
|
73
|
+
/**
|
|
74
|
+
* Grid-v2 click behavior fix:
|
|
75
|
+
*
|
|
76
|
+
* WHY V2 NEEDS THIS BUT V1 DOESN'T:
|
|
77
|
+
* V1's CSS uses minmax() for grid rows, so content fills most of the clickable area.
|
|
78
|
+
* V2 has explicit padding creating empty space that triggers unwanted selection. This padding is needed to make space for
|
|
79
|
+
* the seclection and focus outline states which uses psuedo elements to create the outline.
|
|
80
|
+
*
|
|
81
|
+
* WHAT THIS DOES:
|
|
82
|
+
* - Checkbox clicks: propagate → toggle selection
|
|
83
|
+
* - Action buttons: propagate → button handlers fire
|
|
84
|
+
* - Content/empty space: stop propagation, trigger onAction
|
|
85
|
+
*/
|
|
86
|
+
const handleContentPointerDown = e => {
|
|
87
|
+
const target = e.target;
|
|
88
|
+
// Allow checkbox and interactive element clicks to propagate normally
|
|
89
|
+
if (target.closest(CHECKBOX_SELECTOR) || target.closest(INTERACTIVE_SELECTOR)) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
// Stop propagation for content clicks, then trigger onAction
|
|
93
|
+
e.stopPropagation();
|
|
94
|
+
const itemKey = rest.id ?? textValue;
|
|
95
|
+
if (onAction && itemKey) {
|
|
96
|
+
onAction(itemKey);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
// Only apply pointer handler for grid-v2 in interactive mode
|
|
100
|
+
const pointerDownHandler = isGridV2 && isInteractive ? handleContentPointerDown : undefined;
|
|
57
101
|
return jsx(GridListItem$1, {
|
|
58
102
|
...rest,
|
|
59
103
|
ref: forwardedRef,
|
|
@@ -61,11 +105,19 @@ const BaseGridListItem = /*#__PURE__*/forwardRef(function BaseGridListItem(props
|
|
|
61
105
|
[styles.loading]: loading
|
|
62
106
|
}, {
|
|
63
107
|
[styles.isItemInteracted]: isItemInteracted || debouncedIsItemInteracted
|
|
108
|
+
},
|
|
109
|
+
// In grid-v2, keep subtitle visible on hover/focus when there are no action buttons
|
|
110
|
+
{
|
|
111
|
+
[styles.noActions]: isGridV2 && !hasActions
|
|
64
112
|
}, className),
|
|
65
113
|
textValue: textValue,
|
|
66
114
|
children: jsx(BaseGridListItemContext.Provider, {
|
|
67
115
|
value: context,
|
|
68
|
-
children:
|
|
116
|
+
children: pointerDownHandler ? jsx("div", {
|
|
117
|
+
className: styles.gridV2ClickShield,
|
|
118
|
+
onPointerDownCapture: pointerDownHandler,
|
|
119
|
+
children: children
|
|
120
|
+
}) : children
|
|
69
121
|
})
|
|
70
122
|
});
|
|
71
123
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import '../../index.css';
|
|
2
|
-
var styles = {"smallList":"bp_base_grid_list_item_module_smallList--
|
|
2
|
+
var styles = {"smallList":"bp_base_grid_list_item_module_smallList--33914","smallListItem":"bp_base_grid_list_item_module_smallListItem--33914","header":"bp_base_grid_list_item_module_header--33914","subtitle":"bp_base_grid_list_item_module_subtitle--33914","loading":"bp_base_grid_list_item_module_loading--33914","thumbnail":"bp_base_grid_list_item_module_thumbnail--33914","thumbnailContent":"bp_base_grid_list_item_module_thumbnailContent--33914","actions":"bp_base_grid_list_item_module_actions--33914","selection":"bp_base_grid_list_item_module_selection--33914","inner":"bp_base_grid_list_item_module_inner--33914","actionsCheckboxWrapper":"bp_base_grid_list_item_module_actionsCheckboxWrapper--33914","largeList":"bp_base_grid_list_item_module_largeList--33914","largeListItem":"bp_base_grid_list_item_module_largeListItem--33914","fade":"bp_base_grid_list_item_module_fade--33914","description":"bp_base_grid_list_item_module_description--33914","snippet":"bp_base_grid_list_item_module_snippet--33914","snippetContent":"bp_base_grid_list_item_module_snippetContent--33914","gridList":"bp_base_grid_list_item_module_gridList--33914","gridListItem":"bp_base_grid_list_item_module_gridListItem--33914","statusPin":"bp_base_grid_list_item_module_statusPin--33914","isItemInteracted":"bp_base_grid_list_item_module_isItemInteracted--33914","tooltipContent":"bp_base_grid_list_item_module_tooltipContent--33914","tooltipArrow":"bp_base_grid_list_item_module_tooltipArrow--33914","gridListV2":"bp_base_grid_list_item_module_gridListV2--33914","gridListV2Item":"bp_base_grid_list_item_module_gridListV2Item--33914","noActions":"bp_base_grid_list_item_module_noActions--33914","thumbnailBadges":"bp_base_grid_list_item_module_thumbnailBadges--33914","statusBadge":"bp_base_grid_list_item_module_statusBadge--33914","fileTypePill":"bp_base_grid_list_item_module_fileTypePill--33914","textCentered":"bp_base_grid_list_item_module_textCentered--33914","innerCentered":"bp_base_grid_list_item_module_innerCentered--33914","gridListV2Small":"bp_base_grid_list_item_module_gridListV2Small--33914","gridV2ClickShield":"bp_base_grid_list_item_module_gridV2ClickShield--33914","staticList":"bp_base_grid_list_item_module_staticList--33914","staticListItem":"bp_base_grid_list_item_module_staticListItem--33914"};
|
|
3
3
|
|
|
4
4
|
export { styles as default };
|
|
@@ -29,6 +29,8 @@ const BaseGridList = /*#__PURE__*/forwardRef(function BaseGridList(props, forwar
|
|
|
29
29
|
className,
|
|
30
30
|
isInteractive = true,
|
|
31
31
|
layoutStyle,
|
|
32
|
+
centerText = false,
|
|
33
|
+
variant = 'large',
|
|
32
34
|
...rest
|
|
33
35
|
} = props;
|
|
34
36
|
const {
|
|
@@ -40,8 +42,10 @@ const BaseGridList = /*#__PURE__*/forwardRef(function BaseGridList(props, forwar
|
|
|
40
42
|
selectionBehavior: rest.selectionBehavior,
|
|
41
43
|
layoutStyle,
|
|
42
44
|
isInteractive,
|
|
45
|
+
centerText,
|
|
46
|
+
variant,
|
|
43
47
|
onAction: handleOnAction
|
|
44
|
-
}), [rest.selectionMode, rest.selectionBehavior, layoutStyle, isInteractive, handleOnAction]);
|
|
48
|
+
}), [rest.selectionMode, rest.selectionBehavior, layoutStyle, isInteractive, centerText, variant, handleOnAction]);
|
|
45
49
|
let layoutStyleClass;
|
|
46
50
|
let layoutFinal;
|
|
47
51
|
switch (layoutStyle) {
|
|
@@ -53,12 +57,18 @@ const BaseGridList = /*#__PURE__*/forwardRef(function BaseGridList(props, forwar
|
|
|
53
57
|
layoutStyleClass = styles.gridList;
|
|
54
58
|
layoutFinal = 'grid';
|
|
55
59
|
break;
|
|
60
|
+
case 'grid-v2':
|
|
61
|
+
layoutStyleClass = styles.gridListV2;
|
|
62
|
+
layoutFinal = 'grid';
|
|
63
|
+
break;
|
|
56
64
|
case 'small-list':
|
|
57
65
|
layoutFinal = 'stack';
|
|
58
66
|
layoutStyleClass = styles.smallList;
|
|
59
67
|
break;
|
|
60
68
|
}
|
|
61
69
|
const GridList$1 = isInteractive ? GridList : StaticGridList;
|
|
70
|
+
const isGridV2 = layoutStyle === 'grid-v2';
|
|
71
|
+
const variantClass = isGridV2 && variant === 'small' ? styles.gridListV2Small : undefined;
|
|
62
72
|
return jsx("div", {
|
|
63
73
|
onKeyDownCapture: stopPropagationForNonSpecialKeys,
|
|
64
74
|
children: jsx(BaseGridListContext.Provider, {
|
|
@@ -66,7 +76,7 @@ const BaseGridList = /*#__PURE__*/forwardRef(function BaseGridList(props, forwar
|
|
|
66
76
|
children: jsx(GridList$1, {
|
|
67
77
|
...rest,
|
|
68
78
|
ref: forwardedRef,
|
|
69
|
-
className: clsx(layoutStyleClass, className),
|
|
79
|
+
className: clsx(layoutStyleClass, variantClass, className),
|
|
70
80
|
"data-modern": enableModernizedComponents ? 'true' : 'false',
|
|
71
81
|
layout: layoutFinal,
|
|
72
82
|
onAction: handleOnAction,
|
|
@@ -33,4 +33,4 @@ export declare const BaseGridList: import("react").ForwardRefExoticComponent<imp
|
|
|
33
33
|
*/
|
|
34
34
|
ActionIconButton: import("react").ForwardRefExoticComponent<(Omit<import("../../primitives/icon-button/types").IconButtonVariantsProps, "ref"> | Omit<import("../../primitives/icon-button/types").IconButtonSmallUtilityVariantProps, "ref">) & import("react").RefAttributes<HTMLButtonElement>>;
|
|
35
35
|
};
|
|
36
|
-
export type { BaseGridListActionIconButtonProps, BaseGridListActionsProps, BaseGridListDescriptionProps, BaseGridListHeaderProps, BaseGridListItemProps, BaseGridListProps, BaseGridListSubtitleProps, BaseGridListThumbnailProps, } from './types';
|
|
36
|
+
export type { BaseGridListActionIconButtonProps, BaseGridListActionsProps, BaseGridListDescriptionProps, BaseGridListHeaderProps, BaseGridListItemProps, BaseGridListProps, BaseGridListSubtitleProps, BaseGridListThumbnailProps, FileCategory, GridV2Variant, } from './types';
|