@spaced-out/ui-design-system 0.1.119 → 0.1.121

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/CHANGELOG.md CHANGED
@@ -2,6 +2,21 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [0.1.121](https://github.com/spaced-out/ui-design-system/compare/v0.1.120...v0.1.121) (2024-08-20)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * 👻 added ghost buttons for range slider instead of clickable buttons ([ddff85a](https://github.com/spaced-out/ui-design-system/commit/ddff85a2202363132a530f8ed288279d182d1d2b))
11
+ * accessibility fixes for range slider ([67d4f94](https://github.com/spaced-out/ui-design-system/commit/67d4f9450e687a46162c1c3a8fa8c6ee7c8e5115))
12
+
13
+ ### [0.1.120](https://github.com/spaced-out/ui-design-system/compare/v0.1.119...v0.1.120) (2024-08-19)
14
+
15
+
16
+ ### Features
17
+
18
+ * 🛝 new range slider component ([#254](https://github.com/spaced-out/ui-design-system/issues/254)) ([5631aa3](https://github.com/spaced-out/ui-design-system/commit/5631aa30bc9794e4400b0b88938dc2700a94939d))
19
+
5
20
  ### [0.1.119](https://github.com/spaced-out/ui-design-system/compare/v0.1.118...v0.1.119) (2024-08-16)
6
21
 
7
22
 
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.UnstyledButton = exports.Button = exports.BUTTON_TYPES = exports.BUTTON_ACTION_TYPE = void 0;
6
+ exports.UnstyledButton = exports.Button = exports.BUTTON_TYPES = exports.BUTTON_SIZE = exports.BUTTON_ACTION_TYPE = void 0;
7
7
  var React = _interopRequireWildcard(require("react"));
8
8
  var _classify = require("../../utils/classify");
9
9
  var _CircularLoader = require("../CircularLoader");
@@ -38,6 +38,11 @@ const BUTTON_ACTION_TYPE = Object.freeze({
38
38
  reset: 'reset'
39
39
  });
40
40
  exports.BUTTON_ACTION_TYPE = BUTTON_ACTION_TYPE;
41
+ const BUTTON_SIZE = Object.freeze({
42
+ small: 'small',
43
+ medium: 'medium'
44
+ });
45
+ exports.BUTTON_SIZE = BUTTON_SIZE;
41
46
  const ButtonTypeToIconColorMap = {
42
47
  primary: 'inversePrimary',
43
48
  secondary: 'clickable',
@@ -37,8 +37,14 @@ export const BUTTON_ACTION_TYPE = Object.freeze({
37
37
  reset: 'reset',
38
38
  });
39
39
 
40
+ export const BUTTON_SIZE = Object.freeze({
41
+ small: 'small',
42
+ medium: 'medium',
43
+ });
44
+
40
45
  export type ButtonType = $Values<typeof BUTTON_TYPES>;
41
46
  export type ButtonActionType = $Values<typeof BUTTON_ACTION_TYPE>;
47
+ export type ButtonSize = $Keys<typeof BUTTON_SIZE>;
42
48
 
43
49
  export type BaseButtonProps = {
44
50
  children?: React.Node,
@@ -66,7 +72,7 @@ export type ButtonProps = {
66
72
  iconRightType?: IconType,
67
73
  type?: ButtonType,
68
74
  isFluid?: boolean,
69
- size?: 'medium' | 'small',
75
+ size?: ButtonSize,
70
76
  ...
71
77
  };
72
78
 
@@ -9,6 +9,12 @@ Object.defineProperty(exports, "BUTTON_ACTION_TYPE", {
9
9
  return _Button.BUTTON_ACTION_TYPE;
10
10
  }
11
11
  });
12
+ Object.defineProperty(exports, "BUTTON_SIZE", {
13
+ enumerable: true,
14
+ get: function () {
15
+ return _Button.BUTTON_SIZE;
16
+ }
17
+ });
12
18
  Object.defineProperty(exports, "BUTTON_TYPES", {
13
19
  enumerable: true,
14
20
  get: function () {
@@ -3,12 +3,14 @@
3
3
  export type {
4
4
  ButtonActionType,
5
5
  ButtonProps,
6
+ ButtonSize,
6
7
  ButtonType,
7
8
  UnstyledButtonProps,
8
9
  } from './Button';
9
10
  export {
10
11
  Button,
11
12
  BUTTON_ACTION_TYPE,
13
+ BUTTON_SIZE,
12
14
  BUTTON_TYPES,
13
15
  UnstyledButton,
14
16
  } from './Button';
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.RangeSlider = void 0;
7
+ var React = _interopRequireWildcard(require("react"));
8
+ var _color = require("../../styles/variables/_color");
9
+ var _classify = _interopRequireDefault(require("../../utils/classify"));
10
+ var _Button = require("../Button");
11
+ var _RangeSliderModule = _interopRequireDefault(require("./RangeSlider.module.css"));
12
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
14
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
15
+ function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
16
+ const RangeSlider = /*#__PURE__*/React.forwardRef((_ref, ref) => {
17
+ let {
18
+ classNames,
19
+ disabled,
20
+ min = 0,
21
+ max = 100,
22
+ step = 1,
23
+ value = min,
24
+ onChange,
25
+ showTicks,
26
+ iconLeftName = 'minus',
27
+ btnLeftSize = _Button.BUTTON_SIZE.small,
28
+ iconRightName = 'plus',
29
+ btnRightSize = _Button.BUTTON_SIZE.small,
30
+ hideLeftBtn,
31
+ hideRightBtn,
32
+ ariaLabel = 'Slider',
33
+ ...restInputProps
34
+ } = _ref;
35
+ const progress = (value - min) / (max - min) * 100;
36
+ const btnLeftDisabled = disabled || value <= min;
37
+ const btnRightDisabled = disabled || value >= max;
38
+ const progressColor = disabled ? _color.colorTextDisabled : _color.colorFillPrimary;
39
+ const handleChange = e => {
40
+ emitRoundedValue(e.currentTarget.value);
41
+ };
42
+ const emitRoundedValue = value => {
43
+ const newValue = parseFloat(value);
44
+ const roundedValue = Math.round(newValue * 100) / 100; // Rounds to two decimal places
45
+ onChange?.(roundedValue);
46
+ };
47
+ return /*#__PURE__*/React.createElement("div", {
48
+ ref: ref,
49
+ "data-testid": "RangeSlider",
50
+ className: (0, _classify.default)(_RangeSliderModule.default.wrapper, {
51
+ [_RangeSliderModule.default.disabled]: disabled
52
+ }, classNames?.wrapper)
53
+ }, !hideLeftBtn && /*#__PURE__*/React.createElement(_Button.Button, {
54
+ type: "ghost",
55
+ iconLeftName: iconLeftName,
56
+ size: btnLeftSize,
57
+ ariaLabel: "Decrease Value",
58
+ disabled: btnLeftDisabled,
59
+ onClick: () => emitRoundedValue(value - step)
60
+ }), /*#__PURE__*/React.createElement("div", {
61
+ className: _RangeSliderModule.default.sliderContainer
62
+ }, /*#__PURE__*/React.createElement("input", _extends({}, restInputProps, {
63
+ type: "range",
64
+ min: min,
65
+ max: max,
66
+ step: step,
67
+ value: value,
68
+ onChange: handleChange,
69
+ className: _RangeSliderModule.default.slider,
70
+ list: showTicks ? 'ticks' : undefined,
71
+ disabled: disabled,
72
+ "aria-label": ariaLabel,
73
+ style: {
74
+ background: `linear-gradient(to right, ${progressColor} ${progress}%, ${_color.colorGrayLightest} ${progress}%)`
75
+ }
76
+ })), showTicks && step > 0 && /*#__PURE__*/React.createElement("datalist", {
77
+ id: "ticks",
78
+ className: _RangeSliderModule.default.sliderTicks
79
+ }, Array.from({
80
+ length: (max - min) / step + 1
81
+ }, (_, index) => /*#__PURE__*/React.createElement("option", {
82
+ key: index,
83
+ value: min + index * step
84
+ })))), !hideRightBtn && /*#__PURE__*/React.createElement(_Button.Button, {
85
+ type: "ghost",
86
+ iconRightName: iconRightName,
87
+ size: btnRightSize,
88
+ ariaLabel: "Increase Value",
89
+ disabled: btnRightDisabled,
90
+ onClick: () => emitRoundedValue(value + step)
91
+ }));
92
+ });
93
+ exports.RangeSlider = RangeSlider;
@@ -0,0 +1,144 @@
1
+ // @flow strict
2
+
3
+ import * as React from 'react';
4
+
5
+ import {
6
+ colorFillPrimary,
7
+ colorGrayLightest,
8
+ colorTextDisabled,
9
+ } from '../../styles/variables/_color';
10
+ import classify from '../../utils/classify';
11
+ import type {ButtonSize} from '../Button';
12
+ import {Button, BUTTON_SIZE} from '../Button';
13
+
14
+ import css from './RangeSlider.module.css';
15
+
16
+
17
+ type ClassNames = $ReadOnly<{wrapper?: string}>;
18
+
19
+ export type RangeSliderProps = {
20
+ min?: number,
21
+ max?: number,
22
+ step?: number,
23
+ value?: number,
24
+ onChange?: (value: number) => void, // We don't want to send in the event because the icon buttons also modify the value
25
+ showTicks?: boolean,
26
+ iconLeftName?: string,
27
+ btnLeftSize?: ButtonSize,
28
+ iconRightName?: string,
29
+ btnRightSize?: ButtonSize,
30
+ disabled?: boolean,
31
+ hideLeftBtn?: boolean,
32
+ hideRightBtn?: boolean,
33
+ classNames?: ClassNames,
34
+ ariaLabel?: string,
35
+ ...
36
+ };
37
+
38
+ export const RangeSlider: React$AbstractComponent<
39
+ RangeSliderProps,
40
+ HTMLDivElement,
41
+ > = React.forwardRef<RangeSliderProps, HTMLDivElement>(
42
+ (
43
+ {
44
+ classNames,
45
+ disabled,
46
+ min = 0,
47
+ max = 100,
48
+ step = 1,
49
+ value = min,
50
+ onChange,
51
+ showTicks,
52
+ iconLeftName = 'minus',
53
+ btnLeftSize = BUTTON_SIZE.small,
54
+ iconRightName = 'plus',
55
+ btnRightSize = BUTTON_SIZE.small,
56
+ hideLeftBtn,
57
+ hideRightBtn,
58
+ ariaLabel = 'Slider',
59
+ ...restInputProps
60
+ }: RangeSliderProps,
61
+ ref,
62
+ ) => {
63
+ const progress = ((value - min) / (max - min)) * 100;
64
+
65
+ const btnLeftDisabled = disabled || value <= min;
66
+ const btnRightDisabled = disabled || value >= max;
67
+
68
+ const progressColor = disabled ? colorTextDisabled : colorFillPrimary;
69
+
70
+ const handleChange = (e: SyntheticEvent<HTMLInputElement>) => {
71
+ emitRoundedValue(e.currentTarget.value);
72
+ };
73
+
74
+ const emitRoundedValue = (value: number | string) => {
75
+ const newValue = parseFloat(value);
76
+ const roundedValue = Math.round(newValue * 100) / 100; // Rounds to two decimal places
77
+ onChange?.(roundedValue);
78
+ };
79
+
80
+ return (
81
+ <div
82
+ ref={ref}
83
+ data-testid="RangeSlider"
84
+ className={classify(
85
+ css.wrapper,
86
+ {[css.disabled]: disabled},
87
+ classNames?.wrapper,
88
+ )}
89
+ >
90
+ {!hideLeftBtn && (
91
+ <Button
92
+ type="ghost"
93
+ iconLeftName={iconLeftName}
94
+ size={btnLeftSize}
95
+ ariaLabel="Decrease Value"
96
+ disabled={btnLeftDisabled}
97
+ onClick={() => emitRoundedValue(value - step)}
98
+ />
99
+ )}
100
+
101
+ <div className={css.sliderContainer}>
102
+ <input
103
+ {...restInputProps}
104
+ type="range"
105
+ min={min}
106
+ max={max}
107
+ step={step}
108
+ value={value}
109
+ onChange={handleChange}
110
+ className={css.slider}
111
+ list={showTicks ? 'ticks' : undefined}
112
+ disabled={disabled}
113
+ aria-label={ariaLabel}
114
+ style={{
115
+ background: `linear-gradient(to right, ${progressColor} ${progress}%, ${colorGrayLightest} ${progress}%)`,
116
+ }}
117
+ />
118
+ {showTicks && step > 0 && (
119
+ <datalist id="ticks" className={css.sliderTicks}>
120
+ {/*
121
+ Note(Nishant): Currently, ticks are shown based on the step value.
122
+ This can be easily extended in the future to support custom tick intervals
123
+ by allowing user-defined brackets or ranges for tick marks.
124
+ */}
125
+ {Array.from({length: (max - min) / step + 1}, (_, index) => (
126
+ <option key={index} value={min + index * step} />
127
+ ))}
128
+ </datalist>
129
+ )}
130
+ </div>
131
+ {!hideRightBtn && (
132
+ <Button
133
+ type="ghost"
134
+ iconRightName={iconRightName}
135
+ size={btnRightSize}
136
+ ariaLabel="Increase Value"
137
+ disabled={btnRightDisabled}
138
+ onClick={() => emitRoundedValue(value + step)}
139
+ />
140
+ )}
141
+ </div>
142
+ );
143
+ },
144
+ );
@@ -0,0 +1,121 @@
1
+ @value (colorFillPrimary, colorGrayLightest, colorBackgroundTertiary, colorFocusPrimary, colorTextDisabled) from '../../styles/variables/_color.css';
2
+ @value (sizeFluid, size4, size20, size2) from '../../styles/variables/_size.css';
3
+ @value (spaceXSmall, spaceXXSmall, spaceNone) from '../../styles/variables/_space.css';
4
+ @value (borderRadiusLarge, borderRadiusCircle, borderWidthTertiary, borderWidthNone) from '../../styles/variables/_border.css';
5
+
6
+ @value thumbSize: size20;
7
+ @value tickSize: size2;
8
+
9
+ .wrapper {
10
+ display: flex;
11
+ align-items: center;
12
+ width: sizeFluid;
13
+ gap: calc(spaceXSmall * 2);
14
+ }
15
+
16
+ .sliderContainer {
17
+ display: flex;
18
+ flex-flow: column;
19
+ align-items: center;
20
+ position: relative;
21
+ width: sizeFluid;
22
+ }
23
+
24
+ .slider {
25
+ display: flex;
26
+ align-items: center;
27
+ -webkit-appearance: none;
28
+ appearance: none;
29
+ width: sizeFluid;
30
+ height: size4;
31
+ background-color: colorGrayLightest;
32
+ border-radius: borderRadiusLarge;
33
+ outline: none;
34
+ cursor: pointer;
35
+ }
36
+
37
+ .slider::-webkit-slider-thumb {
38
+ -webkit-appearance: none;
39
+ appearance: none;
40
+ width: thumbSize;
41
+ height: thumbSize;
42
+ border-radius: borderRadiusCircle;
43
+ background: colorFillPrimary;
44
+ cursor: progress;
45
+ border: borderWidthTertiary solid colorBackgroundTertiary;
46
+ cursor: move; /* fallback if grab cursor is unsupported */
47
+ cursor: grab;
48
+ cursor: -webkit-grab;
49
+ }
50
+
51
+ .slider:active::-webkit-slider-thumb {
52
+ cursor: grabbing;
53
+ cursor: -webkit-grabbing;
54
+ }
55
+
56
+ .disabled .slider::-webkit-slider-thumb {
57
+ background: colorTextDisabled; /* Disabled thumb color */
58
+ cursor: not-allowed;
59
+ }
60
+
61
+ .slider::-moz-range-thumb {
62
+ width: thumbSize;
63
+ height: thumbSize;
64
+ border-radius: borderRadiusCircle;
65
+ background: colorFillPrimary;
66
+ cursor: progress;
67
+ border: borderWidthTertiary solid colorBackgroundTertiary;
68
+ cursor: move; /* fallback if grab cursor is unsupported */
69
+ cursor: grab;
70
+ cursor: -moz-grab;
71
+ }
72
+
73
+ .slider:active::-moz-range-thumb {
74
+ cursor: grabbing;
75
+ cursor: -moz-grabbing;
76
+ }
77
+
78
+ .disabled .slider::-moz-range-thumb {
79
+ background: colorTextDisabled; /* Disabled thumb color */
80
+ cursor: not-allowed;
81
+ }
82
+
83
+ /***** Focus Styles *****/
84
+ /* Removes default focus */
85
+ input[type='range']:focus {
86
+ outline: none;
87
+ }
88
+
89
+ input[type='range']:focus::-webkit-slider-thumb {
90
+ box-shadow: borderWidthNone borderWidthNone borderWidthNone
91
+ borderWidthTertiary colorFocusPrimary;
92
+ }
93
+
94
+ input[type='range']:focus::-moz-range-thumb {
95
+ box-shadow: borderWidthNone borderWidthNone borderWidthNone
96
+ borderWidthTertiary colorFocusPrimary;
97
+ }
98
+
99
+ .sliderTicks {
100
+ display: flex;
101
+ position: absolute;
102
+ top: calc(spaceXXSmall / 4);
103
+ width: sizeFluid;
104
+ justify-content: space-between;
105
+ pointer-events: none; /* Prevent ticks from interfering with slider interaction */
106
+ padding: spaceNone calc(thumbSize / 2); /* Half of thumb size */
107
+ }
108
+
109
+ .sliderTicks option {
110
+ display: flex;
111
+ background-color: colorFillPrimary;
112
+ width: tickSize;
113
+ height: tickSize;
114
+ border-radius: borderRadiusLarge;
115
+ display: flex;
116
+ padding-block-start: spaceNone;
117
+ padding-block-end: spaceNone;
118
+ min-block-size: tickSize;
119
+ padding-inline: spaceNone;
120
+ white-space: nowrap;
121
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ var _RangeSlider = require("./RangeSlider");
7
+ Object.keys(_RangeSlider).forEach(function (key) {
8
+ if (key === "default" || key === "__esModule") return;
9
+ if (key in exports && exports[key] === _RangeSlider[key]) return;
10
+ Object.defineProperty(exports, key, {
11
+ enumerable: true,
12
+ get: function () {
13
+ return _RangeSlider[key];
14
+ }
15
+ });
16
+ });
@@ -0,0 +1,3 @@
1
+ // @flow strict
2
+
3
+ export * from './RangeSlider';
@@ -454,6 +454,17 @@ Object.keys(_RadioButton).forEach(function (key) {
454
454
  }
455
455
  });
456
456
  });
457
+ var _RangeSlider = require("./RangeSlider");
458
+ Object.keys(_RangeSlider).forEach(function (key) {
459
+ if (key === "default" || key === "__esModule") return;
460
+ if (key in exports && exports[key] === _RangeSlider[key]) return;
461
+ Object.defineProperty(exports, key, {
462
+ enumerable: true,
463
+ get: function () {
464
+ return _RangeSlider[key];
465
+ }
466
+ });
467
+ });
457
468
  var _SearchInput = require("./SearchInput");
458
469
  Object.keys(_SearchInput).forEach(function (key) {
459
470
  if (key === "default" || key === "__esModule") return;
@@ -41,6 +41,7 @@ export * from './Pagination';
41
41
  export * from './Panel';
42
42
  export * from './ProgressDonut';
43
43
  export * from './RadioButton';
44
+ export * from './RangeSlider';
44
45
  export * from './SearchInput';
45
46
  export * from './Shimmer';
46
47
  export * from './SideMenuLink';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spaced-out/ui-design-system",
3
- "version": "0.1.119",
3
+ "version": "0.1.121",
4
4
  "main": "index.js",
5
5
  "description": "Sense UI components library",
6
6
  "author": {