@box/blueprint-web 7.10.3 → 7.11.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/lib-esm/index.css +44 -0
- package/lib-esm/index.d.ts +1 -0
- package/lib-esm/index.js +1 -0
- package/lib-esm/text-toggle-button/index.d.ts +2 -0
- package/lib-esm/text-toggle-button/text-toggle-button.d.ts +3 -0
- package/lib-esm/text-toggle-button/text-toggle-button.js +40 -0
- package/lib-esm/text-toggle-button/text-toggle-button.module.js +4 -0
- package/lib-esm/text-toggle-button/types.d.ts +21 -0
- package/lib-esm/utils/composeEventHandlers.d.ts +4 -0
- package/lib-esm/utils/composeEventHandlers.js +13 -0
- package/lib-esm/utils/useCallbackRef.d.ts +6 -0
- package/lib-esm/utils/useCallbackRef.js +18 -0
- package/lib-esm/utils/useControllableState.d.ts +8 -0
- package/lib-esm/utils/useControllableState.js +48 -0
- package/package.json +3 -3
package/lib-esm/index.css
CHANGED
|
@@ -5285,6 +5285,50 @@ table.bp_inline_table_module_inlineTable--b023b tr:not(:last-child) td{
|
|
|
5285
5285
|
.bp_text_input_module_textInput--3c0cc input:has(+ .bp_text_input_module_iconLoading--3c0cc){
|
|
5286
5286
|
padding-inline-end:1.875rem;
|
|
5287
5287
|
}
|
|
5288
|
+
|
|
5289
|
+
.bp_text_toggle_button_module_textToggleButton--527c5{
|
|
5290
|
+
background:var(--surface-toggle-surface);
|
|
5291
|
+
border:var(--border-1) solid var(--border-switch-border);
|
|
5292
|
+
border-radius:var(--radius-2);
|
|
5293
|
+
color:var(--text-text-on-light);
|
|
5294
|
+
cursor:pointer;
|
|
5295
|
+
font-family:Lato, -apple-system, BlinkMacSystemFont, "San Francisco", "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
|
|
5296
|
+
font-size:.875rem;
|
|
5297
|
+
font-weight:400;
|
|
5298
|
+
letter-spacing:.01875rem;
|
|
5299
|
+
line-height:1.25rem;
|
|
5300
|
+
min-height:var(--size-8);
|
|
5301
|
+
outline:0;
|
|
5302
|
+
padding-inline:var(--space-2);
|
|
5303
|
+
text-decoration:none;
|
|
5304
|
+
text-transform:none;
|
|
5305
|
+
-webkit-user-select:none;
|
|
5306
|
+
user-select:none;
|
|
5307
|
+
white-space:nowrap;
|
|
5308
|
+
}
|
|
5309
|
+
.bp_text_toggle_button_module_textToggleButton--527c5:disabled{
|
|
5310
|
+
opacity:.3;
|
|
5311
|
+
pointer-events:none;
|
|
5312
|
+
}
|
|
5313
|
+
.bp_text_toggle_button_module_textToggleButton--527c5[data-focus-visible]{
|
|
5314
|
+
box-shadow:0 0 0 .0625rem #fff,0 0 0 .1875rem #2486fc;
|
|
5315
|
+
}
|
|
5316
|
+
.bp_text_toggle_button_module_textToggleButton--527c5:active,.bp_text_toggle_button_module_textToggleButton--527c5[data-focus-visible]{
|
|
5317
|
+
background:var(--surface-switch-surface-hover);
|
|
5318
|
+
border:var(--border-1) solid var(--border-switch-border-hover);
|
|
5319
|
+
}
|
|
5320
|
+
.bp_text_toggle_button_module_textToggleButton--527c5:hover{
|
|
5321
|
+
background:var(--surface-toggle-surface-hover);
|
|
5322
|
+
}
|
|
5323
|
+
.bp_text_toggle_button_module_textToggleButton--527c5[aria-pressed=true]{
|
|
5324
|
+
background:var(--surface-toggle-surface-pressed);
|
|
5325
|
+
border:var(--border-1) solid var(--surface-toggle-surface-pressed);
|
|
5326
|
+
color:var(--text-text-on-dark);
|
|
5327
|
+
}
|
|
5328
|
+
.bp_text_toggle_button_module_textToggleButton--527c5[aria-pressed=true]:active,.bp_text_toggle_button_module_textToggleButton--527c5[aria-pressed=true]:hover,.bp_text_toggle_button_module_textToggleButton--527c5[aria-pressed=true][data-focus-visible]{
|
|
5329
|
+
background:var(--surface-toggle-surface-pressed-hover);
|
|
5330
|
+
border:var(--border-1) solid var(--surface-toggle-surface-pressed-hover);
|
|
5331
|
+
}
|
|
5288
5332
|
:root{
|
|
5289
5333
|
--notification-default-paragraph-indent:0rem;
|
|
5290
5334
|
--notification-default-paragraph-spacing:0;
|
package/lib-esm/index.d.ts
CHANGED
package/lib-esm/index.js
CHANGED
|
@@ -69,6 +69,7 @@ export { Text } from './text/text.js';
|
|
|
69
69
|
export { TextArea } from './text-area/text-area.js';
|
|
70
70
|
export { TextButton } from './text-button/text-button.js';
|
|
71
71
|
export { TextInput } from './text-input/text-input.js';
|
|
72
|
+
export { TextToggleButton } from './text-toggle-button/text-toggle-button.js';
|
|
72
73
|
export { Toolbar } from './toolbar/index.js';
|
|
73
74
|
export { Tooltip, TooltipProvider } from './tooltip/tooltip.js';
|
|
74
75
|
export { TriggerButton } from './trigger-button/trigger-button.js';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Button } from '@ariakit/react';
|
|
3
|
+
import clsx from 'clsx';
|
|
4
|
+
import { forwardRef } from 'react';
|
|
5
|
+
import { composeEventHandlers } from '../utils/composeEventHandlers.js';
|
|
6
|
+
import { useControllableState } from '../utils/useControllableState.js';
|
|
7
|
+
import styles from './text-toggle-button.module.js';
|
|
8
|
+
|
|
9
|
+
const TextToggleButton = /*#__PURE__*/forwardRef(({
|
|
10
|
+
pressed: pressedProp,
|
|
11
|
+
defaultPressed = false,
|
|
12
|
+
onPressedChange,
|
|
13
|
+
disabled,
|
|
14
|
+
onClick,
|
|
15
|
+
className,
|
|
16
|
+
...rest
|
|
17
|
+
}, ref) => {
|
|
18
|
+
const [pressed = false, setPressed] = useControllableState({
|
|
19
|
+
prop: pressedProp,
|
|
20
|
+
onChange: onPressedChange,
|
|
21
|
+
defaultProp: defaultPressed
|
|
22
|
+
});
|
|
23
|
+
return jsx(Button, {
|
|
24
|
+
"aria-pressed": pressed,
|
|
25
|
+
"data-disabled": disabled ? '' : undefined,
|
|
26
|
+
"data-state": pressed ? 'on' : 'off',
|
|
27
|
+
...rest,
|
|
28
|
+
ref: ref,
|
|
29
|
+
className: clsx(styles.textToggleButton, className),
|
|
30
|
+
disabled: disabled,
|
|
31
|
+
onClick: composeEventHandlers(onClick, () => {
|
|
32
|
+
if (!disabled) {
|
|
33
|
+
setPressed(!pressed);
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
TextToggleButton.displayName = 'TextToggleButton';
|
|
39
|
+
|
|
40
|
+
export { TextToggleButton };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type ButtonProps as AriakitButtonProps } from '@ariakit/react';
|
|
2
|
+
export interface TextToggleButtonProps extends AriakitButtonProps {
|
|
3
|
+
/**
|
|
4
|
+
* The text content of the button.
|
|
5
|
+
*/
|
|
6
|
+
children: string;
|
|
7
|
+
/**
|
|
8
|
+
* The controlled state of the toggle.
|
|
9
|
+
*/
|
|
10
|
+
pressed?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* The state of the toggle when initially rendered. Use `defaultPressed`
|
|
13
|
+
* if you do not need to control the state of the toggle.
|
|
14
|
+
* @defaultValue false
|
|
15
|
+
*/
|
|
16
|
+
defaultPressed?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* The callback that fires when the state of the toggle changes.
|
|
19
|
+
*/
|
|
20
|
+
onPressedChange?(pressed: boolean): void;
|
|
21
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// copy of radix function: https://github.com/radix-ui/primitives/blob/main/packages/core/primitive/src/primitive.tsx
|
|
2
|
+
function composeEventHandlers(originalEventHandler, ourEventHandler, {
|
|
3
|
+
checkForDefaultPrevented = true
|
|
4
|
+
} = {}) {
|
|
5
|
+
return function handleEvent(event) {
|
|
6
|
+
originalEventHandler?.(event);
|
|
7
|
+
if (checkForDefaultPrevented === false || !event.defaultPrevented) {
|
|
8
|
+
ourEventHandler?.(event);
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export { composeEventHandlers };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A custom hook that converts a callback to a ref to avoid triggering re-renders when passed as a
|
|
3
|
+
* prop or avoid re-executing effects when passed as a dependency
|
|
4
|
+
*/
|
|
5
|
+
declare function useCallbackRef<T extends (...args: any[]) => any>(callback: T | undefined): T;
|
|
6
|
+
export { useCallbackRef };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
// copy of radix hook: https://github.com/radix-ui/primitives/blob/main/packages/react/use-callback-ref/src/useCallbackRef.tsx
|
|
4
|
+
/**
|
|
5
|
+
* A custom hook that converts a callback to a ref to avoid triggering re-renders when passed as a
|
|
6
|
+
* prop or avoid re-executing effects when passed as a dependency
|
|
7
|
+
*/
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
9
|
+
function useCallbackRef(callback) {
|
|
10
|
+
const callbackRef = React.useRef(callback);
|
|
11
|
+
React.useEffect(() => {
|
|
12
|
+
callbackRef.current = callback;
|
|
13
|
+
});
|
|
14
|
+
// https://github.com/facebook/react/issues/19240
|
|
15
|
+
return React.useMemo(() => (...args) => callbackRef.current?.(...args), []);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { useCallbackRef };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
interface UseControllableStateParams<T> {
|
|
3
|
+
prop?: T | undefined;
|
|
4
|
+
defaultProp?: T | undefined;
|
|
5
|
+
onChange?: (state: T) => void;
|
|
6
|
+
}
|
|
7
|
+
declare function useControllableState<T>({ prop, defaultProp, onChange }: UseControllableStateParams<T>): readonly [T | undefined, React.Dispatch<React.SetStateAction<T | undefined>>];
|
|
8
|
+
export { useControllableState };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useCallbackRef } from './useCallbackRef.js';
|
|
3
|
+
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
5
|
+
function useControllableState({
|
|
6
|
+
prop,
|
|
7
|
+
defaultProp,
|
|
8
|
+
onChange = () => {}
|
|
9
|
+
}) {
|
|
10
|
+
const [uncontrolledProp, setUncontrolledProp] = useUncontrolledState({
|
|
11
|
+
defaultProp,
|
|
12
|
+
onChange
|
|
13
|
+
});
|
|
14
|
+
const isControlled = prop !== undefined;
|
|
15
|
+
const value = isControlled ? prop : uncontrolledProp;
|
|
16
|
+
const handleChange = useCallbackRef(onChange);
|
|
17
|
+
const setValue = React.useCallback(nextValue => {
|
|
18
|
+
if (isControlled) {
|
|
19
|
+
const setter = nextValue;
|
|
20
|
+
// renamed variable since it overlapped with variable "value" in the outer scope of hook
|
|
21
|
+
const internalValue = typeof nextValue === 'function' ? setter(prop) : nextValue;
|
|
22
|
+
if (internalValue !== prop) {
|
|
23
|
+
handleChange(internalValue);
|
|
24
|
+
}
|
|
25
|
+
} else {
|
|
26
|
+
setUncontrolledProp(nextValue);
|
|
27
|
+
}
|
|
28
|
+
}, [isControlled, prop, setUncontrolledProp, handleChange]);
|
|
29
|
+
return [value, setValue];
|
|
30
|
+
}
|
|
31
|
+
function useUncontrolledState({
|
|
32
|
+
defaultProp,
|
|
33
|
+
onChange
|
|
34
|
+
}) {
|
|
35
|
+
const uncontrolledState = React.useState(defaultProp);
|
|
36
|
+
const [value] = uncontrolledState;
|
|
37
|
+
const prevValueRef = React.useRef(value);
|
|
38
|
+
const handleChange = useCallbackRef(onChange);
|
|
39
|
+
React.useEffect(() => {
|
|
40
|
+
if (prevValueRef.current !== value) {
|
|
41
|
+
handleChange(value);
|
|
42
|
+
prevValueRef.current = value;
|
|
43
|
+
}
|
|
44
|
+
}, [value, prevValueRef, handleChange]);
|
|
45
|
+
return uncontrolledState;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export { useControllableState };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@box/blueprint-web",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.11.0",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
@@ -54,10 +54,10 @@
|
|
|
54
54
|
"type-fest": "^3.2.0"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@box/storybook-utils": "^0.
|
|
57
|
+
"@box/storybook-utils": "^0.3.0",
|
|
58
58
|
"react-stately": "^3.31.1"
|
|
59
59
|
},
|
|
60
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "64f24026d06c71ca4145bf9f77a9adb4acd37787",
|
|
61
61
|
"module": "lib-esm/index.js",
|
|
62
62
|
"main": "lib-esm/index.js",
|
|
63
63
|
"exports": {
|