@react-spectrum/s2 3.0.0-nightly-4b2c6e76f-250325 → 3.0.0-nightly-d7511d723-250327
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/ActionButton.cjs +25 -7
- package/dist/ActionButton.cjs.map +1 -1
- package/dist/ActionButton.css +78 -18
- package/dist/ActionButton.css.map +1 -1
- package/dist/ActionButton.mjs +25 -7
- package/dist/ActionButton.mjs.map +1 -1
- package/dist/NotificationBadge.cjs +155 -0
- package/dist/NotificationBadge.cjs.map +1 -0
- package/dist/NotificationBadge.css +211 -0
- package/dist/NotificationBadge.css.map +1 -0
- package/dist/NotificationBadge.mjs +149 -0
- package/dist/NotificationBadge.mjs.map +1 -0
- package/dist/en-US.cjs +2 -0
- package/dist/en-US.cjs.map +1 -1
- package/dist/en-US.mjs +2 -0
- package/dist/en-US.mjs.map +1 -1
- package/dist/main.cjs +4 -0
- package/dist/main.cjs.map +1 -1
- package/dist/module.mjs +3 -1
- package/dist/module.mjs.map +1 -1
- package/dist/types.d.ts +20 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +19 -18
- package/src/ActionButton.tsx +36 -2
- package/src/NotificationBadge.tsx +160 -0
- package/src/index.ts +2 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 Adobe. All rights reserved.
|
|
3
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
*
|
|
7
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
* governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {AriaLabelingProps, DOMProps, DOMRef, DOMRefValue} from '@react-types/shared';
|
|
14
|
+
import {ContextValue, SlotProps} from 'react-aria-components';
|
|
15
|
+
import {filterDOMProps} from '@react-aria/utils';
|
|
16
|
+
import {fontRelative, style} from '../style' with {type: 'macro'};
|
|
17
|
+
import {getAllowedOverrides, StyleProps} from './style-utils' with {type: 'macro'};
|
|
18
|
+
// @ts-ignore
|
|
19
|
+
import intlMessages from '../intl/*.json';
|
|
20
|
+
import {NumberFormatter} from '@internationalized/number';
|
|
21
|
+
import React, {createContext, forwardRef} from 'react';
|
|
22
|
+
import {useDOMRef} from '@react-spectrum/utils';
|
|
23
|
+
import {useLocale, useLocalizedStringFormatter} from '@react-aria/i18n';
|
|
24
|
+
import {useSpectrumContextProps} from './useSpectrumContextProps';
|
|
25
|
+
|
|
26
|
+
export interface NotificationBadgeStyleProps {
|
|
27
|
+
/**
|
|
28
|
+
* The size of the notification badge.
|
|
29
|
+
*
|
|
30
|
+
* @default 'S'
|
|
31
|
+
*/
|
|
32
|
+
size?: 'S' | 'M' | 'L' | 'XL'
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface NotificationBadgeProps extends DOMProps, AriaLabelingProps, StyleProps, NotificationBadgeStyleProps, SlotProps {
|
|
36
|
+
/**
|
|
37
|
+
* The value to be displayed in the notification badge.
|
|
38
|
+
*/
|
|
39
|
+
value?: number | null
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const NotificationBadgeContext = createContext<ContextValue<Partial<NotificationBadgeProps>, DOMRefValue<HTMLDivElement>>>(null);
|
|
43
|
+
|
|
44
|
+
const badge = style({
|
|
45
|
+
display: 'flex',
|
|
46
|
+
font: 'control',
|
|
47
|
+
color: {
|
|
48
|
+
default: 'white',
|
|
49
|
+
forcedColors: 'ButtonText'
|
|
50
|
+
},
|
|
51
|
+
fontSize: {
|
|
52
|
+
size: {
|
|
53
|
+
S: 'ui-xs',
|
|
54
|
+
M: 'ui-xs',
|
|
55
|
+
L: 'ui-sm',
|
|
56
|
+
XL: 'ui'
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
borderStyle: {
|
|
60
|
+
forcedColors: 'solid'
|
|
61
|
+
},
|
|
62
|
+
borderWidth: {
|
|
63
|
+
forcedColors: '[1px]'
|
|
64
|
+
},
|
|
65
|
+
borderColor: {
|
|
66
|
+
forcedColors: 'ButtonBorder'
|
|
67
|
+
},
|
|
68
|
+
justifyContent: 'center',
|
|
69
|
+
alignItems: 'center',
|
|
70
|
+
backgroundColor: {
|
|
71
|
+
default: 'accent',
|
|
72
|
+
forcedColors: 'ButtonFace'
|
|
73
|
+
},
|
|
74
|
+
height: {
|
|
75
|
+
size: {
|
|
76
|
+
S: {
|
|
77
|
+
default: 12,
|
|
78
|
+
isIndicatorOnly: 8
|
|
79
|
+
},
|
|
80
|
+
M: {
|
|
81
|
+
default: fontRelative(18), // sort of arbitrary? tried to get as close to the figma designs as possible
|
|
82
|
+
isIndicatorOnly: 8
|
|
83
|
+
},
|
|
84
|
+
L: {
|
|
85
|
+
default: 16,
|
|
86
|
+
isIndicatorOnly: fontRelative(12)
|
|
87
|
+
},
|
|
88
|
+
XL: {
|
|
89
|
+
default: 18,
|
|
90
|
+
isIndicatorOnly: fontRelative(12)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
aspectRatio: {
|
|
95
|
+
isIndicatorOnly: 'square',
|
|
96
|
+
isSingleDigit: 'square'
|
|
97
|
+
},
|
|
98
|
+
width: 'fit',
|
|
99
|
+
paddingX: {
|
|
100
|
+
isDoubleDigit: 'edge-to-text'
|
|
101
|
+
},
|
|
102
|
+
borderRadius: 'pill'
|
|
103
|
+
}, getAllowedOverrides());
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Notification badges are used to indicate new or pending activity .
|
|
107
|
+
*/
|
|
108
|
+
export const NotificationBadge = forwardRef(function Badge(props: NotificationBadgeProps, ref: DOMRef<HTMLDivElement>) {
|
|
109
|
+
let stringFormatter = useLocalizedStringFormatter(intlMessages, '@react-spectrum/s2');
|
|
110
|
+
[props, ref] = useSpectrumContextProps(props, ref, NotificationBadgeContext);
|
|
111
|
+
let {
|
|
112
|
+
size = 'S',
|
|
113
|
+
value,
|
|
114
|
+
...otherProps
|
|
115
|
+
} = props;
|
|
116
|
+
let domRef = useDOMRef(ref);
|
|
117
|
+
let {locale} = useLocale();
|
|
118
|
+
let formattedValue = '';
|
|
119
|
+
|
|
120
|
+
let isIndicatorOnly = false;
|
|
121
|
+
let isSingleDigit = false;
|
|
122
|
+
let isDoubleDigit = false;
|
|
123
|
+
|
|
124
|
+
if (value == null) {
|
|
125
|
+
isIndicatorOnly = true;
|
|
126
|
+
} else if (value <= 0) {
|
|
127
|
+
throw new Error('Value cannot be negative or zero');
|
|
128
|
+
} else if (!Number.isInteger(value)) {
|
|
129
|
+
throw new Error('Value must be a positive integer');
|
|
130
|
+
} else {
|
|
131
|
+
formattedValue = new NumberFormatter(locale).format(Math.min(value, 99));
|
|
132
|
+
let length = Math.log(value <= 99 ? value : 99) * Math.LOG10E + 1 | 0; // for positive integers (https://stackoverflow.com/questions/14879691/get-number-of-digits-with-javascript)
|
|
133
|
+
if (length === 1) {
|
|
134
|
+
isSingleDigit = true;
|
|
135
|
+
} else if (length === 2) {
|
|
136
|
+
isDoubleDigit = true;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (value > 99) {
|
|
140
|
+
formattedValue = stringFormatter.format('notificationbadge.plus', {notifications: formattedValue});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
let ariaLabel = props['aria-label'] || undefined;
|
|
145
|
+
if (ariaLabel === undefined && isIndicatorOnly) {
|
|
146
|
+
ariaLabel = stringFormatter.format('notificationbadge.indicatorOnly');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return (
|
|
150
|
+
<span
|
|
151
|
+
{...filterDOMProps(otherProps, {labelable: true})}
|
|
152
|
+
role={ariaLabel && 'img'}
|
|
153
|
+
aria-label={ariaLabel}
|
|
154
|
+
className={(props.UNSAFE_className || '') + badge({size, isIndicatorOnly, isSingleDigit, isDoubleDigit}, props.styles)}
|
|
155
|
+
style={props.UNSAFE_style}
|
|
156
|
+
ref={domRef}>
|
|
157
|
+
{formattedValue}
|
|
158
|
+
</span>
|
|
159
|
+
);
|
|
160
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -53,6 +53,7 @@ export {InlineAlert, InlineAlertContext} from './InlineAlert';
|
|
|
53
53
|
export {Link, LinkContext} from './Link';
|
|
54
54
|
export {MenuItem, MenuTrigger, Menu, MenuSection, SubmenuTrigger, MenuContext} from './Menu';
|
|
55
55
|
export {Meter, MeterContext} from './Meter';
|
|
56
|
+
export {NotificationBadge, NotificationBadgeContext} from './NotificationBadge';
|
|
56
57
|
export {NumberField, NumberFieldContext} from './NumberField';
|
|
57
58
|
export {Picker, PickerItem, PickerSection, PickerContext} from './Picker';
|
|
58
59
|
export {Popover} from './Popover';
|
|
@@ -123,6 +124,7 @@ export type {ImageCoordinatorProps} from './ImageCoordinator';
|
|
|
123
124
|
export type {LinkProps} from './Link';
|
|
124
125
|
export type {MenuTriggerProps, MenuProps, MenuItemProps, MenuSectionProps, SubmenuTriggerProps} from './Menu';
|
|
125
126
|
export type {MeterProps} from './Meter';
|
|
127
|
+
export type {NotificationBadgeProps} from './NotificationBadge';
|
|
126
128
|
export type {PickerProps, PickerItemProps, PickerSectionProps} from './Picker';
|
|
127
129
|
export type {PopoverProps} from './Popover';
|
|
128
130
|
export type {ProgressBarProps} from './ProgressBar';
|