@spark-web/button 1.5.2 → 1.5.4-poc-simple.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.
@@ -1,483 +0,0 @@
1
- import _objectSpread from '@babel/runtime/helpers/esm/objectSpread2';
2
- import _objectWithoutProperties from '@babel/runtime/helpers/esm/objectWithoutProperties';
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 _slicedToArray from '@babel/runtime/helpers/esm/slicedToArray';
8
- import { css } from '@emotion/css';
9
- import { useFocusRing, VisuallyHidden } from '@spark-web/a11y';
10
- import { Spinner } from '@spark-web/spinner';
11
- import { Text } from '@spark-web/text';
12
- import { useTheme } from '@spark-web/theme';
13
- import { useLinkComponent } from '@spark-web/link';
14
- import { forwardRefWithAs } from '@spark-web/utils/ts';
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
- consumerProps = _objectWithoutProperties(_ref, _excluded$2);
24
- var internalRef = useRef(null);
25
- var composedRef = useComposedRefs(internalRef, forwardedRef);
26
- /**
27
- * In Safari buttons are not focused automatically by the browser once
28
- * pressed, the default behaviour is to focus the nearest focusable ancestor.
29
- * To fix this we need to manually focus the button element after the user
30
- * presses the element.
31
- */
32
- var onClick = useCallback(function (event) {
33
- var _internalRef$current;
34
- (_internalRef$current = internalRef.current) === null || _internalRef$current === void 0 || _internalRef$current.focus();
35
- var preventableClickHandler = getPreventableClickHandler(onClickProp, disabled);
36
- preventableClickHandler(event);
37
- }, [disabled, onClickProp]);
38
- return /*#__PURE__*/jsx(Box, _objectSpread(_objectSpread({}, consumerProps), {}, {
39
- as: "button",
40
- ref: composedRef
41
- // Hide aria-disabled attribute when button is not disabled
42
- ,
43
- "aria-disabled": disabled || undefined,
44
- onClick: onClick,
45
- type: type
46
- }));
47
- });
48
- BaseButton.displayName = 'BaseButton';
49
-
50
- /**
51
- * handle "disabled" behaviour w/o disabling buttons
52
- * @see https://axesslab.com/disabled-buttons-suck/
53
- */
54
- function getPreventableClickHandler(onClick, disabled) {
55
- return function handleClick(event) {
56
- if (disabled) {
57
- event.preventDefault();
58
- } else {
59
- onClick === null || onClick === void 0 || onClick(event);
60
- }
61
- };
62
- }
63
-
64
- var highDisabledStyles = {
65
- backgroundDisabled: 'disabled',
66
- borderDisabled: 'fieldDisabled',
67
- textToneDisabled: 'neutralInverted'
68
- };
69
- var highDisabledAltStyles = {
70
- backgroundDisabled: 'neutral',
71
- borderDisabled: 'standard',
72
- textToneDisabled: 'placeholder'
73
- };
74
- var lowDisabledStyles = {
75
- backgroundDisabled: 'inputDisabled',
76
- textToneDisabled: 'disabled'
77
- };
78
- var lowDisabledAltStyles = {
79
- backgroundDisabled: 'inputDisabled',
80
- borderDisabled: 'fieldDisabled',
81
- textToneDisabled: 'disabled'
82
- };
83
- var noneDisabledStyles = {
84
- backgroundDisabled: 'neutral',
85
- textToneDisabled: 'disabled'
86
- };
87
- var variants = {
88
- high: {
89
- primary: _objectSpread({
90
- background: 'primary',
91
- backgroundHover: 'primaryHover',
92
- backgroundActive: 'primaryActive'
93
- }, highDisabledStyles),
94
- secondary: _objectSpread({
95
- background: 'secondary',
96
- backgroundHover: 'secondaryHover',
97
- backgroundActive: 'secondaryActive'
98
- }, highDisabledStyles),
99
- neutral: _objectSpread({
100
- background: 'neutral',
101
- border: 'field',
102
- backgroundHover: 'neutralHover',
103
- backgroundActive: 'neutralActive'
104
- }, highDisabledAltStyles),
105
- positive: _objectSpread({
106
- background: 'positive',
107
- backgroundHover: 'positiveHover',
108
- backgroundActive: 'positiveActive'
109
- }, highDisabledStyles),
110
- critical: _objectSpread({
111
- background: 'critical',
112
- backgroundHover: 'criticalHover',
113
- backgroundActive: 'criticalActive'
114
- }, highDisabledStyles),
115
- caution: undefined,
116
- info: undefined
117
- },
118
- low: {
119
- primary: _objectSpread({
120
- background: 'surface',
121
- border: 'primary',
122
- borderWidth: 'large',
123
- textTone: 'primary',
124
- backgroundHover: 'none',
125
- borderHover: 'primaryHover',
126
- textToneHover: 'primaryHover',
127
- backgroundActive: 'none',
128
- borderActive: 'primaryActive',
129
- textToneActive: 'primaryActive'
130
- }, lowDisabledAltStyles),
131
- secondary: _objectSpread({
132
- background: 'surface',
133
- border: 'secondary',
134
- borderWidth: 'large',
135
- textTone: 'secondary',
136
- backgroundHover: 'none',
137
- borderHover: 'secondaryHover',
138
- textToneHover: 'secondaryHover',
139
- backgroundActive: 'none',
140
- borderActive: 'secondaryActive',
141
- textToneActive: 'secondaryActive'
142
- }, lowDisabledAltStyles),
143
- neutral: _objectSpread({
144
- background: 'neutralLow',
145
- backgroundHover: 'neutralLowHover',
146
- backgroundActive: 'neutralLowActive'
147
- }, lowDisabledStyles),
148
- positive: _objectSpread({
149
- background: 'positiveLow',
150
- backgroundHover: 'positiveLowHover',
151
- backgroundActive: 'positiveLowActive'
152
- }, lowDisabledStyles),
153
- caution: _objectSpread({
154
- background: 'cautionLow',
155
- backgroundHover: 'cautionLowHover',
156
- backgroundActive: 'cautionLowActive'
157
- }, lowDisabledStyles),
158
- critical: _objectSpread({
159
- background: 'criticalLow',
160
- backgroundHover: 'criticalLowHover',
161
- backgroundActive: 'criticalLowActive'
162
- }, lowDisabledStyles),
163
- info: _objectSpread({
164
- background: 'infoLow',
165
- backgroundHover: 'infoLowHover',
166
- backgroundActive: 'infoLowActive'
167
- }, lowDisabledStyles)
168
- },
169
- none: {
170
- primary: _objectSpread({
171
- background: 'surface',
172
- textTone: 'primaryActive',
173
- backgroundHover: 'primaryLowHover',
174
- backgroundActive: 'primaryLowActive'
175
- }, noneDisabledStyles),
176
- secondary: _objectSpread({
177
- background: 'surface',
178
- textTone: 'secondaryActive',
179
- backgroundHover: 'secondaryLowHover',
180
- backgroundActive: 'secondaryLowActive'
181
- }, noneDisabledStyles),
182
- neutral: _objectSpread({
183
- background: 'surface',
184
- textTone: 'neutral',
185
- backgroundHover: 'neutralLowHover',
186
- backgroundActive: 'neutralLowActive'
187
- }, noneDisabledStyles),
188
- positive: _objectSpread({
189
- background: 'surface',
190
- textTone: 'positive',
191
- backgroundHover: 'positiveLowHover',
192
- backgroundActive: 'positiveLowActive'
193
- }, noneDisabledStyles),
194
- caution: _objectSpread({
195
- background: 'surface',
196
- textTone: 'caution',
197
- backgroundHover: 'cautionLowHover',
198
- backgroundActive: 'cautionLowActive'
199
- }, noneDisabledStyles),
200
- critical: _objectSpread({
201
- background: 'surface',
202
- textTone: 'critical',
203
- backgroundHover: 'criticalLowHover',
204
- backgroundActive: 'criticalLowActive'
205
- }, noneDisabledStyles),
206
- info: _objectSpread({
207
- background: 'surface',
208
- textTone: 'info',
209
- backgroundHover: 'infoLowHover',
210
- backgroundActive: 'infoLowActive'
211
- }, noneDisabledStyles)
212
- }
213
- };
214
- var mapTokens = {
215
- fontSize: {
216
- medium: 'small',
217
- large: 'standard'
218
- },
219
- size: {
220
- medium: 'medium',
221
- large: 'large'
222
- },
223
- spacing: {
224
- medium: 'medium',
225
- large: 'xlarge'
226
- }
227
- };
228
-
229
- var resolveButtonChildren = function resolveButtonChildren(_ref) {
230
- var children = _ref.children,
231
- isLoading = _ref.isLoading,
232
- prominence = _ref.prominence,
233
- size = _ref.size,
234
- tone = _ref.tone;
235
- var variant = variants[prominence][tone];
236
- return Children.map(children, function (child) {
237
- if (typeof child === 'string' || typeof child === 'number') {
238
- return /*#__PURE__*/jsx(HiddenWhenLoading, {
239
- isLoading: isLoading,
240
- children: /*#__PURE__*/jsx(Text, {
241
- as: "span",
242
- baseline: false,
243
- overflowStrategy: "nowrap",
244
- weight: "semibold",
245
- size: mapTokens.fontSize[size],
246
- tone: variant === null || variant === void 0 ? void 0 : variant.textTone,
247
- children: child
248
- })
249
- });
250
- }
251
- if ( /*#__PURE__*/isValidElement(child)) {
252
- return /*#__PURE__*/jsx(HiddenWhenLoading, {
253
- isLoading: isLoading,
254
- children: /*#__PURE__*/cloneElement(child, {
255
- // Dismiss buttons need to be `xxsmall`
256
- // For everything else, we force them to be `xsmall`
257
- size: child.props.size === 'xxsmall' ? child.props.size : 'xsmall',
258
- // If the button is low prominence with a decorative tone we want to force
259
- // the tone to be the same as the button
260
- // We also don't want users to override the tone of the icon inside of the button
261
- tone: variant === null || variant === void 0 ? void 0 : variant.textTone
262
- })
263
- });
264
- }
265
- return null;
266
- });
267
- };
268
- function HiddenWhenLoading(_ref2) {
269
- var children = _ref2.children,
270
- isLoading = _ref2.isLoading;
271
- return /*#__PURE__*/jsx(Box, {
272
- as: "span",
273
- display: "inline-flex",
274
- alignItems: "center",
275
- justifyContent: "center",
276
- opacity: isLoading ? 0 : undefined,
277
- children: children
278
- });
279
- }
280
-
281
- ////////////////////////////////////////////////////////////////////////////////
282
-
283
- /**
284
- * useButtonStyles
285
- *
286
- * Custom hook for styling buttons and certain links.
287
- * Returns a tuple where the first item is an object of props to spread onto the
288
- * underlying `Box` component, and the second item is a CSS object that can be
289
- * passed to Emotion's `css` function.
290
- */
291
- function useButtonStyles(_ref) {
292
- var iconOnly = _ref.iconOnly,
293
- prominence = _ref.prominence,
294
- size = _ref.size,
295
- tone = _ref.tone;
296
- var theme = useTheme();
297
- var focusRingStyles = useFocusRing({
298
- tone: tone
299
- });
300
- var disabledFocusRingStyles = useFocusRing({
301
- tone: 'disabled'
302
- });
303
- var variant = variants[prominence][tone];
304
- var isLarge = size === 'large';
305
- var transitionColors = {
306
- transitionProperty: 'color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter',
307
- transitionTimingFunction: theme.animation.standard.easing,
308
- transitionDuration: "".concat(theme.animation.standard.duration, "ms")
309
- };
310
- return [{
311
- alignItems: 'center',
312
- background: variant === null || variant === void 0 ? void 0 : variant.background,
313
- border: variant === null || variant === void 0 ? void 0 : variant.border,
314
- borderWidth: variant === null || variant === void 0 ? void 0 : variant.borderWidth,
315
- borderRadius: isLarge ? 'medium' : 'small',
316
- cursor: 'pointer',
317
- display: 'inline-flex',
318
- gap: 'small',
319
- height: mapTokens.size[size],
320
- justifyContent: 'center',
321
- paddingX: iconOnly ? undefined : mapTokens.spacing[size],
322
- position: 'relative',
323
- width: iconOnly ? mapTokens.size[size] : undefined
324
- }, _objectSpread(_objectSpread({}, transitionColors), {}, {
325
- // Styles for buttons that aren't disabled.
326
- // Using the :not() pseudo-class so we don't have to undo the styles when
327
- // the button is disabled.
328
- '&:not([aria-disabled=true])': {
329
- ':hover': {
330
- borderColor: variant !== null && variant !== void 0 && variant.borderHover ? theme.border.color[variant.borderHover] : undefined,
331
- backgroundColor: variant !== null && variant !== void 0 && variant.backgroundHover ? theme.backgroundInteractions[variant.backgroundHover] : undefined,
332
- // Style button text when hovering
333
- '> *': _objectSpread(_objectSpread({}, transitionColors), {}, {
334
- color: variant !== null && variant !== void 0 && variant.textToneHover ? theme.color.foreground[variant.textToneHover] : undefined,
335
- stroke: variant !== null && variant !== void 0 && variant.textToneHover ? theme.color.foreground[variant.textToneHover] : undefined
336
- })
337
- },
338
- ':active': {
339
- borderColor: variant !== null && variant !== void 0 && variant.borderActive ? theme.border.color[variant.borderActive] : undefined,
340
- backgroundColor: variant !== null && variant !== void 0 && variant.backgroundActive ? theme.backgroundInteractions[variant === null || variant === void 0 ? void 0 : variant.backgroundActive] : undefined,
341
- transform: 'scale(0.98)',
342
- // Style button text when it's active
343
- '> *': _objectSpread(_objectSpread({}, transitionColors), {}, {
344
- color: variant !== null && variant !== void 0 && variant.textToneActive ? theme.color.foreground[variant.textToneActive] : undefined,
345
- stroke: variant !== null && variant !== void 0 && variant.textToneActive ? theme.color.foreground[variant.textToneActive] : undefined
346
- })
347
- },
348
- ':focus': focusRingStyles
349
- },
350
- '&[aria-disabled=true]': {
351
- backgroundColor: variant !== null && variant !== void 0 && variant.backgroundDisabled ? theme.color.background[variant === null || variant === void 0 ? void 0 : variant.backgroundDisabled] : undefined,
352
- borderColor: variant !== null && variant !== void 0 && variant.borderDisabled ? theme.border.color[variant.borderDisabled] : undefined,
353
- cursor: 'default',
354
- '*': {
355
- color: variant !== null && variant !== void 0 && variant.textToneDisabled ? theme.color.foreground[variant.textToneDisabled] : undefined,
356
- stroke: variant !== null && variant !== void 0 && variant.textToneDisabled ? theme.color.foreground[variant.textToneDisabled] : undefined
357
- },
358
- ':focus': disabledFocusRingStyles
359
- }
360
- })];
361
- }
362
-
363
- var _excluded$1 = ["aria-controls", "aria-describedby", "aria-expanded", "data", "disabled", "id", "loading", "onClick", "prominence", "size", "tone", "type"];
364
- /**
365
- * Buttons are used to initialize an action, their label should express what
366
- * action will occur when the user interacts with it.
367
- */
368
- var Button = /*#__PURE__*/forwardRef(function (_ref, forwardedRef) {
369
- var ariaControls = _ref['aria-controls'],
370
- ariaDescribedBy = _ref['aria-describedby'],
371
- ariaExpanded = _ref['aria-expanded'],
372
- data = _ref.data,
373
- disabled = _ref.disabled,
374
- id = _ref.id,
375
- _ref$loading = _ref.loading,
376
- loading = _ref$loading === void 0 ? false : _ref$loading,
377
- onClick = _ref.onClick,
378
- _ref$prominence = _ref.prominence,
379
- prominence = _ref$prominence === void 0 ? 'high' : _ref$prominence,
380
- _ref$size = _ref.size,
381
- size = _ref$size === void 0 ? 'medium' : _ref$size,
382
- _ref$tone = _ref.tone,
383
- tone = _ref$tone === void 0 ? 'primary' : _ref$tone,
384
- type = _ref.type,
385
- props = _objectWithoutProperties(_ref, _excluded$1);
386
- var iconOnly = Boolean(props.label);
387
- var _useButtonStyles = useButtonStyles({
388
- iconOnly: iconOnly,
389
- size: size,
390
- tone: tone,
391
- prominence: prominence
392
- }),
393
- _useButtonStyles2 = _slicedToArray(_useButtonStyles, 2),
394
- boxProps = _useButtonStyles2[0],
395
- buttonStyles = _useButtonStyles2[1];
396
- var variant = variants[prominence][tone];
397
- return /*#__PURE__*/jsxs(BaseButton, _objectSpread(_objectSpread({}, boxProps), {}, {
398
- "aria-controls": ariaControls,
399
- "aria-describedby": ariaDescribedBy,
400
- "aria-expanded": ariaExpanded,
401
- "aria-label": props.label,
402
- className: css(buttonStyles),
403
- data: data,
404
- disabled: loading || disabled,
405
- id: id,
406
- onClick: onClick,
407
- ref: forwardedRef,
408
- type: type,
409
- children: [resolveButtonChildren(_objectSpread(_objectSpread({}, props), {}, {
410
- isLoading: loading,
411
- prominence: prominence,
412
- size: size,
413
- tone: tone
414
- })), loading && /*#__PURE__*/jsx(Loading, {
415
- tone: variant === null || variant === void 0 ? void 0 : variant.textTone
416
- })]
417
- }));
418
- });
419
- Button.displayName = 'Button';
420
- function Loading(_ref2) {
421
- var tone = _ref2.tone;
422
- return /*#__PURE__*/jsxs(Box, {
423
- as: "span",
424
- position: "absolute",
425
- top: 0,
426
- bottom: 0,
427
- left: 0,
428
- right: 0,
429
- display: "flex",
430
- alignItems: "center",
431
- justifyContent: "center",
432
- children: [/*#__PURE__*/jsx(VisuallyHidden, {
433
- children: "button loading indicator"
434
- }), /*#__PURE__*/jsx(Spinner, {
435
- size: "xsmall",
436
- tone: tone
437
- })]
438
- });
439
- }
440
-
441
- var _excluded = ["data", "href", "id", "prominence", "size", "tone"];
442
- /** The appearance of a `Button`, with the semantics of a link. */
443
- var ButtonLink = forwardRefWithAs(function (_ref, forwardedRef) {
444
- var data = _ref.data,
445
- href = _ref.href,
446
- id = _ref.id,
447
- _ref$prominence = _ref.prominence,
448
- prominence = _ref$prominence === void 0 ? 'high' : _ref$prominence,
449
- _ref$size = _ref.size,
450
- size = _ref$size === void 0 ? 'medium' : _ref$size,
451
- _ref$tone = _ref.tone,
452
- tone = _ref$tone === void 0 ? 'primary' : _ref$tone,
453
- consumerProps = _objectWithoutProperties(_ref, _excluded);
454
- var LinkComponent = useLinkComponent(forwardedRef);
455
- var iconOnly = Boolean(consumerProps.label);
456
- var _useButtonStyles = useButtonStyles({
457
- iconOnly: iconOnly,
458
- prominence: prominence,
459
- size: size,
460
- tone: tone
461
- }),
462
- _useButtonStyles2 = _slicedToArray(_useButtonStyles, 2),
463
- boxProps = _useButtonStyles2[0],
464
- buttonStyles = _useButtonStyles2[1];
465
- return /*#__PURE__*/jsx(Box, _objectSpread(_objectSpread({}, boxProps), {}, {
466
- "aria-label": consumerProps.label,
467
- as: LinkComponent,
468
- asElement: "a",
469
- className: css(buttonStyles),
470
- data: data,
471
- href: href,
472
- id: id,
473
- ref: forwardedRef,
474
- children: resolveButtonChildren(_objectSpread(_objectSpread({}, consumerProps), {}, {
475
- isLoading: false,
476
- prominence: prominence,
477
- size: size,
478
- tone: tone
479
- }))
480
- }));
481
- });
482
-
483
- export { BaseButton, Button, ButtonLink, useButtonStyles };