@spark-web/button 1.1.0 → 1.2.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/README.md +14 -22
- package/dist/declarations/src/BaseButton.d.ts +10 -0
- package/dist/declarations/src/Button.d.ts +1 -7
- package/dist/declarations/src/ButtonLink.d.ts +1 -1
- package/dist/declarations/src/index.d.ts +2 -0
- package/dist/declarations/src/resolveButtonChildren.d.ts +1 -0
- package/dist/spark-web-button.cjs.dev.js +71 -41
- package/dist/spark-web-button.cjs.prod.js +71 -41
- package/dist/spark-web-button.esm.js +71 -42
- package/package.json +11 -11
package/README.md
CHANGED
|
@@ -196,25 +196,17 @@ with the exception of `href` vs `onClick` props.
|
|
|
196
196
|
</Text>
|
|
197
197
|
```
|
|
198
198
|
|
|
199
|
-
##
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
| onClick? | Function | | Function to be fired following a click event of the button. Only applicable for `Button`. |
|
|
214
|
-
| prominence? | 'high' \| 'low' | 'high' | Sets the visual prominence of the button. |
|
|
215
|
-
| size? | 'medium' \| 'large' | 'medium' | Sets the size of the button. |
|
|
216
|
-
| tone? | 'primary' \| 'secondary' \| 'neutral' \| 'positive' \| 'caution' \| 'critical' \| 'info' | 'primary' | Sets the tone of the button. |
|
|
217
|
-
| type? | 'button' \| 'submit' \| 'reset' | 'button' | Sets the button type. Only applicable for `Button`. |
|
|
218
|
-
|
|
219
|
-
[data-attribute-map]:
|
|
220
|
-
https://github.com/brighte-labs/spark-web/blob/e7f6f4285b4cfd876312cc89fbdd094039aa239a/packages/utils/src/internal/buildDataAttributes.ts#L1
|
|
199
|
+
## BaseButton
|
|
200
|
+
|
|
201
|
+
Unstyled button primitive that:
|
|
202
|
+
|
|
203
|
+
- Forwards the button ref
|
|
204
|
+
- Provides a default type of `button` (so it doesn't accidently submit forms if
|
|
205
|
+
left off)
|
|
206
|
+
- Prevents `onClick` from firing when disabled without disabling the button
|
|
207
|
+
- Forces focus of the underlying button when clicked (to address a bug in
|
|
208
|
+
Safari)
|
|
209
|
+
|
|
210
|
+
## Button Props
|
|
211
|
+
|
|
212
|
+
<PropsTable displayName="Button" />
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { BoxProps } from '@spark-web/box';
|
|
2
|
+
import type { MouseEvent as ReactMouseEvent } from 'react';
|
|
3
|
+
import type { NativeButtonProps } from './types';
|
|
4
|
+
export declare type BaseButtonProps = NativeButtonProps & Partial<BoxProps>;
|
|
5
|
+
export declare const BaseButton: import("react").ForwardRefExoticComponent<NativeButtonProps & Partial<BoxProps> & import("react").RefAttributes<HTMLButtonElement>>;
|
|
6
|
+
/**
|
|
7
|
+
* handle "disabled" behaviour w/o disabling buttons
|
|
8
|
+
* @see https://axesslab.com/disabled-buttons-suck/
|
|
9
|
+
*/
|
|
10
|
+
export declare function getPreventableClickHandler(onClick: BaseButtonProps['onClick'], disabled: boolean): (event: ReactMouseEvent<HTMLButtonElement, MouseEvent>) => void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
/// <reference types="react" />
|
|
2
2
|
import type { CommonButtonProps, NativeButtonProps } from './types';
|
|
3
3
|
export declare type ButtonProps = CommonButtonProps & {
|
|
4
4
|
/**
|
|
@@ -26,9 +26,3 @@ export declare type ButtonProps = CommonButtonProps & {
|
|
|
26
26
|
* action will occur when the user interacts with it.
|
|
27
27
|
*/
|
|
28
28
|
export declare const Button: import("react").ForwardRefExoticComponent<ButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
29
|
-
/**
|
|
30
|
-
* Prevent click events when the component is "disabled".
|
|
31
|
-
* Note: we don't want to actually disable a button element for several reasons.
|
|
32
|
-
* One being because that would prohibit the use of tooltips.
|
|
33
|
-
*/
|
|
34
|
-
export declare function getPreventableClickHandler(onClick: NativeButtonProps['onClick'], disabled: boolean): (event: ReactMouseEvent<HTMLButtonElement, MouseEvent>) => void;
|
|
@@ -5,5 +5,5 @@ export declare type ButtonLinkProps = LinkComponentProps & CommonButtonProps;
|
|
|
5
5
|
/** The appearance of a `Button`, with the semantics of a link. */
|
|
6
6
|
export declare const ButtonLink: <Comp extends import("react").ElementType<any> = "a">(props: {
|
|
7
7
|
as?: Comp | undefined;
|
|
8
|
-
ref?: import("react").Ref<Comp extends "symbol" | "clipPath" | "filter" | "mask" | "marker" | "
|
|
8
|
+
ref?: import("react").Ref<Comp extends "symbol" | "clipPath" | "filter" | "mask" | "marker" | "svg" | "animate" | "animateMotion" | "animateTransform" | "circle" | "defs" | "desc" | "ellipse" | "feBlend" | "feColorMatrix" | "feComponentTransfer" | "feComposite" | "feConvolveMatrix" | "feDiffuseLighting" | "feDisplacementMap" | "feDistantLight" | "feDropShadow" | "feFlood" | "feFuncA" | "feFuncB" | "feFuncG" | "feFuncR" | "feGaussianBlur" | "feImage" | "feMerge" | "feMergeNode" | "feMorphology" | "feOffset" | "fePointLight" | "feSpecularLighting" | "feSpotLight" | "feTile" | "feTurbulence" | "foreignObject" | "g" | "image" | "line" | "linearGradient" | "metadata" | "mpath" | "path" | "pattern" | "polygon" | "polyline" | "radialGradient" | "rect" | "stop" | "switch" | "text" | "textPath" | "tspan" | "use" | "view" | keyof HTMLElementTagNameMap | "set" ? (HTMLElementTagNameMap & Pick<SVGElementTagNameMap, "symbol" | "clipPath" | "filter" | "mask" | "marker" | "svg" | "animate" | "animateMotion" | "animateTransform" | "circle" | "defs" | "desc" | "ellipse" | "feBlend" | "feColorMatrix" | "feComponentTransfer" | "feComposite" | "feConvolveMatrix" | "feDiffuseLighting" | "feDisplacementMap" | "feDistantLight" | "feDropShadow" | "feFlood" | "feFuncA" | "feFuncB" | "feFuncG" | "feFuncR" | "feGaussianBlur" | "feImage" | "feMerge" | "feMergeNode" | "feMorphology" | "feOffset" | "fePointLight" | "feSpecularLighting" | "feSpotLight" | "feTile" | "feTurbulence" | "foreignObject" | "g" | "image" | "line" | "linearGradient" | "metadata" | "mpath" | "path" | "pattern" | "polygon" | "polyline" | "radialGradient" | "rect" | "stop" | "switch" | "text" | "textPath" | "tspan" | "use" | "view" | "set">)[Comp] : Comp extends new (...args: any) => any ? InstanceType<Comp> : undefined> | undefined;
|
|
9
9
|
} & Omit<import("react").PropsWithoutRef<import("react").ComponentProps<Comp>>, "as"> & ButtonLinkProps) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
export { BaseButton } from './BaseButton';
|
|
1
2
|
export { Button } from './Button';
|
|
2
3
|
export { ButtonLink } from './ButtonLink';
|
|
4
|
+
export type { BaseButtonProps } from './BaseButton';
|
|
3
5
|
export type { ButtonProps } from './Button';
|
|
4
6
|
export type { ButtonLinkProps } from './ButtonLink';
|
|
@@ -4,18 +4,68 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var _objectSpread = require('@babel/runtime/helpers/objectSpread2');
|
|
6
6
|
var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties');
|
|
7
|
-
var a11y = require('@spark-web/a11y');
|
|
8
7
|
var box = require('@spark-web/box');
|
|
9
|
-
var
|
|
10
|
-
var internal = require('@spark-web/utils/internal');
|
|
8
|
+
var utils = require('@spark-web/utils');
|
|
11
9
|
var react = require('react');
|
|
12
|
-
var css = require('@emotion/css');
|
|
13
|
-
var text = require('@spark-web/text');
|
|
14
10
|
var jsxRuntime = require('react/jsx-runtime');
|
|
11
|
+
var a11y = require('@spark-web/a11y');
|
|
12
|
+
var spinner = require('@spark-web/spinner');
|
|
13
|
+
var text = require('@spark-web/text');
|
|
14
|
+
var css = require('@emotion/css');
|
|
15
15
|
var theme = require('@spark-web/theme');
|
|
16
16
|
var link = require('@spark-web/link');
|
|
17
|
+
var internal = require('@spark-web/utils/internal');
|
|
17
18
|
var ts = require('@spark-web/utils/ts');
|
|
18
19
|
|
|
20
|
+
var _excluded$2 = ["onClick", "disabled", "type"];
|
|
21
|
+
var BaseButton = /*#__PURE__*/react.forwardRef(function (_ref, forwardedRef) {
|
|
22
|
+
var onClickProp = _ref.onClick,
|
|
23
|
+
_ref$disabled = _ref.disabled,
|
|
24
|
+
disabled = _ref$disabled === void 0 ? false : _ref$disabled,
|
|
25
|
+
_ref$type = _ref.type,
|
|
26
|
+
type = _ref$type === void 0 ? 'button' : _ref$type,
|
|
27
|
+
rest = _objectWithoutProperties(_ref, _excluded$2);
|
|
28
|
+
|
|
29
|
+
var internalRef = react.useRef(null);
|
|
30
|
+
var composedRef = utils.useComposedRefs(internalRef, forwardedRef);
|
|
31
|
+
/**
|
|
32
|
+
* In Safari buttons are not focused automatically by the browser once
|
|
33
|
+
* pressed, the default behaviour is to focus the nearest focusable ancestor.
|
|
34
|
+
* To fix this we need to manually focus the button element after the user
|
|
35
|
+
* presses the element.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
var onClick = react.useCallback(function (event) {
|
|
39
|
+
var _internalRef$current;
|
|
40
|
+
|
|
41
|
+
(_internalRef$current = internalRef.current) === null || _internalRef$current === void 0 ? void 0 : _internalRef$current.focus();
|
|
42
|
+
var preventableClickHandler = getPreventableClickHandler(onClickProp, disabled);
|
|
43
|
+
preventableClickHandler(event);
|
|
44
|
+
}, [disabled, onClickProp]);
|
|
45
|
+
return /*#__PURE__*/jsxRuntime.jsx(box.Box, _objectSpread(_objectSpread({
|
|
46
|
+
as: "button"
|
|
47
|
+
}, rest), {}, {
|
|
48
|
+
onClick: onClick,
|
|
49
|
+
ref: composedRef,
|
|
50
|
+
type: type
|
|
51
|
+
}));
|
|
52
|
+
});
|
|
53
|
+
BaseButton.displayName = 'BaseButton';
|
|
54
|
+
/**
|
|
55
|
+
* handle "disabled" behaviour w/o disabling buttons
|
|
56
|
+
* @see https://axesslab.com/disabled-buttons-suck/
|
|
57
|
+
*/
|
|
58
|
+
|
|
59
|
+
function getPreventableClickHandler(onClick, disabled) {
|
|
60
|
+
return function handleClick(event) {
|
|
61
|
+
if (disabled) {
|
|
62
|
+
event.preventDefault();
|
|
63
|
+
} else {
|
|
64
|
+
onClick === null || onClick === void 0 ? void 0 : onClick(event);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
19
69
|
var variants = {
|
|
20
70
|
high: {
|
|
21
71
|
primary: {
|
|
@@ -203,10 +253,12 @@ var resolveButtonChildren = function resolveButtonChildren(_ref) {
|
|
|
203
253
|
function HiddenWhenLoading(_ref2) {
|
|
204
254
|
var children = _ref2.children,
|
|
205
255
|
isLoading = _ref2.isLoading;
|
|
206
|
-
return /*#__PURE__*/jsxRuntime.jsx(
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
256
|
+
return /*#__PURE__*/jsxRuntime.jsx(box.Box, {
|
|
257
|
+
as: "span",
|
|
258
|
+
display: "inline-flex",
|
|
259
|
+
alignItems: "center",
|
|
260
|
+
justifyContent: "center",
|
|
261
|
+
opacity: isLoading ? 0 : undefined,
|
|
210
262
|
children: children
|
|
211
263
|
});
|
|
212
264
|
}
|
|
@@ -274,13 +326,12 @@ var _excluded$1 = ["aria-controls", "aria-describedby", "aria-expanded", "data",
|
|
|
274
326
|
* Buttons are used to initialize an action, their label should express what
|
|
275
327
|
* action will occur when the user interacts with it.
|
|
276
328
|
*/
|
|
277
|
-
var Button = /*#__PURE__*/react.forwardRef(function (_ref,
|
|
329
|
+
var Button = /*#__PURE__*/react.forwardRef(function (_ref, forwardedRef) {
|
|
278
330
|
var ariaControls = _ref['aria-controls'],
|
|
279
331
|
ariaDescribedBy = _ref['aria-describedby'],
|
|
280
332
|
ariaExpanded = _ref['aria-expanded'],
|
|
281
333
|
data = _ref.data,
|
|
282
|
-
|
|
283
|
-
disabled = _ref$disabled === void 0 ? false : _ref$disabled,
|
|
334
|
+
disabled = _ref.disabled,
|
|
284
335
|
id = _ref.id,
|
|
285
336
|
_ref$loading = _ref.loading,
|
|
286
337
|
loading = _ref$loading === void 0 ? false : _ref$loading,
|
|
@@ -291,8 +342,7 @@ var Button = /*#__PURE__*/react.forwardRef(function (_ref, ref) {
|
|
|
291
342
|
size = _ref$size === void 0 ? 'medium' : _ref$size,
|
|
292
343
|
_ref$tone = _ref.tone,
|
|
293
344
|
tone = _ref$tone === void 0 ? 'primary' : _ref$tone,
|
|
294
|
-
|
|
295
|
-
type = _ref$type === void 0 ? 'button' : _ref$type,
|
|
345
|
+
type = _ref.type,
|
|
296
346
|
props = _objectWithoutProperties(_ref, _excluded$1);
|
|
297
347
|
|
|
298
348
|
var iconOnly = Boolean(props.label);
|
|
@@ -305,24 +355,18 @@ var Button = /*#__PURE__*/react.forwardRef(function (_ref, ref) {
|
|
|
305
355
|
var isDisabled = disabled || loading;
|
|
306
356
|
var isLoading = loading && !disabled;
|
|
307
357
|
var variant = variants[prominence][tone];
|
|
308
|
-
|
|
309
|
-
* handle "disabled" behaviour w/o disabling buttons
|
|
310
|
-
* @see https://axesslab.com/disabled-buttons-suck/
|
|
311
|
-
*/
|
|
312
|
-
|
|
313
|
-
var handleClick = getPreventableClickHandler(onClick, isDisabled);
|
|
314
|
-
return /*#__PURE__*/jsxRuntime.jsxs(box.Box, _objectSpread(_objectSpread(_objectSpread({
|
|
358
|
+
return /*#__PURE__*/jsxRuntime.jsxs(BaseButton, _objectSpread(_objectSpread({}, buttonStyleProps), {}, {
|
|
315
359
|
"aria-controls": ariaControls,
|
|
316
360
|
"aria-describedby": ariaDescribedBy,
|
|
317
361
|
"aria-disabled": isDisabled,
|
|
318
362
|
"aria-expanded": ariaExpanded,
|
|
319
363
|
"aria-label": props.label,
|
|
320
|
-
|
|
364
|
+
data: data,
|
|
365
|
+
disabled: isDisabled,
|
|
321
366
|
id: id,
|
|
322
|
-
onClick:
|
|
323
|
-
ref:
|
|
324
|
-
type: type
|
|
325
|
-
}, buttonStyleProps), data ? internal.buildDataAttributes(data) : undefined), {}, {
|
|
367
|
+
onClick: onClick,
|
|
368
|
+
ref: forwardedRef,
|
|
369
|
+
type: type,
|
|
326
370
|
children: [resolveButtonChildren(_objectSpread(_objectSpread({}, props), {}, {
|
|
327
371
|
isLoading: isLoading,
|
|
328
372
|
prominence: prominence,
|
|
@@ -334,21 +378,6 @@ var Button = /*#__PURE__*/react.forwardRef(function (_ref, ref) {
|
|
|
334
378
|
}));
|
|
335
379
|
});
|
|
336
380
|
Button.displayName = 'Button';
|
|
337
|
-
/**
|
|
338
|
-
* Prevent click events when the component is "disabled".
|
|
339
|
-
* Note: we don't want to actually disable a button element for several reasons.
|
|
340
|
-
* One being because that would prohibit the use of tooltips.
|
|
341
|
-
*/
|
|
342
|
-
|
|
343
|
-
function getPreventableClickHandler(onClick, disabled) {
|
|
344
|
-
return function handleClick(event) {
|
|
345
|
-
if (disabled) {
|
|
346
|
-
event.preventDefault();
|
|
347
|
-
} else {
|
|
348
|
-
onClick === null || onClick === void 0 ? void 0 : onClick(event);
|
|
349
|
-
}
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
381
|
|
|
353
382
|
function Loading(_ref2) {
|
|
354
383
|
var tone = _ref2.tone;
|
|
@@ -411,5 +440,6 @@ var ButtonLink = ts.forwardRefWithAs(function (_ref, ref) {
|
|
|
411
440
|
}));
|
|
412
441
|
});
|
|
413
442
|
|
|
443
|
+
exports.BaseButton = BaseButton;
|
|
414
444
|
exports.Button = Button;
|
|
415
445
|
exports.ButtonLink = ButtonLink;
|
|
@@ -4,18 +4,68 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var _objectSpread = require('@babel/runtime/helpers/objectSpread2');
|
|
6
6
|
var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties');
|
|
7
|
-
var a11y = require('@spark-web/a11y');
|
|
8
7
|
var box = require('@spark-web/box');
|
|
9
|
-
var
|
|
10
|
-
var internal = require('@spark-web/utils/internal');
|
|
8
|
+
var utils = require('@spark-web/utils');
|
|
11
9
|
var react = require('react');
|
|
12
|
-
var css = require('@emotion/css');
|
|
13
|
-
var text = require('@spark-web/text');
|
|
14
10
|
var jsxRuntime = require('react/jsx-runtime');
|
|
11
|
+
var a11y = require('@spark-web/a11y');
|
|
12
|
+
var spinner = require('@spark-web/spinner');
|
|
13
|
+
var text = require('@spark-web/text');
|
|
14
|
+
var css = require('@emotion/css');
|
|
15
15
|
var theme = require('@spark-web/theme');
|
|
16
16
|
var link = require('@spark-web/link');
|
|
17
|
+
var internal = require('@spark-web/utils/internal');
|
|
17
18
|
var ts = require('@spark-web/utils/ts');
|
|
18
19
|
|
|
20
|
+
var _excluded$2 = ["onClick", "disabled", "type"];
|
|
21
|
+
var BaseButton = /*#__PURE__*/react.forwardRef(function (_ref, forwardedRef) {
|
|
22
|
+
var onClickProp = _ref.onClick,
|
|
23
|
+
_ref$disabled = _ref.disabled,
|
|
24
|
+
disabled = _ref$disabled === void 0 ? false : _ref$disabled,
|
|
25
|
+
_ref$type = _ref.type,
|
|
26
|
+
type = _ref$type === void 0 ? 'button' : _ref$type,
|
|
27
|
+
rest = _objectWithoutProperties(_ref, _excluded$2);
|
|
28
|
+
|
|
29
|
+
var internalRef = react.useRef(null);
|
|
30
|
+
var composedRef = utils.useComposedRefs(internalRef, forwardedRef);
|
|
31
|
+
/**
|
|
32
|
+
* In Safari buttons are not focused automatically by the browser once
|
|
33
|
+
* pressed, the default behaviour is to focus the nearest focusable ancestor.
|
|
34
|
+
* To fix this we need to manually focus the button element after the user
|
|
35
|
+
* presses the element.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
var onClick = react.useCallback(function (event) {
|
|
39
|
+
var _internalRef$current;
|
|
40
|
+
|
|
41
|
+
(_internalRef$current = internalRef.current) === null || _internalRef$current === void 0 ? void 0 : _internalRef$current.focus();
|
|
42
|
+
var preventableClickHandler = getPreventableClickHandler(onClickProp, disabled);
|
|
43
|
+
preventableClickHandler(event);
|
|
44
|
+
}, [disabled, onClickProp]);
|
|
45
|
+
return /*#__PURE__*/jsxRuntime.jsx(box.Box, _objectSpread(_objectSpread({
|
|
46
|
+
as: "button"
|
|
47
|
+
}, rest), {}, {
|
|
48
|
+
onClick: onClick,
|
|
49
|
+
ref: composedRef,
|
|
50
|
+
type: type
|
|
51
|
+
}));
|
|
52
|
+
});
|
|
53
|
+
BaseButton.displayName = 'BaseButton';
|
|
54
|
+
/**
|
|
55
|
+
* handle "disabled" behaviour w/o disabling buttons
|
|
56
|
+
* @see https://axesslab.com/disabled-buttons-suck/
|
|
57
|
+
*/
|
|
58
|
+
|
|
59
|
+
function getPreventableClickHandler(onClick, disabled) {
|
|
60
|
+
return function handleClick(event) {
|
|
61
|
+
if (disabled) {
|
|
62
|
+
event.preventDefault();
|
|
63
|
+
} else {
|
|
64
|
+
onClick === null || onClick === void 0 ? void 0 : onClick(event);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
19
69
|
var variants = {
|
|
20
70
|
high: {
|
|
21
71
|
primary: {
|
|
@@ -203,10 +253,12 @@ var resolveButtonChildren = function resolveButtonChildren(_ref) {
|
|
|
203
253
|
function HiddenWhenLoading(_ref2) {
|
|
204
254
|
var children = _ref2.children,
|
|
205
255
|
isLoading = _ref2.isLoading;
|
|
206
|
-
return /*#__PURE__*/jsxRuntime.jsx(
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
256
|
+
return /*#__PURE__*/jsxRuntime.jsx(box.Box, {
|
|
257
|
+
as: "span",
|
|
258
|
+
display: "inline-flex",
|
|
259
|
+
alignItems: "center",
|
|
260
|
+
justifyContent: "center",
|
|
261
|
+
opacity: isLoading ? 0 : undefined,
|
|
210
262
|
children: children
|
|
211
263
|
});
|
|
212
264
|
}
|
|
@@ -274,13 +326,12 @@ var _excluded$1 = ["aria-controls", "aria-describedby", "aria-expanded", "data",
|
|
|
274
326
|
* Buttons are used to initialize an action, their label should express what
|
|
275
327
|
* action will occur when the user interacts with it.
|
|
276
328
|
*/
|
|
277
|
-
var Button = /*#__PURE__*/react.forwardRef(function (_ref,
|
|
329
|
+
var Button = /*#__PURE__*/react.forwardRef(function (_ref, forwardedRef) {
|
|
278
330
|
var ariaControls = _ref['aria-controls'],
|
|
279
331
|
ariaDescribedBy = _ref['aria-describedby'],
|
|
280
332
|
ariaExpanded = _ref['aria-expanded'],
|
|
281
333
|
data = _ref.data,
|
|
282
|
-
|
|
283
|
-
disabled = _ref$disabled === void 0 ? false : _ref$disabled,
|
|
334
|
+
disabled = _ref.disabled,
|
|
284
335
|
id = _ref.id,
|
|
285
336
|
_ref$loading = _ref.loading,
|
|
286
337
|
loading = _ref$loading === void 0 ? false : _ref$loading,
|
|
@@ -291,8 +342,7 @@ var Button = /*#__PURE__*/react.forwardRef(function (_ref, ref) {
|
|
|
291
342
|
size = _ref$size === void 0 ? 'medium' : _ref$size,
|
|
292
343
|
_ref$tone = _ref.tone,
|
|
293
344
|
tone = _ref$tone === void 0 ? 'primary' : _ref$tone,
|
|
294
|
-
|
|
295
|
-
type = _ref$type === void 0 ? 'button' : _ref$type,
|
|
345
|
+
type = _ref.type,
|
|
296
346
|
props = _objectWithoutProperties(_ref, _excluded$1);
|
|
297
347
|
|
|
298
348
|
var iconOnly = Boolean(props.label);
|
|
@@ -305,24 +355,18 @@ var Button = /*#__PURE__*/react.forwardRef(function (_ref, ref) {
|
|
|
305
355
|
var isDisabled = disabled || loading;
|
|
306
356
|
var isLoading = loading && !disabled;
|
|
307
357
|
var variant = variants[prominence][tone];
|
|
308
|
-
|
|
309
|
-
* handle "disabled" behaviour w/o disabling buttons
|
|
310
|
-
* @see https://axesslab.com/disabled-buttons-suck/
|
|
311
|
-
*/
|
|
312
|
-
|
|
313
|
-
var handleClick = getPreventableClickHandler(onClick, isDisabled);
|
|
314
|
-
return /*#__PURE__*/jsxRuntime.jsxs(box.Box, _objectSpread(_objectSpread(_objectSpread({
|
|
358
|
+
return /*#__PURE__*/jsxRuntime.jsxs(BaseButton, _objectSpread(_objectSpread({}, buttonStyleProps), {}, {
|
|
315
359
|
"aria-controls": ariaControls,
|
|
316
360
|
"aria-describedby": ariaDescribedBy,
|
|
317
361
|
"aria-disabled": isDisabled,
|
|
318
362
|
"aria-expanded": ariaExpanded,
|
|
319
363
|
"aria-label": props.label,
|
|
320
|
-
|
|
364
|
+
data: data,
|
|
365
|
+
disabled: isDisabled,
|
|
321
366
|
id: id,
|
|
322
|
-
onClick:
|
|
323
|
-
ref:
|
|
324
|
-
type: type
|
|
325
|
-
}, buttonStyleProps), data ? internal.buildDataAttributes(data) : undefined), {}, {
|
|
367
|
+
onClick: onClick,
|
|
368
|
+
ref: forwardedRef,
|
|
369
|
+
type: type,
|
|
326
370
|
children: [resolveButtonChildren(_objectSpread(_objectSpread({}, props), {}, {
|
|
327
371
|
isLoading: isLoading,
|
|
328
372
|
prominence: prominence,
|
|
@@ -334,21 +378,6 @@ var Button = /*#__PURE__*/react.forwardRef(function (_ref, ref) {
|
|
|
334
378
|
}));
|
|
335
379
|
});
|
|
336
380
|
Button.displayName = 'Button';
|
|
337
|
-
/**
|
|
338
|
-
* Prevent click events when the component is "disabled".
|
|
339
|
-
* Note: we don't want to actually disable a button element for several reasons.
|
|
340
|
-
* One being because that would prohibit the use of tooltips.
|
|
341
|
-
*/
|
|
342
|
-
|
|
343
|
-
function getPreventableClickHandler(onClick, disabled) {
|
|
344
|
-
return function handleClick(event) {
|
|
345
|
-
if (disabled) {
|
|
346
|
-
event.preventDefault();
|
|
347
|
-
} else {
|
|
348
|
-
onClick === null || onClick === void 0 ? void 0 : onClick(event);
|
|
349
|
-
}
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
381
|
|
|
353
382
|
function Loading(_ref2) {
|
|
354
383
|
var tone = _ref2.tone;
|
|
@@ -411,5 +440,6 @@ var ButtonLink = ts.forwardRefWithAs(function (_ref, ref) {
|
|
|
411
440
|
}));
|
|
412
441
|
});
|
|
413
442
|
|
|
443
|
+
exports.BaseButton = BaseButton;
|
|
414
444
|
exports.Button = Button;
|
|
415
445
|
exports.ButtonLink = ButtonLink;
|
|
@@ -1,17 +1,67 @@
|
|
|
1
1
|
import _objectSpread from '@babel/runtime/helpers/esm/objectSpread2';
|
|
2
2
|
import _objectWithoutProperties from '@babel/runtime/helpers/esm/objectWithoutProperties';
|
|
3
|
-
import { useFocusRing, VisuallyHidden } from '@spark-web/a11y';
|
|
4
3
|
import { Box } from '@spark-web/box';
|
|
4
|
+
import { useComposedRefs } from '@spark-web/utils';
|
|
5
|
+
import { forwardRef, useRef, useCallback, Children, isValidElement, cloneElement } from 'react';
|
|
6
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
7
|
+
import { useFocusRing, VisuallyHidden } from '@spark-web/a11y';
|
|
5
8
|
import { Spinner } from '@spark-web/spinner';
|
|
6
|
-
import { buildDataAttributes } from '@spark-web/utils/internal';
|
|
7
|
-
import { Children, isValidElement, cloneElement, forwardRef } from 'react';
|
|
8
|
-
import { css } from '@emotion/css';
|
|
9
9
|
import { Text } from '@spark-web/text';
|
|
10
|
-
import {
|
|
10
|
+
import { css } from '@emotion/css';
|
|
11
11
|
import { useTheme } from '@spark-web/theme';
|
|
12
12
|
import { useLinkComponent } from '@spark-web/link';
|
|
13
|
+
import { buildDataAttributes } from '@spark-web/utils/internal';
|
|
13
14
|
import { forwardRefWithAs } from '@spark-web/utils/ts';
|
|
14
15
|
|
|
16
|
+
var _excluded$2 = ["onClick", "disabled", "type"];
|
|
17
|
+
var BaseButton = /*#__PURE__*/forwardRef(function (_ref, forwardedRef) {
|
|
18
|
+
var onClickProp = _ref.onClick,
|
|
19
|
+
_ref$disabled = _ref.disabled,
|
|
20
|
+
disabled = _ref$disabled === void 0 ? false : _ref$disabled,
|
|
21
|
+
_ref$type = _ref.type,
|
|
22
|
+
type = _ref$type === void 0 ? 'button' : _ref$type,
|
|
23
|
+
rest = _objectWithoutProperties(_ref, _excluded$2);
|
|
24
|
+
|
|
25
|
+
var internalRef = useRef(null);
|
|
26
|
+
var composedRef = useComposedRefs(internalRef, forwardedRef);
|
|
27
|
+
/**
|
|
28
|
+
* In Safari buttons are not focused automatically by the browser once
|
|
29
|
+
* pressed, the default behaviour is to focus the nearest focusable ancestor.
|
|
30
|
+
* To fix this we need to manually focus the button element after the user
|
|
31
|
+
* presses the element.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
var onClick = useCallback(function (event) {
|
|
35
|
+
var _internalRef$current;
|
|
36
|
+
|
|
37
|
+
(_internalRef$current = internalRef.current) === null || _internalRef$current === void 0 ? void 0 : _internalRef$current.focus();
|
|
38
|
+
var preventableClickHandler = getPreventableClickHandler(onClickProp, disabled);
|
|
39
|
+
preventableClickHandler(event);
|
|
40
|
+
}, [disabled, onClickProp]);
|
|
41
|
+
return /*#__PURE__*/jsx(Box, _objectSpread(_objectSpread({
|
|
42
|
+
as: "button"
|
|
43
|
+
}, rest), {}, {
|
|
44
|
+
onClick: onClick,
|
|
45
|
+
ref: composedRef,
|
|
46
|
+
type: type
|
|
47
|
+
}));
|
|
48
|
+
});
|
|
49
|
+
BaseButton.displayName = 'BaseButton';
|
|
50
|
+
/**
|
|
51
|
+
* handle "disabled" behaviour w/o disabling buttons
|
|
52
|
+
* @see https://axesslab.com/disabled-buttons-suck/
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
function getPreventableClickHandler(onClick, disabled) {
|
|
56
|
+
return function handleClick(event) {
|
|
57
|
+
if (disabled) {
|
|
58
|
+
event.preventDefault();
|
|
59
|
+
} else {
|
|
60
|
+
onClick === null || onClick === void 0 ? void 0 : onClick(event);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
15
65
|
var variants = {
|
|
16
66
|
high: {
|
|
17
67
|
primary: {
|
|
@@ -199,10 +249,12 @@ var resolveButtonChildren = function resolveButtonChildren(_ref) {
|
|
|
199
249
|
function HiddenWhenLoading(_ref2) {
|
|
200
250
|
var children = _ref2.children,
|
|
201
251
|
isLoading = _ref2.isLoading;
|
|
202
|
-
return /*#__PURE__*/jsx(
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
252
|
+
return /*#__PURE__*/jsx(Box, {
|
|
253
|
+
as: "span",
|
|
254
|
+
display: "inline-flex",
|
|
255
|
+
alignItems: "center",
|
|
256
|
+
justifyContent: "center",
|
|
257
|
+
opacity: isLoading ? 0 : undefined,
|
|
206
258
|
children: children
|
|
207
259
|
});
|
|
208
260
|
}
|
|
@@ -270,13 +322,12 @@ var _excluded$1 = ["aria-controls", "aria-describedby", "aria-expanded", "data",
|
|
|
270
322
|
* Buttons are used to initialize an action, their label should express what
|
|
271
323
|
* action will occur when the user interacts with it.
|
|
272
324
|
*/
|
|
273
|
-
var Button = /*#__PURE__*/forwardRef(function (_ref,
|
|
325
|
+
var Button = /*#__PURE__*/forwardRef(function (_ref, forwardedRef) {
|
|
274
326
|
var ariaControls = _ref['aria-controls'],
|
|
275
327
|
ariaDescribedBy = _ref['aria-describedby'],
|
|
276
328
|
ariaExpanded = _ref['aria-expanded'],
|
|
277
329
|
data = _ref.data,
|
|
278
|
-
|
|
279
|
-
disabled = _ref$disabled === void 0 ? false : _ref$disabled,
|
|
330
|
+
disabled = _ref.disabled,
|
|
280
331
|
id = _ref.id,
|
|
281
332
|
_ref$loading = _ref.loading,
|
|
282
333
|
loading = _ref$loading === void 0 ? false : _ref$loading,
|
|
@@ -287,8 +338,7 @@ var Button = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
|
287
338
|
size = _ref$size === void 0 ? 'medium' : _ref$size,
|
|
288
339
|
_ref$tone = _ref.tone,
|
|
289
340
|
tone = _ref$tone === void 0 ? 'primary' : _ref$tone,
|
|
290
|
-
|
|
291
|
-
type = _ref$type === void 0 ? 'button' : _ref$type,
|
|
341
|
+
type = _ref.type,
|
|
292
342
|
props = _objectWithoutProperties(_ref, _excluded$1);
|
|
293
343
|
|
|
294
344
|
var iconOnly = Boolean(props.label);
|
|
@@ -301,24 +351,18 @@ var Button = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
|
301
351
|
var isDisabled = disabled || loading;
|
|
302
352
|
var isLoading = loading && !disabled;
|
|
303
353
|
var variant = variants[prominence][tone];
|
|
304
|
-
|
|
305
|
-
* handle "disabled" behaviour w/o disabling buttons
|
|
306
|
-
* @see https://axesslab.com/disabled-buttons-suck/
|
|
307
|
-
*/
|
|
308
|
-
|
|
309
|
-
var handleClick = getPreventableClickHandler(onClick, isDisabled);
|
|
310
|
-
return /*#__PURE__*/jsxs(Box, _objectSpread(_objectSpread(_objectSpread({
|
|
354
|
+
return /*#__PURE__*/jsxs(BaseButton, _objectSpread(_objectSpread({}, buttonStyleProps), {}, {
|
|
311
355
|
"aria-controls": ariaControls,
|
|
312
356
|
"aria-describedby": ariaDescribedBy,
|
|
313
357
|
"aria-disabled": isDisabled,
|
|
314
358
|
"aria-expanded": ariaExpanded,
|
|
315
359
|
"aria-label": props.label,
|
|
316
|
-
|
|
360
|
+
data: data,
|
|
361
|
+
disabled: isDisabled,
|
|
317
362
|
id: id,
|
|
318
|
-
onClick:
|
|
319
|
-
ref:
|
|
320
|
-
type: type
|
|
321
|
-
}, buttonStyleProps), data ? buildDataAttributes(data) : undefined), {}, {
|
|
363
|
+
onClick: onClick,
|
|
364
|
+
ref: forwardedRef,
|
|
365
|
+
type: type,
|
|
322
366
|
children: [resolveButtonChildren(_objectSpread(_objectSpread({}, props), {}, {
|
|
323
367
|
isLoading: isLoading,
|
|
324
368
|
prominence: prominence,
|
|
@@ -330,21 +374,6 @@ var Button = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
|
330
374
|
}));
|
|
331
375
|
});
|
|
332
376
|
Button.displayName = 'Button';
|
|
333
|
-
/**
|
|
334
|
-
* Prevent click events when the component is "disabled".
|
|
335
|
-
* Note: we don't want to actually disable a button element for several reasons.
|
|
336
|
-
* One being because that would prohibit the use of tooltips.
|
|
337
|
-
*/
|
|
338
|
-
|
|
339
|
-
function getPreventableClickHandler(onClick, disabled) {
|
|
340
|
-
return function handleClick(event) {
|
|
341
|
-
if (disabled) {
|
|
342
|
-
event.preventDefault();
|
|
343
|
-
} else {
|
|
344
|
-
onClick === null || onClick === void 0 ? void 0 : onClick(event);
|
|
345
|
-
}
|
|
346
|
-
};
|
|
347
|
-
}
|
|
348
377
|
|
|
349
378
|
function Loading(_ref2) {
|
|
350
379
|
var tone = _ref2.tone;
|
|
@@ -407,4 +436,4 @@ var ButtonLink = forwardRefWithAs(function (_ref, ref) {
|
|
|
407
436
|
}));
|
|
408
437
|
});
|
|
409
438
|
|
|
410
|
-
export { Button, ButtonLink };
|
|
439
|
+
export { BaseButton, Button, ButtonLink };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spark-web/button",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/spark-web-button.cjs.js",
|
|
6
6
|
"module": "dist/spark-web-button.esm.js",
|
|
@@ -8,16 +8,16 @@
|
|
|
8
8
|
"dist"
|
|
9
9
|
],
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@babel/runtime": "^7.
|
|
12
|
-
"@emotion/css": "^11.
|
|
13
|
-
"@spark-web/a11y": "^1.0
|
|
14
|
-
"@spark-web/box": "^1.0.
|
|
15
|
-
"@spark-web/icon": "^1.1.
|
|
16
|
-
"@spark-web/link": "^1.0.
|
|
17
|
-
"@spark-web/spinner": "^1.0.
|
|
18
|
-
"@spark-web/text": "^1.0.
|
|
19
|
-
"@spark-web/theme": "^3.0.
|
|
20
|
-
"@spark-web/utils": "^1.1.
|
|
11
|
+
"@babel/runtime": "^7.18.3",
|
|
12
|
+
"@emotion/css": "^11.9.0",
|
|
13
|
+
"@spark-web/a11y": "^1.1.0",
|
|
14
|
+
"@spark-web/box": "^1.0.6",
|
|
15
|
+
"@spark-web/icon": "^1.1.4",
|
|
16
|
+
"@spark-web/link": "^1.0.6",
|
|
17
|
+
"@spark-web/spinner": "^1.0.4",
|
|
18
|
+
"@spark-web/text": "^1.0.6",
|
|
19
|
+
"@spark-web/theme": "^3.0.2",
|
|
20
|
+
"@spark-web/utils": "^1.1.5"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@types/react": "^17.0.12",
|