@box/blueprint-web 7.8.0 → 7.10.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.
@@ -0,0 +1,9 @@
1
+ /// <reference types="react" />
2
+ import { type BadgeProps } from './types';
3
+ export type BaseBadgeProps = BadgeProps & {
4
+ /** The color of the badge background */
5
+ backgroundColor: string;
6
+ className?: string;
7
+ };
8
+ export declare const BadgeSizes: readonly ["small", "medium", "large", "xlarge"];
9
+ export declare const BaseBadge: ({ backgroundColor, className, children, size, offset }: BaseBadgeProps) => JSX.Element;
@@ -0,0 +1,24 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import clsx from 'clsx';
3
+ import mapValues from 'lodash/mapValues';
4
+ import styles from './base-badge.module.js';
5
+
6
+ const BaseBadge = ({
7
+ backgroundColor,
8
+ className,
9
+ children,
10
+ size,
11
+ offset
12
+ }) => {
13
+ const offsetStyle = mapValues(offset, value => Number.isInteger(value) ? `${value}px` : `0`);
14
+ return jsx("div", {
15
+ className: clsx(className, styles.badge, styles[`${size}SizeBadge`]),
16
+ style: {
17
+ backgroundColor,
18
+ ...offsetStyle
19
+ },
20
+ children: children
21
+ });
22
+ };
23
+
24
+ export { BaseBadge };
@@ -0,0 +1,4 @@
1
+ import '../index.css';
2
+ var styles = {"badgeContainer":"bp_base_badge_module_badgeContainer--251c2","badge":"bp_base_badge_module_badge--251c2","smallSizeBadge":"bp_base_badge_module_smallSizeBadge--251c2","mediumSizeBadge":"bp_base_badge_module_mediumSizeBadge--251c2","largeSizeBadge":"bp_base_badge_module_largeSizeBadge--251c2","xlargeSizeBadge":"bp_base_badge_module_xlargeSizeBadge--251c2","iconBadge":"bp_base_badge_module_iconBadge--251c2","statusBadge":"bp_base_badge_module_statusBadge--251c2","numericBadge":"bp_base_badge_module_numericBadge--251c2","numericBadgeSingleDigit":"bp_base_badge_module_numericBadgeSingleDigit--251c2","numericBadgeMoreDigits":"bp_base_badge_module_numericBadgeMoreDigits--251c2"};
3
+
4
+ export { styles as default };
@@ -0,0 +1,8 @@
1
+ /// <reference types="react" />
2
+ import { type BadgeProps } from './types';
3
+ export interface IconBadgeProps extends BadgeProps {
4
+ /** The variant of the icon badge */
5
+ variant: 'file-pdf' | 'file-docs' | 'file-sheets' | 'file-image' | 'file-canvas' | 'file-pages' | 'file-keynote' | 'file-boxnote' | 'file-video' | 'folder-external' | 'folder-shared' | 'action-relay' | 'action-mention' | 'action-task' | 'action-taskapproval' | 'action-annotation' | 'action-performed-completed' | 'action-performed-rejected' | 'collaborator-external' | 'collaborator-admin' | 'collaborator-coadmin' | 'content-pin' | 'content-collection' | 'content-offline' | 'content-progress';
6
+ }
7
+ export declare const IconBadgeVariants: ("file-pdf" | "file-docs" | "file-sheets" | "file-image" | "file-canvas" | "file-pages" | "file-keynote" | "file-boxnote" | "file-video" | "folder-external" | "folder-shared" | "action-relay" | "action-mention" | "action-task" | "action-taskapproval" | "action-annotation" | "action-performed-completed" | "action-performed-rejected" | "collaborator-external" | "collaborator-admin" | "collaborator-coadmin" | "content-pin" | "content-collection" | "content-offline" | "content-progress")[];
8
+ export declare const IconBadge: (props: IconBadgeProps) => JSX.Element;
@@ -0,0 +1,182 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { FilePdf, FileDocs, FileSheets, FileImage, FileCanvas, FilePages, FileKeynote, FileBoxNote, FileVideo, FolderExternal, FolderShared, Relay, EllipsisBubble, Task, ApprovalTask, Annotation, Checkmark, XMark, GlobeBadge, Star, Pin, Arrow, CheckmarkUnderline, Loader } from '@box/blueprint-web-assets/icons/Fill';
3
+ import { GrayWhite, GreenLight100, Orange100, Gray10, Gray100, Gray65, LightBlue100, LightBlue120, Yellorange100, WatermelonRed110, Gray50, DarkBlue100, PurpleRain100, Gray80 } from '@box/blueprint-web-assets/tokens/tokens';
4
+ import { Children, createElement } from 'react';
5
+ import { BaseBadge } from './base-badge.js';
6
+ import styles from './base-badge.module.js';
7
+
8
+ const badgeVariantToIconProps = {
9
+ 'file-pdf': {
10
+ backgroundColor: '#D0021B',
11
+ icon: FilePdf,
12
+ iconColor: GrayWhite
13
+ },
14
+ 'file-docs': {
15
+ backgroundColor: '#4083F7',
16
+ icon: FileDocs,
17
+ iconColor: GrayWhite
18
+ },
19
+ 'file-sheets': {
20
+ backgroundColor: '#21A464',
21
+ icon: FileSheets,
22
+ iconColor: GrayWhite
23
+ },
24
+ 'file-image': {
25
+ backgroundColor: GreenLight100,
26
+ icon: FileImage,
27
+ iconColor: GrayWhite
28
+ },
29
+ 'file-canvas': {
30
+ backgroundColor: Orange100,
31
+ icon: FileCanvas,
32
+ iconColor: GrayWhite
33
+ },
34
+ 'file-pages': {
35
+ backgroundColor: '#FF9500',
36
+ icon: FilePages,
37
+ iconColor: GrayWhite
38
+ },
39
+ 'file-keynote': {
40
+ backgroundColor: '#0A84FF',
41
+ icon: FileKeynote,
42
+ iconColor: GrayWhite
43
+ },
44
+ 'file-boxnote': {
45
+ backgroundColor: Gray10,
46
+ icon: FileBoxNote,
47
+ iconColor: Gray100
48
+ },
49
+ 'file-video': {
50
+ backgroundColor: '#009AED',
51
+ icon: FileVideo,
52
+ iconColor: GrayWhite
53
+ },
54
+ 'folder-external': {
55
+ backgroundColor: Gray65,
56
+ icon: FolderExternal,
57
+ iconColor: GrayWhite
58
+ },
59
+ 'folder-shared': {
60
+ backgroundColor: LightBlue100,
61
+ icon: FolderShared,
62
+ iconColor: GrayWhite
63
+ },
64
+ 'action-relay': {
65
+ backgroundColor: LightBlue120,
66
+ icon: Relay,
67
+ iconColor: GrayWhite
68
+ },
69
+ 'action-mention': {
70
+ backgroundColor: LightBlue120,
71
+ icon: EllipsisBubble,
72
+ iconColor: GrayWhite
73
+ },
74
+ 'action-task': {
75
+ backgroundColor: LightBlue100,
76
+ icon: Task,
77
+ iconColor: GrayWhite
78
+ },
79
+ 'action-taskapproval': {
80
+ backgroundColor: LightBlue120,
81
+ icon: ApprovalTask,
82
+ iconColor: GrayWhite
83
+ },
84
+ 'action-annotation': {
85
+ backgroundColor: Yellorange100,
86
+ icon: Annotation,
87
+ iconColor: GrayWhite
88
+ },
89
+ 'action-performed-completed': {
90
+ backgroundColor: GreenLight100,
91
+ icon: Checkmark,
92
+ iconColor: GrayWhite
93
+ },
94
+ 'action-performed-rejected': {
95
+ backgroundColor: WatermelonRed110,
96
+ icon: XMark,
97
+ iconColor: GrayWhite
98
+ },
99
+ 'collaborator-external': {
100
+ backgroundColor: Gray50,
101
+ icon: GlobeBadge,
102
+ iconColor: GrayWhite
103
+ },
104
+ 'collaborator-admin': {
105
+ backgroundColor: DarkBlue100,
106
+ icon: Star,
107
+ iconColor: GrayWhite
108
+ },
109
+ 'collaborator-coadmin': {
110
+ backgroundColor: PurpleRain100,
111
+ icon: Star,
112
+ iconColor: GrayWhite
113
+ },
114
+ 'content-pin': {
115
+ backgroundColor: Gray10,
116
+ icon: Pin,
117
+ iconColor: Gray80
118
+ },
119
+ 'content-collection': {
120
+ backgroundColor: Gray10,
121
+ icon: Arrow,
122
+ iconColor: Gray80,
123
+ iconStyle: {
124
+ transform: 'rotate(135deg)'
125
+ }
126
+ },
127
+ 'content-offline': {
128
+ backgroundColor: GreenLight100,
129
+ icon: CheckmarkUnderline,
130
+ iconColor: GrayWhite
131
+ },
132
+ 'content-progress': {
133
+ backgroundColor: Yellorange100,
134
+ icon: Loader,
135
+ iconColor: GrayWhite
136
+ }
137
+ };
138
+ const badgeSizeToIconSize = {
139
+ small: '6px',
140
+ medium: '9px',
141
+ large: '10px',
142
+ xlarge: '14px'
143
+ };
144
+ const IconBadge = props => {
145
+ const {
146
+ size,
147
+ variant,
148
+ children,
149
+ offset
150
+ } = props;
151
+ const {
152
+ backgroundColor,
153
+ icon,
154
+ iconColor,
155
+ iconStyle
156
+ } = badgeVariantToIconProps[variant];
157
+ const iconSize = badgeSizeToIconSize[size];
158
+ if (Children.count(children) !== 1) {
159
+ if (process.env.NODE_ENV !== 'production') {
160
+ // eslint-disable-next-line no-console
161
+ console.error('IconBadge component requires exactly one child');
162
+ }
163
+ }
164
+ return jsxs("div", {
165
+ className: styles.badgeContainer,
166
+ children: [children, jsx(BaseBadge, {
167
+ backgroundColor: backgroundColor,
168
+ className: styles.iconBadge,
169
+ offset: offset,
170
+ size: size,
171
+ children: /*#__PURE__*/createElement(icon, {
172
+ color: iconColor,
173
+ height: iconSize,
174
+ width: iconSize,
175
+ role: 'presentation',
176
+ style: iconStyle || {}
177
+ })
178
+ })]
179
+ });
180
+ };
181
+
182
+ export { IconBadge };
@@ -0,0 +1,3 @@
1
+ export { IconBadge, type IconBadgeProps } from './icon-badge';
2
+ export { NumericBadge, type NumericBadgeProps } from './numeric-badge';
3
+ export { StatusBadge, type StatusBadgeProps } from './status-badge';
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import { type BadgeProps } from './types';
3
+ export interface NumericBadgeProps extends Omit<BadgeProps, 'size'> {
4
+ /** The numeric value to inform users of the total count */
5
+ value: string;
6
+ }
7
+ export declare const NumericBadge: React.ForwardRefExoticComponent<NumericBadgeProps & React.RefAttributes<React.ReactNode>>;
@@ -0,0 +1,49 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { WatermelonRed110 } from '@box/blueprint-web-assets/tokens/tokens';
3
+ import clsx from 'clsx';
4
+ import React__default, { forwardRef, Children } from 'react';
5
+ import { Text } from '../text/text.js';
6
+ import { useUniqueId } from '../utils/useUniqueId.js';
7
+ import { BaseBadge } from './base-badge.js';
8
+ import styles from './base-badge.module.js';
9
+
10
+ const NumericBadge = /*#__PURE__*/forwardRef((props, forwardedRef) => {
11
+ const {
12
+ value,
13
+ children,
14
+ offset
15
+ } = props;
16
+ const valueId = useUniqueId('numeric-badge-value');
17
+ if (Children.count(children) !== 1) {
18
+ if (process.env.NODE_ENV !== 'production') {
19
+ // eslint-disable-next-line no-console
20
+ console.error('NumericBadge component requires exactly one child');
21
+ }
22
+ }
23
+ const child = Children.only(children);
24
+ return jsxs("div", {
25
+ className: styles.badgeContainer,
26
+ children: [/*#__PURE__*/React__default.cloneElement(child, {
27
+ ref: forwardedRef,
28
+ 'aria-describedby': valueId
29
+ }), jsx(BaseBadge, {
30
+ backgroundColor: WatermelonRed110,
31
+ className: clsx({
32
+ [styles.numericBadge]: true,
33
+ [styles.numericBadgeMoreDigits]: value.length > 1,
34
+ [styles.numericBadgeSingleDigit]: value.length === 1
35
+ }),
36
+ offset: offset,
37
+ size: "medium",
38
+ children: jsx(Text, {
39
+ as: "span",
40
+ color: "textOnDarkDefault",
41
+ id: valueId,
42
+ variant: "labelBold",
43
+ children: value
44
+ })
45
+ })]
46
+ });
47
+ });
48
+
49
+ export { NumericBadge };
@@ -0,0 +1,8 @@
1
+ /// <reference types="react" />
2
+ import { type BadgeProps } from './types';
3
+ export interface StatusBadgeProps extends BadgeProps {
4
+ /** The variant for the status */
5
+ variant: 'online';
6
+ }
7
+ export declare const StatusBadgeVariants: "online"[];
8
+ export declare const StatusBadge: (props: StatusBadgeProps) => JSX.Element;
@@ -0,0 +1,37 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { GreenLight120 } from '@box/blueprint-web-assets/tokens/tokens';
3
+ import { Children } from 'react';
4
+ import { BaseBadge } from './base-badge.js';
5
+ import styles from './base-badge.module.js';
6
+
7
+ const variantToBaseBadgeProp = {
8
+ online: {
9
+ backgroundColor: GreenLight120,
10
+ children: null
11
+ }
12
+ };
13
+ const StatusBadge = props => {
14
+ const {
15
+ variant,
16
+ size,
17
+ children,
18
+ offset
19
+ } = props;
20
+ if (Children.count(children) !== 1) {
21
+ if (process.env.NODE_ENV !== 'production') {
22
+ // eslint-disable-next-line no-console
23
+ console.error('StatusBadge component requires exactly one child');
24
+ }
25
+ }
26
+ return jsxs("div", {
27
+ className: styles.badgeContainer,
28
+ children: [children, jsx(BaseBadge, {
29
+ ...variantToBaseBadgeProp[variant],
30
+ className: styles.statusBadge,
31
+ offset: offset,
32
+ size: size
33
+ })]
34
+ });
35
+ };
36
+
37
+ export { StatusBadge };
@@ -0,0 +1,14 @@
1
+ /// <reference types="react" />
2
+ export interface BadgeProps {
3
+ /** Accepts exactly a single child component. Badge will be displayed over the child. */
4
+ children: React.ReactNode;
5
+ /** The size of the badge */
6
+ size: 'small' | 'medium' | 'large' | 'xlarge';
7
+ /** The offset in pixels from the default position of the badge. Accepts positive and negative integers. */
8
+ offset?: {
9
+ top?: number;
10
+ right?: number;
11
+ bottom?: number;
12
+ left?: number;
13
+ };
14
+ }
@@ -1,4 +1,4 @@
1
1
  /// <reference types="react" />
2
2
  import { type ContentFieldProps } from './types';
3
3
  export declare const contentFieldButtonTestId = "ContentField-button";
4
- export declare const ContentField: ({ clearButtonAriaLabel, itemIcon, hintText, isSharedFolder, onClick, onClickClearButton, title, error, }: ContentFieldProps) => JSX.Element;
4
+ export declare const ContentField: import("react").ForwardRefExoticComponent<ContentFieldProps & import("react").RefAttributes<HTMLButtonElement>>;
@@ -4,7 +4,7 @@ import { FolderShared } from '@box/blueprint-web-assets/icons/Content';
4
4
  import { XMark, Folder } from '@box/blueprint-web-assets/icons/Fill';
5
5
  import { Space6, Space4 } from '@box/blueprint-web-assets/tokens/tokens';
6
6
  import clsx from 'clsx';
7
- import { createRef } from 'react';
7
+ import { forwardRef, createRef } from 'react';
8
8
  import { InlineError } from '../primitives/inline-error/inline-error.js';
9
9
  import { useFullTextTooltip } from '../utils/useFullTextTooltip.js';
10
10
  import styles from './content-field.module.js';
@@ -47,7 +47,7 @@ const handleOnClickClearButton = ({
47
47
  onClickClearButton(e);
48
48
  };
49
49
  const contentFieldButtonTestId = 'ContentField-button';
50
- const ContentField = ({
50
+ const ContentField = /*#__PURE__*/forwardRef(({
51
51
  clearButtonAriaLabel,
52
52
  itemIcon,
53
53
  hintText,
@@ -56,13 +56,13 @@ const ContentField = ({
56
56
  onClickClearButton,
57
57
  title,
58
58
  error
59
- }) => {
60
- const ref = /*#__PURE__*/createRef();
59
+ }, forwardedRef) => {
60
+ const labelRef = /*#__PURE__*/createRef();
61
61
  const {
62
62
  Wrapper: Tooltip,
63
63
  wrapperProps
64
64
  } = useFullTextTooltip({
65
- ref,
65
+ ref: labelRef,
66
66
  textValue: title ?? hintText
67
67
  });
68
68
  return jsxs("div", {
@@ -72,6 +72,7 @@ const ContentField = ({
72
72
  children: [jsx(Tooltip, {
73
73
  ...wrapperProps,
74
74
  children: jsxs(Button, {
75
+ ref: forwardedRef,
75
76
  className: clsx(styles.contentButton, {
76
77
  [styles.hasSelection]: title,
77
78
  [styles.error]: !!error
@@ -85,7 +86,7 @@ const ContentField = ({
85
86
  }), jsx("div", {
86
87
  className: styles.contentLabelWrapper,
87
88
  children: jsx("div", {
88
- ref: ref,
89
+ ref: labelRef,
89
90
  className: styles.contentLabel,
90
91
  children: title ?? hintText
91
92
  })
@@ -98,7 +99,7 @@ const ContentField = ({
98
99
  [styles.error]: !!error
99
100
  }),
100
101
  onClick: handleOnClickClearButton({
101
- ref,
102
+ ref: labelRef,
102
103
  onClickClearButton
103
104
  }),
104
105
  type: "button",
@@ -113,6 +114,6 @@ const ContentField = ({
113
114
  children: error
114
115
  })]
115
116
  });
116
- };
117
+ });
117
118
 
118
119
  export { ContentField, contentFieldButtonTestId };
package/lib-esm/index.css CHANGED
@@ -801,6 +801,74 @@
801
801
  top:0;
802
802
  }
803
803
 
804
+ .bp_base_badge_module_badgeContainer--251c2{
805
+ display:inline-flex;
806
+ position:relative;
807
+ }
808
+
809
+ .bp_base_badge_module_badge--251c2{
810
+ align-items:center;
811
+ border:var(--border-2) solid var(--border-badge-border);
812
+ border-radius:2rem;
813
+ box-sizing:initial !important;
814
+ display:flex;
815
+ justify-content:center;
816
+ position:absolute;
817
+ }
818
+
819
+ .bp_base_badge_module_smallSizeBadge--251c2{
820
+ height:var(--size-2);
821
+ min-width:var(--size-2);
822
+ }
823
+
824
+ .bp_base_badge_module_mediumSizeBadge--251c2{
825
+ height:var(--size-3);
826
+ min-width:var(--size-3);
827
+ }
828
+
829
+ .bp_base_badge_module_largeSizeBadge--251c2{
830
+ height:var(--size-4);
831
+ min-width:var(--size-4);
832
+ }
833
+
834
+ .bp_base_badge_module_xlargeSizeBadge--251c2{
835
+ height:var(--size-5);
836
+ min-width:var(--size-5);
837
+ }
838
+
839
+ .bp_base_badge_module_iconBadge--251c2{
840
+ bottom:-5%;
841
+ right:-5%;
842
+ }
843
+
844
+ .bp_base_badge_module_statusBadge--251c2{
845
+ bottom:-20%;
846
+ right:-20%;
847
+ }
848
+
849
+ .bp_base_badge_module_statusBadge--251c2.bp_base_badge_module_largeSizeBadge--251c2{
850
+ bottom:-22%;
851
+ right:-22%;
852
+ }
853
+
854
+ .bp_base_badge_module_statusBadge--251c2.bp_base_badge_module_xlargeSizeBadge--251c2{
855
+ bottom:-15%;
856
+ right:-15%;
857
+ }
858
+
859
+ .bp_base_badge_module_numericBadge--251c2{
860
+ left:60%;
861
+ top:0;
862
+ }
863
+
864
+ .bp_base_badge_module_numericBadgeSingleDigit--251c2{
865
+ padding:1px;
866
+ }
867
+
868
+ .bp_base_badge_module_numericBadgeMoreDigits--251c2{
869
+ padding:1px 3px;
870
+ }
871
+
804
872
  .bp_card_module_card--aac33{
805
873
  background:var(--surface-card-surface);
806
874
  border:var(--border-1) solid var(--border-card-border);
@@ -1,6 +1,7 @@
1
1
  export * from './accordion';
2
2
  export * from './actionable-inline-notice';
3
3
  export * from './avatar';
4
+ export * from './badge';
4
5
  export * from './branding-styles';
5
6
  export * from './button';
6
7
  export * from './card';
package/lib-esm/index.js CHANGED
@@ -1,6 +1,9 @@
1
1
  export { Accordion } from './accordion/accordion.js';
2
2
  export { ActionableInlineNotice } from './actionable-inline-notice/index.js';
3
3
  export { Avatar } from './avatar/avatar.js';
4
+ export { IconBadge } from './badge/icon-badge.js';
5
+ export { NumericBadge } from './badge/numeric-badge.js';
6
+ export { StatusBadge } from './badge/status-badge.js';
4
7
  export { BrandingStyles } from './branding-styles/branding-styles.js';
5
8
  export { useCustomBranding } from './branding-styles/useCustomBranding.js';
6
9
  export { Button } from './button/button.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@box/blueprint-web",
3
- "version": "7.8.0",
3
+ "version": "7.10.0",
4
4
  "license": "SEE LICENSE IN LICENSE",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -57,7 +57,7 @@
57
57
  "@box/storybook-utils": "^0.2.1",
58
58
  "react-stately": "^3.31.1"
59
59
  },
60
- "gitHead": "cca3b51a9667470b94e0898699f1c2ed8ccdc4cd",
60
+ "gitHead": "1c4894acc4c1c6e26e2ce2bda5dcb5d500b9a0db",
61
61
  "module": "lib-esm/index.js",
62
62
  "main": "lib-esm/index.js",
63
63
  "exports": {