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

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,14 @@
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.122](https://github.com/spaced-out/ui-design-system/compare/v0.1.121...v0.1.122) (2024-08-22)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * ↕️ added option to hide spinner for number input, exposes wrapper classname for input ([05267ee](https://github.com/spaced-out/ui-design-system/commit/05267eeef9dd984d5e6d6030f778ed197d518cf0))
11
+ * 🛝 slider enhancements to add value input in the right slot, min max range indicators as config ([eecd31a](https://github.com/spaced-out/ui-design-system/commit/eecd31ae53dd460f08d7c31ea648d0aa20d3ca1d))
12
+
5
13
  ### [0.1.121](https://github.com/spaced-out/ui-design-system/compare/v0.1.120...v0.1.121) (2024-08-20)
6
14
 
7
15
 
@@ -59,6 +59,7 @@ const Input_ = (props, ref) => {
59
59
  boxRef,
60
60
  onKeyDown,
61
61
  disallowExponents,
62
+ hideNumberSpinner,
62
63
  ...inputProps
63
64
  } = props;
64
65
  const [showPassword, setShowPassword] = React.useState(false);
@@ -84,7 +85,7 @@ const Input_ = (props, ref) => {
84
85
  className: (0, _classify.classify)(_InputModule.default.wrapper, {
85
86
  [_InputModule.default.filled]: controlledInputFilled ?? false,
86
87
  [_InputModule.default.withError]: error ?? false
87
- })
88
+ }, classNames?.wrapper)
88
89
  }, Boolean(label) && /*#__PURE__*/React.createElement("div", {
89
90
  className: _InputModule.default.info
90
91
  }, /*#__PURE__*/React.createElement("div", {
@@ -99,7 +100,8 @@ const Input_ = (props, ref) => {
99
100
  [_InputModule.default.medium]: size === 'medium',
100
101
  [_InputModule.default.small]: size === 'small',
101
102
  [_InputModule.default.locked]: locked,
102
- [_InputModule.default.color]: type === 'color'
103
+ [_InputModule.default.color]: type === 'color',
104
+ [_InputModule.default.hideNumberSpinner]: hideNumberSpinner
103
105
  }, classNames?.box),
104
106
  onClick: !(disabled || locked) ? onContainerClick : null,
105
107
  ref: boxRef
@@ -13,6 +13,7 @@ type ClassNames = $ReadOnly<{
13
13
  box?: string,
14
14
  iconLeft?: string,
15
15
  iconRight?: string,
16
+ wrapper?: string,
16
17
  }>;
17
18
 
18
19
  export const EXPONENT_CHARACTER_LIST = ['E', 'e'];
@@ -80,6 +81,7 @@ export type InputProps = {
80
81
  * Only values which are equal to the basis for stepping (min if specified, value otherwise, and an
81
82
  * appropriate default value if neither of those is provided) are valid. */
82
83
  step?: string,
84
+ hideNumberSpinner?: boolean,
83
85
  ...
84
86
  };
85
87
 
@@ -111,6 +113,7 @@ const Input_ = (props: InputProps, ref): React.Node => {
111
113
  boxRef,
112
114
  onKeyDown,
113
115
  disallowExponents,
116
+ hideNumberSpinner,
114
117
  ...inputProps
115
118
  } = props;
116
119
 
@@ -142,10 +145,14 @@ const Input_ = (props: InputProps, ref): React.Node => {
142
145
 
143
146
  return (
144
147
  <div
145
- className={classify(css.wrapper, {
146
- [css.filled]: controlledInputFilled ?? false,
147
- [css.withError]: error ?? false,
148
- })}
148
+ className={classify(
149
+ css.wrapper,
150
+ {
151
+ [css.filled]: controlledInputFilled ?? false,
152
+ [css.withError]: error ?? false,
153
+ },
154
+ classNames?.wrapper,
155
+ )}
149
156
  >
150
157
  {Boolean(label) && (
151
158
  <div className={css.info}>
@@ -165,6 +172,7 @@ const Input_ = (props: InputProps, ref): React.Node => {
165
172
  [css.small]: size === 'small',
166
173
  [css.locked]: locked,
167
174
  [css.color]: type === 'color',
175
+ [css.hideNumberSpinner]: hideNumberSpinner,
168
176
  },
169
177
  classNames?.box,
170
178
  )}
@@ -172,3 +172,15 @@ input::placeholder {
172
172
  min-height: size18;
173
173
  border-radius: borderRadiusXSmall;
174
174
  }
175
+
176
+ .hideNumberSpinner input[type='number']::-webkit-outer-spin-button,
177
+ .hideNumberSpinner input[type='number']::-webkit-inner-spin-button {
178
+ -webkit-appearance: none;
179
+ margin: 0;
180
+ }
181
+
182
+ /* Hide spinner in Firefox */
183
+ .hideNumberSpinner input[type='number'] {
184
+ appearance: textfield;
185
+ -moz-appearance: textfield;
186
+ }
@@ -8,6 +8,8 @@ var React = _interopRequireWildcard(require("react"));
8
8
  var _color = require("../../styles/variables/_color");
9
9
  var _classify = _interopRequireDefault(require("../../utils/classify"));
10
10
  var _Button = require("../Button");
11
+ var _Input = require("../Input");
12
+ var _Text = require("../Text");
11
13
  var _RangeSliderModule = _interopRequireDefault(require("./RangeSlider.module.css"));
12
14
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
15
  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); }
@@ -30,12 +32,29 @@ const RangeSlider = /*#__PURE__*/React.forwardRef((_ref, ref) => {
30
32
  hideLeftBtn,
31
33
  hideRightBtn,
32
34
  ariaLabel = 'Slider',
35
+ showRange,
36
+ hideValueInput,
33
37
  ...restInputProps
34
38
  } = _ref;
35
39
  const progress = (value - min) / (max - min) * 100;
36
40
  const btnLeftDisabled = disabled || value <= min;
37
41
  const btnRightDisabled = disabled || value >= max;
38
42
  const progressColor = disabled ? _color.colorTextDisabled : _color.colorFillPrimary;
43
+ const handleInputChange = e => {
44
+ let inputValue = parseFloat(e.currentTarget.value);
45
+
46
+ // Validate and adjust the value
47
+ if (isNaN(inputValue) || inputValue < min) {
48
+ inputValue = min;
49
+ } else if (inputValue > max) {
50
+ inputValue = max;
51
+ } else if (step > 0) {
52
+ const nearestStep = Math.round(inputValue / step) * step;
53
+ inputValue = Math.round(nearestStep * 100) / 100; // Adjust to nearest valid step
54
+ }
55
+
56
+ onChange?.(inputValue);
57
+ };
39
58
  const handleChange = e => {
40
59
  emitRoundedValue(e.currentTarget.value);
41
60
  };
@@ -50,14 +69,17 @@ const RangeSlider = /*#__PURE__*/React.forwardRef((_ref, ref) => {
50
69
  className: (0, _classify.default)(_RangeSliderModule.default.wrapper, {
51
70
  [_RangeSliderModule.default.disabled]: disabled
52
71
  }, classNames?.wrapper)
53
- }, !hideLeftBtn && /*#__PURE__*/React.createElement(_Button.Button, {
72
+ }, !hideLeftBtn && !showRange && /*#__PURE__*/React.createElement(_Button.Button, {
54
73
  type: "ghost",
55
74
  iconLeftName: iconLeftName,
56
75
  size: btnLeftSize,
57
76
  ariaLabel: "Decrease Value",
58
77
  disabled: btnLeftDisabled,
59
78
  onClick: () => emitRoundedValue(value - step)
60
- }), /*#__PURE__*/React.createElement("div", {
79
+ }), showRange && /*#__PURE__*/React.createElement(_Text.BodySmall, {
80
+ className: _RangeSliderModule.default.rangeText,
81
+ color: disabled ? 'disabled' : 'primary'
82
+ }, min), /*#__PURE__*/React.createElement("div", {
61
83
  className: _RangeSliderModule.default.sliderContainer
62
84
  }, /*#__PURE__*/React.createElement("input", _extends({}, restInputProps, {
63
85
  type: "range",
@@ -80,14 +102,31 @@ const RangeSlider = /*#__PURE__*/React.forwardRef((_ref, ref) => {
80
102
  length: (max - min) / step + 1
81
103
  }, (_, index) => /*#__PURE__*/React.createElement("option", {
82
104
  key: index,
83
- value: min + index * step
84
- })))), !hideRightBtn && /*#__PURE__*/React.createElement(_Button.Button, {
105
+ value: min + index * step,
106
+ className: (0, _classify.default)({
107
+ [_RangeSliderModule.default.disabled]: disabled
108
+ })
109
+ })))), showRange && /*#__PURE__*/React.createElement(_Text.BodySmall, {
110
+ className: _RangeSliderModule.default.rangeText,
111
+ color: disabled ? 'disabled' : 'primary'
112
+ }, max), !hideRightBtn && !showRange && /*#__PURE__*/React.createElement(_Button.Button, {
85
113
  type: "ghost",
86
114
  iconRightName: iconRightName,
87
115
  size: btnRightSize,
88
116
  ariaLabel: "Increase Value",
89
117
  disabled: btnRightDisabled,
90
118
  onClick: () => emitRoundedValue(value + step)
119
+ }), !hideValueInput && /*#__PURE__*/React.createElement(_Input.Input, {
120
+ size: "small",
121
+ type: "number",
122
+ value: String(value),
123
+ classNames: {
124
+ wrapper: _RangeSliderModule.default.valueInputWrapper
125
+ },
126
+ disabled: disabled,
127
+ onChange: handleInputChange,
128
+ disallowExponents: true,
129
+ hideNumberSpinner: true
91
130
  }));
92
131
  });
93
132
  exports.RangeSlider = RangeSlider;
@@ -10,6 +10,8 @@ import {
10
10
  import classify from '../../utils/classify';
11
11
  import type {ButtonSize} from '../Button';
12
12
  import {Button, BUTTON_SIZE} from '../Button';
13
+ import {Input} from '../Input';
14
+ import {BodySmall} from '../Text';
13
15
 
14
16
  import css from './RangeSlider.module.css';
15
17
 
@@ -32,6 +34,8 @@ export type RangeSliderProps = {
32
34
  hideRightBtn?: boolean,
33
35
  classNames?: ClassNames,
34
36
  ariaLabel?: string,
37
+ showRange?: boolean,
38
+ hideValueInput?: boolean,
35
39
  ...
36
40
  };
37
41
 
@@ -56,6 +60,8 @@ export const RangeSlider: React$AbstractComponent<
56
60
  hideLeftBtn,
57
61
  hideRightBtn,
58
62
  ariaLabel = 'Slider',
63
+ showRange,
64
+ hideValueInput,
59
65
  ...restInputProps
60
66
  }: RangeSliderProps,
61
67
  ref,
@@ -67,6 +73,22 @@ export const RangeSlider: React$AbstractComponent<
67
73
 
68
74
  const progressColor = disabled ? colorTextDisabled : colorFillPrimary;
69
75
 
76
+ const handleInputChange = (e: SyntheticEvent<HTMLInputElement>) => {
77
+ let inputValue = parseFloat(e.currentTarget.value);
78
+
79
+ // Validate and adjust the value
80
+ if (isNaN(inputValue) || inputValue < min) {
81
+ inputValue = min;
82
+ } else if (inputValue > max) {
83
+ inputValue = max;
84
+ } else if (step > 0) {
85
+ const nearestStep = Math.round(inputValue / step) * step;
86
+ inputValue = Math.round(nearestStep * 100) / 100; // Adjust to nearest valid step
87
+ }
88
+
89
+ onChange?.(inputValue);
90
+ };
91
+
70
92
  const handleChange = (e: SyntheticEvent<HTMLInputElement>) => {
71
93
  emitRoundedValue(e.currentTarget.value);
72
94
  };
@@ -87,7 +109,7 @@ export const RangeSlider: React$AbstractComponent<
87
109
  classNames?.wrapper,
88
110
  )}
89
111
  >
90
- {!hideLeftBtn && (
112
+ {!hideLeftBtn && !showRange && (
91
113
  <Button
92
114
  type="ghost"
93
115
  iconLeftName={iconLeftName}
@@ -98,6 +120,15 @@ export const RangeSlider: React$AbstractComponent<
98
120
  />
99
121
  )}
100
122
 
123
+ {showRange && (
124
+ <BodySmall
125
+ className={css.rangeText}
126
+ color={disabled ? 'disabled' : 'primary'}
127
+ >
128
+ {min}
129
+ </BodySmall>
130
+ )}
131
+
101
132
  <div className={css.sliderContainer}>
102
133
  <input
103
134
  {...restInputProps}
@@ -123,12 +154,26 @@ export const RangeSlider: React$AbstractComponent<
123
154
  by allowing user-defined brackets or ranges for tick marks.
124
155
  */}
125
156
  {Array.from({length: (max - min) / step + 1}, (_, index) => (
126
- <option key={index} value={min + index * step} />
157
+ <option
158
+ key={index}
159
+ value={min + index * step}
160
+ className={classify({[css.disabled]: disabled})}
161
+ />
127
162
  ))}
128
163
  </datalist>
129
164
  )}
130
165
  </div>
131
- {!hideRightBtn && (
166
+
167
+ {showRange && (
168
+ <BodySmall
169
+ className={css.rangeText}
170
+ color={disabled ? 'disabled' : 'primary'}
171
+ >
172
+ {max}
173
+ </BodySmall>
174
+ )}
175
+
176
+ {!hideRightBtn && !showRange && (
132
177
  <Button
133
178
  type="ghost"
134
179
  iconRightName={iconRightName}
@@ -138,6 +183,19 @@ export const RangeSlider: React$AbstractComponent<
138
183
  onClick={() => emitRoundedValue(value + step)}
139
184
  />
140
185
  )}
186
+
187
+ {!hideValueInput && (
188
+ <Input
189
+ size="small"
190
+ type="number"
191
+ value={String(value)}
192
+ classNames={{wrapper: css.valueInputWrapper}}
193
+ disabled={disabled}
194
+ onChange={handleInputChange}
195
+ disallowExponents
196
+ hideNumberSpinner
197
+ />
198
+ )}
141
199
  </div>
142
200
  );
143
201
  },
@@ -1,6 +1,6 @@
1
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';
2
+ @value (sizeFluid, size4, size20, size2, size34) from '../../styles/variables/_size.css';
3
+ @value (spaceXXSmall, spaceNone) from '../../styles/variables/_space.css';
4
4
  @value (borderRadiusLarge, borderRadiusCircle, borderWidthTertiary, borderWidthNone) from '../../styles/variables/_border.css';
5
5
 
6
6
  @value thumbSize: size20;
@@ -10,7 +10,7 @@
10
10
  display: flex;
11
11
  align-items: center;
12
12
  width: sizeFluid;
13
- gap: calc(spaceXSmall * 2);
13
+ gap: spaceXXSmall;
14
14
  }
15
15
 
16
16
  .sliderContainer {
@@ -119,3 +119,19 @@ input[type='range']:focus::-moz-range-thumb {
119
119
  padding-inline: spaceNone;
120
120
  white-space: nowrap;
121
121
  }
122
+
123
+ .sliderTicks option.disabled {
124
+ background-color: colorTextDisabled;
125
+ }
126
+
127
+ .rangeText {
128
+ display: flex;
129
+ min-width: size34;
130
+ min-height: size34;
131
+ justify-content: center;
132
+ align-items: center;
133
+ }
134
+
135
+ .valueInputWrapper {
136
+ max-width: 58px;
137
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spaced-out/ui-design-system",
3
- "version": "0.1.121",
3
+ "version": "0.1.122",
4
4
  "main": "index.js",
5
5
  "description": "Sense UI components library",
6
6
  "author": {