@box/blueprint-web 18.2.2 → 18.4.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.
Files changed (51) hide show
  1. package/dist/lib-esm/blueprint-configuration-context/consts.d.ts +2 -2
  2. package/dist/lib-esm/blueprint-configuration-context/consts.js +2 -2
  3. package/dist/lib-esm/components.css +566 -330
  4. package/dist/lib-esm/grid-list-item/types.d.ts +1 -1
  5. package/dist/lib-esm/index.css +565 -329
  6. package/dist/lib-esm/large-list-item/types.d.ts +1 -1
  7. package/dist/lib-esm/list-item/main.module.js +1 -1
  8. package/dist/lib-esm/list-item/row.d.ts +5 -0
  9. package/dist/lib-esm/list-item/row.js +3 -1
  10. package/dist/lib-esm/modal/constants.d.ts +1 -0
  11. package/dist/lib-esm/modal/constants.js +3 -1
  12. package/dist/lib-esm/modal/index.d.ts +1 -1
  13. package/dist/lib-esm/modal/modal-header-actions.d.ts +12 -0
  14. package/dist/lib-esm/modal/modal-header-actions.js +57 -0
  15. package/dist/lib-esm/modal/modal-header.d.ts +4 -4
  16. package/dist/lib-esm/modal/modal-header.js +10 -3
  17. package/dist/lib-esm/modal/modal.d.ts +4 -1
  18. package/dist/lib-esm/modal/modal.module.js +1 -1
  19. package/dist/lib-esm/modal/types.d.ts +12 -0
  20. package/dist/lib-esm/primitives/notification/hooks/use-hover-focus-expand.d.ts +17 -0
  21. package/dist/lib-esm/primitives/notification/hooks/use-hover-focus-expand.js +85 -0
  22. package/dist/lib-esm/primitives/notification/hooks/use-notification-exit-animation.d.ts +21 -0
  23. package/dist/lib-esm/primitives/notification/hooks/use-notification-exit-animation.js +141 -0
  24. package/dist/lib-esm/primitives/notification/hooks/use-stack-layer-metrics.d.ts +19 -0
  25. package/dist/lib-esm/primitives/notification/hooks/use-stack-layer-metrics.js +96 -0
  26. package/dist/lib-esm/primitives/notification/hooks/use-staggered-notification-admission.d.ts +10 -0
  27. package/dist/lib-esm/primitives/notification/hooks/use-staggered-notification-admission.js +126 -0
  28. package/dist/lib-esm/primitives/notification/load-animated-notification-viewport.d.ts +11 -0
  29. package/dist/lib-esm/primitives/notification/load-animated-notification-viewport.js +24 -0
  30. package/dist/lib-esm/primitives/notification/notification-provider.d.ts +8 -0
  31. package/dist/lib-esm/primitives/notification/notification-provider.js +29 -3
  32. package/dist/lib-esm/primitives/notification/notification-stack-utils.d.ts +21 -0
  33. package/dist/lib-esm/primitives/notification/notification-stack-utils.js +38 -0
  34. package/dist/lib-esm/primitives/notification/notification-stack.module.js +4 -0
  35. package/dist/lib-esm/primitives/notification/notification.module.js +1 -1
  36. package/dist/lib-esm/primitives/notification/notification.viewport-animated.d.ts +7 -0
  37. package/dist/lib-esm/primitives/notification/notification.viewport-animated.js +147 -0
  38. package/dist/lib-esm/primitives/notification/notification.viewport.d.ts +5 -0
  39. package/dist/lib-esm/primitives/notification/notification.viewport.js +51 -1
  40. package/dist/lib-esm/primitives/notification/private-notification-element-animated.d.ts +32 -0
  41. package/dist/lib-esm/primitives/notification/private-notification-element-animated.js +198 -0
  42. package/dist/lib-esm/primitives/notification/private-notification-element.d.ts +3 -0
  43. package/dist/lib-esm/primitives/notification/private-notification-element.js +3 -0
  44. package/dist/lib-esm/small-list-item/types.d.ts +1 -1
  45. package/dist/lib-esm/types/selection-visibility.d.ts +4 -0
  46. package/dist/lib-esm/util-components/base-grid-list-item/base-grid-list-item-actions.js +4 -2
  47. package/dist/lib-esm/util-components/base-grid-list-item/base-grid-list-item.js +3 -0
  48. package/dist/lib-esm/util-components/base-grid-list-item/base-grid-list-item.module.js +1 -1
  49. package/dist/lib-esm/util-components/base-grid-list-item/base-grid-list.js +3 -1
  50. package/dist/lib-esm/util-components/base-grid-list-item/types.d.ts +14 -0
  51. package/package.json +3 -3
@@ -0,0 +1,198 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { XMark } from '@box/blueprint-web-assets/icons/Medium';
3
+ import { bpDurationLong } from '@box/blueprint-web-assets/tokens/tokens';
4
+ import * as Toast from '@radix-ui/react-toast';
5
+ import clsx from 'clsx';
6
+ import { useMemo, useCallback, useRef, useEffect, useState } from 'react';
7
+ import { composeEventHandlers } from '../../utils/composeEventHandlers.js';
8
+ import { IconButton } from '../icon-button/icon-button.js';
9
+ import { useNotificationExitAnimation, handleNotificationExitTransitionEnd } from './hooks/use-notification-exit-animation.js';
10
+ import { isOpenNotification } from './notification-stack-utils.js';
11
+ import stackStyles from './notification-stack.module.js';
12
+ import styles from './notification.module.js';
13
+ import { getIcon } from './private-notification-element.js';
14
+ import { truncateNotificationCopy } from './truncate-notification-copy.js';
15
+
16
+ /**
17
+ * Stacked-deck toast. Loaded only from the animated viewport chunk so the flat
18
+ * Notification path stays off the first-paint graph.
19
+ */
20
+ function AnimatedPrivateNotificationElement(props) {
21
+ const {
22
+ variant,
23
+ styledText,
24
+ sensitivity,
25
+ open,
26
+ onClose,
27
+ closeButtonAriaLabel,
28
+ typeIconAriaLabel,
29
+ children,
30
+ isAnimationEnabled = false,
31
+ isEntering = false,
32
+ depth = 0,
33
+ expandOffset = 0,
34
+ isBeyondVisibleDepth = false,
35
+ layerRef,
36
+ stackId,
37
+ onExitStart,
38
+ onEscapeKeyDown,
39
+ onTransitionEnd,
40
+ style,
41
+ ...rest
42
+ } = props;
43
+ const iconComponent = useMemo(() => getIcon(typeIconAriaLabel, variant), [typeIconAriaLabel, variant]);
44
+ // Radix's own viewport-wide pause-on-hover/focus (`Toast.Provider`'s `toast.viewportPause`/
45
+ // `viewportResume` events) already covers pausing auto-dismiss while the user is interacting
46
+ // with the stack — no bespoke pause context is ported from EndUserApp here.
47
+ const setOpen = useCallback(nextOpen => {
48
+ const resolved = typeof nextOpen === 'function' ? nextOpen(open) : nextOpen;
49
+ if (!resolved) {
50
+ onClose?.();
51
+ }
52
+ }, [onClose, open]);
53
+ // Snapshot layout before the viewport pops this layer out of flow (it re-renders with offset 0).
54
+ const liveLayoutRef = useRef({
55
+ depth,
56
+ expandOffset
57
+ });
58
+ const frozenLayoutRef = useRef({
59
+ depth,
60
+ expandOffset
61
+ });
62
+ liveLayoutRef.current = {
63
+ depth,
64
+ expandOffset
65
+ };
66
+ const notifyExitStart = useCallback(() => {
67
+ frozenLayoutRef.current = liveLayoutRef.current;
68
+ if (stackId) {
69
+ onExitStart?.(stackId);
70
+ }
71
+ }, [onExitStart, stackId]);
72
+ const {
73
+ radixOpen,
74
+ isExiting,
75
+ hasExitStyles,
76
+ completeExit,
77
+ handleOpenChange
78
+ } = useNotificationExitAnimation({
79
+ open: open ?? true,
80
+ setOpen,
81
+ isAnimationEnabled,
82
+ onExitStart: notifyExitStart
83
+ });
84
+ // Esc fires Radix's own onEscapeKeyDown before handleClose runs, so this reliably
85
+ // captures intent even though Esc and the close button both end up at the same
86
+ // onOpenChange(false) call. Reset once the exit styles clear so the next dismissal
87
+ // (of a different kind) isn't misattributed. Composes with the caller-provided
88
+ // onEscapeKeyDown (pulled out of `rest` so it isn't clobbered by this one) — it runs
89
+ // first and can call preventDefault() to suppress both Radix's close and this attribution.
90
+ const exitReasonRef = useRef(null);
91
+ const handleEscapeKeyDown = useCallback(event => {
92
+ onEscapeKeyDown?.(event);
93
+ if (!event.defaultPrevented) {
94
+ exitReasonRef.current = 'escape';
95
+ }
96
+ }, [onEscapeKeyDown]);
97
+ useEffect(() => {
98
+ if (!hasExitStyles) {
99
+ exitReasonRef.current = null;
100
+ }
101
+ }, [hasExitStyles]);
102
+ const layoutDepth = isExiting ? frozenLayoutRef.current.depth : depth;
103
+ const layoutExpandOffset = isExiting ? frozenLayoutRef.current.expandOffset : expandOffset;
104
+ // `data-entering` is the "from" state; one frame later it flips off so CSS can transition in.
105
+ // `isEnterTransitioning` stays true through --bp-duration-long so the destination uses that duration.
106
+ const [hasEntered, setHasEntered] = useState(!isEntering);
107
+ const [isEnterTransitioning, setIsEnterTransitioning] = useState(isEntering);
108
+ useEffect(() => {
109
+ // If this toast stops being the entering one before the rAF, settle immediately
110
+ // so it isn't stranded in the off-screen "from" state.
111
+ if (!isEntering) {
112
+ setHasEntered(true);
113
+ return undefined;
114
+ }
115
+ const frame = requestAnimationFrame(() => setHasEntered(true));
116
+ return () => cancelAnimationFrame(frame);
117
+ }, [isEntering]);
118
+ useEffect(() => {
119
+ if (!isEnterTransitioning || !hasEntered) {
120
+ return undefined;
121
+ }
122
+ const timeout = window.setTimeout(() => setIsEnterTransitioning(false), Number.parseFloat(bpDurationLong));
123
+ return () => window.clearTimeout(timeout);
124
+ }, [hasEntered, isEnterTransitioning]);
125
+ // Exit completion must not be blockable by a consumer `preventDefault()`.
126
+ const handleTransitionEnd = useMemo(() => composeEventHandlers(onTransitionEnd, event => handleNotificationExitTransitionEnd(event, isExiting, completeExit), {
127
+ checkForDefaultPrevented: false
128
+ }), [completeExit, isExiting, onTransitionEnd]);
129
+ const layerStyle = isAnimationEnabled ? {
130
+ '--notification-stack-depth': layoutDepth,
131
+ '--notification-stack-expand-offset': `${layoutExpandOffset}px`
132
+ } : undefined;
133
+ return jsx(Toast.Root, {
134
+ ...rest,
135
+ ref: layerRef,
136
+ className: clsx(styles.root, styles[variant], {
137
+ [stackStyles.stackLayer]: isAnimationEnabled
138
+ }),
139
+ "data-beyond-visible-depth": isAnimationEnabled && isOpenNotification({
140
+ open
141
+ }) && isBeyondVisibleDepth ? 'true' : undefined,
142
+ "data-bp-animated": isAnimationEnabled ? 'true' : 'false',
143
+ "data-front": isAnimationEnabled && isOpenNotification({
144
+ open
145
+ }) && layoutDepth === 0 ? 'true' : undefined,
146
+ "data-bp-exiting": hasExitStyles ? 'true' : undefined,
147
+ "data-bp-exit-reason": hasExitStyles ? exitReasonRef.current ?? undefined : undefined,
148
+ "data-enter-transition": isAnimationEnabled && isEnterTransitioning ? 'true' : undefined,
149
+ "data-entering": isAnimationEnabled && !hasEntered ? 'true' : undefined,
150
+ onEscapeKeyDown: handleEscapeKeyDown,
151
+ onTransitionEnd: handleTransitionEnd,
152
+ onOpenChange: handleOpenChange,
153
+ open: radixOpen,
154
+ style: {
155
+ ...style,
156
+ ...layerStyle
157
+ },
158
+ // Override Toast.Root's tabIndex={0} so a pointer hit cannot leave focus on the
159
+ // <li> and permanently pause TTL. Close / Action stay tabbable.
160
+ tabIndex: -1,
161
+ type: sensitivity,
162
+ children: jsxs("div", {
163
+ className: styles.container,
164
+ children: [jsx("div", {
165
+ className: styles.typeIconContainer,
166
+ children: iconComponent
167
+ }), jsxs("div", {
168
+ className: clsx(styles.messageRow, {
169
+ [styles.withButtons]: children
170
+ }),
171
+ children: [jsx("div", {
172
+ className: styles.text,
173
+ children: jsx(Toast.Description, {
174
+ children: truncateNotificationCopy(styledText)
175
+ })
176
+ }), jsx("div", {
177
+ className: styles.contentButtonSection,
178
+ children: jsx("div", {
179
+ className: styles.contentButtons,
180
+ children: children
181
+ })
182
+ })]
183
+ }), jsx("div", {
184
+ className: styles.closeButtonSection,
185
+ children: jsx(Toast.Close, {
186
+ asChild: true,
187
+ children: jsx(IconButton, {
188
+ "aria-label": closeButtonAriaLabel,
189
+ className: styles.closeButton,
190
+ icon: XMark
191
+ })
192
+ })
193
+ })]
194
+ })
195
+ });
196
+ }
197
+
198
+ export { AnimatedPrivateNotificationElement };
@@ -36,5 +36,8 @@ export declare const getIcon: (iconLabel: string, variant: PrivateNotificationEl
36
36
  * * [Radix-UI link](https://www.radix-ui.com/docs/primitives/components/toast)
37
37
  *
38
38
  * **IMPORTANT**: Must be placed inside a single <b><NotificationProvider></b> singleton component provided by the app
39
+ *
40
+ * The stacked-deck motion variant lives in `private-notification-element-animated.tsx`
41
+ * and is loaded only after first paint when Notification animation is on.
39
42
  */
40
43
  export declare function PrivateNotificationElement(props: PrivateNotificationElementProps): import("react/jsx-runtime").JSX.Element;
@@ -44,6 +44,9 @@ const getIcon = (iconLabel, variant) => {
44
44
  * * [Radix-UI link](https://www.radix-ui.com/docs/primitives/components/toast)
45
45
  *
46
46
  * **IMPORTANT**: Must be placed inside a single <b><NotificationProvider></b> singleton component provided by the app
47
+ *
48
+ * The stacked-deck motion variant lives in `private-notification-element-animated.tsx`
49
+ * and is loaded only after first paint when Notification animation is on.
47
50
  */
48
51
  function PrivateNotificationElement(props) {
49
52
  const {
@@ -4,5 +4,5 @@ export type SmallListActionsProps = BaseGridListActionsProps;
4
4
  export type SmallListHeaderProps = BaseGridListHeaderProps;
5
5
  export type SmallListThumbnailProps = BaseGridListThumbnailProps;
6
6
  export type SmallListSubtitleProps = BaseGridListSubtitleProps;
7
- export type SmallListProps = Omit<BaseGridListProps, 'layoutStyle'>;
7
+ export type SmallListProps = Omit<BaseGridListProps, 'layoutStyle' | 'selectionVisibility'>;
8
8
  export type SmallListItemProps = BaseGridListItemProps;
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Whether a multi-select checkbox stays visible, or shows with the action buttons on hover.
3
+ */
4
+ export type SelectionVisibility = 'hover' | 'always';
@@ -105,7 +105,8 @@ const BaseGridListActions = /*#__PURE__*/forwardRef(function BaseGridListActions
105
105
  const {
106
106
  layoutStyle,
107
107
  selectionMode,
108
- centerText
108
+ centerText,
109
+ selectionVisibility
109
110
  } = useBaseGridListContext();
110
111
  const {
111
112
  children,
@@ -129,11 +130,12 @@ const BaseGridListActions = /*#__PURE__*/forwardRef(function BaseGridListActions
129
130
  const isGridV2 = layoutStyle === 'grid-v2';
130
131
  const isSelectionEnabled = selectionMode === 'multiple';
131
132
  const isRenderPropUsed = typeof children === 'function';
133
+ const alwaysShowSelection = selectionVisibility === 'always' && isSelectionEnabled;
132
134
  return jsxs(Fragment, {
133
135
  children: [jsx("div", {
134
136
  ...rest,
135
137
  ref: forkRef,
136
- className: clsx(styles.actions, className),
138
+ className: clsx(styles.actions, alwaysShowSelection && styles.alwaysShowSelection, className),
137
139
  children: isList ? jsx(BaseListActions, {
138
140
  isSelectionCheckboxDisabled: isSelectionCheckboxDisabled,
139
141
  selectionEnabled: isSelectionEnabled,
@@ -26,6 +26,7 @@ const BaseGridListItem = /*#__PURE__*/forwardRef(function BaseGridListItem(props
26
26
  children,
27
27
  className,
28
28
  isDroppableTarget = true,
29
+ isHighlighted = false,
29
30
  loading = false,
30
31
  pinned = false,
31
32
  pinAriaLabel,
@@ -134,6 +135,8 @@ const BaseGridListItem = /*#__PURE__*/forwardRef(function BaseGridListItem(props
134
135
  [styles.noActions]: isV2Layout && !hasActions
135
136
  }, {
136
137
  [styles.droppableTarget]: isDroppableTarget
138
+ }, {
139
+ [styles.highlighted]: isHighlighted
137
140
  }, className),
138
141
  textValue: textValue,
139
142
  children: jsxs(BaseGridListItemContext.Provider, {
@@ -1,4 +1,4 @@
1
1
  import '../../index.css';
2
- var styles = {"smallList":"bp_base_grid_list_item_module_smallList--1ce37","smallListItem":"bp_base_grid_list_item_module_smallListItem--1ce37","loading":"bp_base_grid_list_item_module_loading--1ce37","thumbnail":"bp_base_grid_list_item_module_thumbnail--1ce37","thumbnailContent":"bp_base_grid_list_item_module_thumbnailContent--1ce37","header":"bp_base_grid_list_item_module_header--1ce37","subtitle":"bp_base_grid_list_item_module_subtitle--1ce37","actions":"bp_base_grid_list_item_module_actions--1ce37","selection":"bp_base_grid_list_item_module_selection--1ce37","inner":"bp_base_grid_list_item_module_inner--1ce37","actionsCheckboxWrapper":"bp_base_grid_list_item_module_actionsCheckboxWrapper--1ce37","largeList":"bp_base_grid_list_item_module_largeList--1ce37","largeListItem":"bp_base_grid_list_item_module_largeListItem--1ce37","fade":"bp_base_grid_list_item_module_fade--1ce37","description":"bp_base_grid_list_item_module_description--1ce37","snippet":"bp_base_grid_list_item_module_snippet--1ce37","snippetContent":"bp_base_grid_list_item_module_snippetContent--1ce37","gridList":"bp_base_grid_list_item_module_gridList--1ce37","gridListItem":"bp_base_grid_list_item_module_gridListItem--1ce37","statusPin":"bp_base_grid_list_item_module_statusPin--1ce37","isItemInteracted":"bp_base_grid_list_item_module_isItemInteracted--1ce37","tooltipContent":"bp_base_grid_list_item_module_tooltipContent--1ce37","tooltipArrow":"bp_base_grid_list_item_module_tooltipArrow--1ce37","gridListV2":"bp_base_grid_list_item_module_gridListV2--1ce37","gridListV2Item":"bp_base_grid_list_item_module_gridListV2Item--1ce37","droppableTarget":"bp_base_grid_list_item_module_droppableTarget--1ce37","noActions":"bp_base_grid_list_item_module_noActions--1ce37","thumbnailBadges":"bp_base_grid_list_item_module_thumbnailBadges--1ce37","statusBadge":"bp_base_grid_list_item_module_statusBadge--1ce37","fileTypePill":"bp_base_grid_list_item_module_fileTypePill--1ce37","textCentered":"bp_base_grid_list_item_module_textCentered--1ce37","innerCentered":"bp_base_grid_list_item_module_innerCentered--1ce37","gridListV2Small":"bp_base_grid_list_item_module_gridListV2Small--1ce37","gridListV2XSmall":"bp_base_grid_list_item_module_gridListV2XSmall--1ce37","gridListV2XSmallBordered":"bp_base_grid_list_item_module_gridListV2XSmallBordered--1ce37","gridV2ClickShield":"bp_base_grid_list_item_module_gridV2ClickShield--1ce37","listV2ClickShield":"bp_base_grid_list_item_module_listV2ClickShield--1ce37","listV2":"bp_base_grid_list_item_module_listV2--1ce37","listV2Item":"bp_base_grid_list_item_module_listV2Item--1ce37","listV2Divider":"bp_base_grid_list_item_module_listV2Divider--1ce37","content":"bp_base_grid_list_item_module_content--1ce37","staticList":"bp_base_grid_list_item_module_staticList--1ce37","staticListItem":"bp_base_grid_list_item_module_staticListItem--1ce37"};
2
+ var styles = {"smallList":"bp_base_grid_list_item_module_smallList--c86e5","smallListItem":"bp_base_grid_list_item_module_smallListItem--c86e5","loading":"bp_base_grid_list_item_module_loading--c86e5","thumbnail":"bp_base_grid_list_item_module_thumbnail--c86e5","thumbnailContent":"bp_base_grid_list_item_module_thumbnailContent--c86e5","header":"bp_base_grid_list_item_module_header--c86e5","subtitle":"bp_base_grid_list_item_module_subtitle--c86e5","actions":"bp_base_grid_list_item_module_actions--c86e5","selection":"bp_base_grid_list_item_module_selection--c86e5","inner":"bp_base_grid_list_item_module_inner--c86e5","actionsCheckboxWrapper":"bp_base_grid_list_item_module_actionsCheckboxWrapper--c86e5","largeList":"bp_base_grid_list_item_module_largeList--c86e5","largeListItem":"bp_base_grid_list_item_module_largeListItem--c86e5","fade":"bp_base_grid_list_item_module_fade--c86e5","description":"bp_base_grid_list_item_module_description--c86e5","snippet":"bp_base_grid_list_item_module_snippet--c86e5","snippetContent":"bp_base_grid_list_item_module_snippetContent--c86e5","gridList":"bp_base_grid_list_item_module_gridList--c86e5","gridListItem":"bp_base_grid_list_item_module_gridListItem--c86e5","statusPin":"bp_base_grid_list_item_module_statusPin--c86e5","isItemInteracted":"bp_base_grid_list_item_module_isItemInteracted--c86e5","tooltipContent":"bp_base_grid_list_item_module_tooltipContent--c86e5","tooltipArrow":"bp_base_grid_list_item_module_tooltipArrow--c86e5","gridListV2":"bp_base_grid_list_item_module_gridListV2--c86e5","gridListV2Item":"bp_base_grid_list_item_module_gridListV2Item--c86e5","droppableTarget":"bp_base_grid_list_item_module_droppableTarget--c86e5","noActions":"bp_base_grid_list_item_module_noActions--c86e5","thumbnailBadges":"bp_base_grid_list_item_module_thumbnailBadges--c86e5","statusBadge":"bp_base_grid_list_item_module_statusBadge--c86e5","fileTypePill":"bp_base_grid_list_item_module_fileTypePill--c86e5","alwaysShowSelection":"bp_base_grid_list_item_module_alwaysShowSelection--c86e5","textCentered":"bp_base_grid_list_item_module_textCentered--c86e5","innerCentered":"bp_base_grid_list_item_module_innerCentered--c86e5","highlighted":"bp_base_grid_list_item_module_highlighted--c86e5","gridListV2Small":"bp_base_grid_list_item_module_gridListV2Small--c86e5","gridListV2XSmall":"bp_base_grid_list_item_module_gridListV2XSmall--c86e5","gridListV2XSmallBordered":"bp_base_grid_list_item_module_gridListV2XSmallBordered--c86e5","gridV2ClickShield":"bp_base_grid_list_item_module_gridV2ClickShield--c86e5","listV2ClickShield":"bp_base_grid_list_item_module_listV2ClickShield--c86e5","listV2":"bp_base_grid_list_item_module_listV2--c86e5","listV2Item":"bp_base_grid_list_item_module_listV2Item--c86e5","listV2Divider":"bp_base_grid_list_item_module_listV2Divider--c86e5","content":"bp_base_grid_list_item_module_content--c86e5","staticList":"bp_base_grid_list_item_module_staticList--c86e5","staticListItem":"bp_base_grid_list_item_module_staticListItem--c86e5"};
3
3
 
4
4
  export { styles as default };
@@ -31,6 +31,7 @@ const BaseGridList = /*#__PURE__*/forwardRef(function BaseGridList(props, forwar
31
31
  layoutStyle,
32
32
  centerText = false,
33
33
  variant = 'large',
34
+ selectionVisibility = 'hover',
34
35
  ...rest
35
36
  } = props;
36
37
  const handleOnAction = onAction || noop;
@@ -45,8 +46,9 @@ const BaseGridList = /*#__PURE__*/forwardRef(function BaseGridList(props, forwar
45
46
  isInteractive,
46
47
  centerText,
47
48
  variant,
49
+ selectionVisibility,
48
50
  onAction: handleOnAction
49
- }), [rest.selectionMode, rest.selectionBehavior, layoutStyle, isInteractive, centerText, variant, handleOnAction]);
51
+ }), [rest.selectionMode, rest.selectionBehavior, layoutStyle, isInteractive, centerText, variant, selectionVisibility, handleOnAction]);
50
52
  let layoutStyleClass;
51
53
  let layoutFinal;
52
54
  switch (layoutStyle) {
@@ -2,6 +2,7 @@ import { type ComponentPropsWithRef, type ReactNode } from 'react';
2
2
  import { type GridListItemProps, type GridListProps as RAGridListProps } from 'react-aria-components';
3
3
  import { type IconButtonProps } from '../../primitives/icon-button';
4
4
  import { type Modify } from '../../types/modify';
5
+ import { type SelectionVisibility } from '../../types/selection-visibility';
5
6
  export interface BaseGridListLayoutProp {
6
7
  layoutStyle: 'grid' | 'grid-v2' | 'list' | 'list-v2' | 'small-list';
7
8
  }
@@ -44,6 +45,14 @@ interface CustomGridListProps extends BaseGridListLayoutProp {
44
45
  * @default 'large'
45
46
  */
46
47
  variant?: GridV2Variant;
48
+ /**
49
+ * Whether the multi-select checkbox stays visible, or shows with the action buttons.
50
+ * `always` keeps the checkbox visible. Action buttons still wait for hover, focus, selection, or an open menu.
51
+ * `hover` shows the checkbox and action buttons together on hover, focus, and selection.
52
+ * `always` is not supported with `selectionMode` `single`.
53
+ * @default 'hover'
54
+ */
55
+ selectionVisibility?: SelectionVisibility;
47
56
  }
48
57
  export declare enum ListLayout {
49
58
  GRID = "Grid List",
@@ -143,5 +152,10 @@ export interface BaseGridListItemProps extends GridListItemProps, Omit<BaseGridL
143
152
  * Set to `false` to style this item as an invalid drop target.
144
153
  */
145
154
  isDroppableTarget?: boolean;
155
+ /**
156
+ * Flashes a green tint that fades to the item's normal background, e.g. for a newly added item.
157
+ * The fade runs once each time this becomes `true`. Supported in `grid-v2` and `list-v2` layouts.
158
+ */
159
+ isHighlighted?: boolean;
146
160
  }
147
161
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@box/blueprint-web",
3
- "version": "18.2.2",
3
+ "version": "18.4.0",
4
4
  "type": "module",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "publishConfig": {
@@ -55,7 +55,7 @@
55
55
  "dependencies": {
56
56
  "@ariakit/react": "0.4.21",
57
57
  "@ariakit/react-core": "0.4.21",
58
- "@box/blueprint-web-assets": "^5.12.1",
58
+ "@box/blueprint-web-assets": "^5.12.3",
59
59
  "@internationalized/date": "^3.12.0",
60
60
  "@radix-ui/react-accordion": "1.1.2",
61
61
  "@radix-ui/react-checkbox": "1.0.4",
@@ -86,7 +86,7 @@
86
86
  "devDependencies": {
87
87
  "@box/box-test-client": "^3.2.7",
88
88
  "@box/playwright-utils": "^2.8.5",
89
- "@box/storybook-utils": "^1.4.13",
89
+ "@box/storybook-utils": "^1.4.15",
90
90
  "@figma/code-connect": "1.4.4",
91
91
  "@playwright/test": "1.46.1",
92
92
  "@types/js-yaml": "^4.0.9",