baseui 10.9.0 → 10.10.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.
@@ -278,10 +278,15 @@ function NumericalFilter(props) {
278
278
  }, [isRange, focused, sv, lv, uv, precision]),
279
279
  _React$useMemo5 = _slicedToArray(_React$useMemo4, 2),
280
280
  inputValueLower = _React$useMemo5[0],
281
- inputValueUpper = _React$useMemo5[1]; // We bound the values within our min and max even if a user enters a huge number
281
+ inputValueUpper = _React$useMemo5[1]; // We have our slider values range from 1 to the bin size, so we have a scale which
282
+ // takes in the data driven range and maps it to values the scale can always handle
282
283
 
283
284
 
284
- var sliderValue = isRange ? [Math.max(inputValueLower, min), Math.min(inputValueUpper, max)] : [Math.min(Math.max(inputValueLower, min), max)]; // keep the slider happy by sorting the two values
285
+ var sliderScale = React.useMemo(function () {
286
+ return (0, _d2.scaleLinear)().domain([min, max]).rangeRound([1, _constants.MAX_BIN_COUNT]) // We clamp the values within our min and max even if a user enters a huge number
287
+ .clamp(true);
288
+ }, [min, max]);
289
+ var sliderValue = isRange ? [sliderScale(inputValueLower), sliderScale(inputValueUpper)] : [sliderScale(inputValueLower)]; // keep the slider happy by sorting the two values
285
290
 
286
291
  if (isRange && sliderValue[0] > sliderValue[1]) {
287
292
  sliderValue = [sliderValue[1], sliderValue[0]];
@@ -372,28 +377,29 @@ function NumericalFilter(props) {
372
377
  // if we create a new instance these errors are prevented.
373
378
  , {
374
379
  key: isRange.toString(),
375
- min: min,
376
- max: max,
380
+ min: 1,
381
+ max: _constants.MAX_BIN_COUNT,
377
382
  value: sliderValue,
378
383
  onChange: function onChange(_ref3) {
379
384
  var value = _ref3.value;
380
385
 
381
386
  if (!value) {
382
387
  return;
383
- }
388
+ } // we convert back from the slider scale to the actual data's scale
389
+
384
390
 
385
391
  if (isRange) {
386
392
  var _value2 = _slicedToArray(value, 2),
387
393
  lowerValue = _value2[0],
388
394
  upperValue = _value2[1];
389
395
 
390
- setLower(lowerValue);
391
- setUpper(upperValue);
396
+ setLower(sliderScale.invert(lowerValue));
397
+ setUpper(sliderScale.invert(upperValue));
392
398
  } else {
393
399
  var _value3 = _slicedToArray(value, 1),
394
400
  singleValue = _value3[0];
395
401
 
396
- setSingle(singleValue);
402
+ setSingle(sliderScale.invert(singleValue));
397
403
  }
398
404
  },
399
405
  overrides: {
@@ -241,10 +241,21 @@ function NumericalFilter(props) {
241
241
  return [roundToFixed(l, precision), roundToFixed(h, precision)];
242
242
  }, [isRange, focused, sv, lv, uv, precision]);
243
243
 
244
- // We bound the values within our min and max even if a user enters a huge number
244
+ // We have our slider values range from 1 to the bin size, so we have a scale which
245
+ // takes in the data driven range and maps it to values the scale can always handle
246
+ const sliderScale = React.useMemo(
247
+ () =>
248
+ scaleLinear()
249
+ .domain([min, max])
250
+ .rangeRound([1, MAX_BIN_COUNT])
251
+ // We clamp the values within our min and max even if a user enters a huge number
252
+ .clamp(true),
253
+ [min, max],
254
+ );
255
+
245
256
  let sliderValue = isRange
246
- ? [Math.max(inputValueLower, min), Math.min(inputValueUpper, max)]
247
- : [Math.min(Math.max(inputValueLower, min), max)];
257
+ ? [sliderScale(inputValueLower), sliderScale(inputValueUpper)]
258
+ : [sliderScale(inputValueLower)];
248
259
 
249
260
  // keep the slider happy by sorting the two values
250
261
  if (isRange && sliderValue[0] > sliderValue[1]) {
@@ -323,20 +334,21 @@ function NumericalFilter(props) {
323
334
  // when it tries to read getThumbDistance on a thumb which is not there anymore
324
335
  // if we create a new instance these errors are prevented.
325
336
  key={isRange.toString()}
326
- min={min}
327
- max={max}
337
+ min={1}
338
+ max={MAX_BIN_COUNT}
328
339
  value={sliderValue}
329
340
  onChange={({value}) => {
330
341
  if (!value) {
331
342
  return;
332
343
  }
344
+ // we convert back from the slider scale to the actual data's scale
333
345
  if (isRange) {
334
346
  const [lowerValue, upperValue] = value;
335
- setLower(lowerValue);
336
- setUpper(upperValue);
347
+ setLower(sliderScale.invert(lowerValue));
348
+ setUpper(sliderScale.invert(upperValue));
337
349
  } else {
338
350
  const [singleValue] = value;
339
- setSingle(singleValue);
351
+ setSingle(sliderScale.invert(singleValue));
340
352
  }
341
353
  }}
342
354
  overrides={{
@@ -46,8 +46,10 @@ function MeasureColumn(_ref) {
46
46
 
47
47
  var ref = (0, React.useRef)();
48
48
  React.useEffect(function () {
49
- if (ref.current) {
50
- onLayout(columnIndex, ref.current.getBoundingClientRect());
49
+ if (typeof document !== 'undefined') {
50
+ if (ref.current) {
51
+ onLayout(columnIndex, ref.current.getBoundingClientRect());
52
+ }
51
53
  }
52
54
  }, []);
53
55
  return /*#__PURE__*/React.createElement("div", {
@@ -28,8 +28,10 @@ function MeasureColumn({
28
28
  const ref = useRef();
29
29
 
30
30
  React.useEffect(() => {
31
- if (ref.current) {
32
- onLayout(columnIndex, ref.current.getBoundingClientRect());
31
+ if (__BROWSER__) {
32
+ if (ref.current) {
33
+ onLayout(columnIndex, ref.current.getBoundingClientRect());
34
+ }
33
35
  }
34
36
  }, []);
35
37
 
@@ -189,9 +189,12 @@ function NumericalFilter(props) {
189
189
  l = validateInput(l) ? l : min;
190
190
  let h = validateInput(uv) ? uv : max;
191
191
  return [roundToFixed(l, precision), roundToFixed(h, precision)];
192
- }, [isRange, focused, sv, lv, uv, precision]); // We bound the values within our min and max even if a user enters a huge number
192
+ }, [isRange, focused, sv, lv, uv, precision]); // We have our slider values range from 1 to the bin size, so we have a scale which
193
+ // takes in the data driven range and maps it to values the scale can always handle
193
194
 
194
- let sliderValue = isRange ? [Math.max(inputValueLower, min), Math.min(inputValueUpper, max)] : [Math.min(Math.max(inputValueLower, min), max)]; // keep the slider happy by sorting the two values
195
+ const sliderScale = React.useMemo(() => scaleLinear().domain([min, max]).rangeRound([1, MAX_BIN_COUNT]) // We clamp the values within our min and max even if a user enters a huge number
196
+ .clamp(true), [min, max]);
197
+ let sliderValue = isRange ? [sliderScale(inputValueLower), sliderScale(inputValueUpper)] : [sliderScale(inputValueLower)]; // keep the slider happy by sorting the two values
195
198
 
196
199
  if (isRange && sliderValue[0] > sliderValue[1]) {
197
200
  sliderValue = [sliderValue[1], sliderValue[0]];
@@ -276,23 +279,24 @@ function NumericalFilter(props) {
276
279
  // if we create a new instance these errors are prevented.
277
280
  , {
278
281
  key: isRange.toString(),
279
- min: min,
280
- max: max,
282
+ min: 1,
283
+ max: MAX_BIN_COUNT,
281
284
  value: sliderValue,
282
285
  onChange: ({
283
286
  value
284
287
  }) => {
285
288
  if (!value) {
286
289
  return;
287
- }
290
+ } // we convert back from the slider scale to the actual data's scale
291
+
288
292
 
289
293
  if (isRange) {
290
294
  const [lowerValue, upperValue] = value;
291
- setLower(lowerValue);
292
- setUpper(upperValue);
295
+ setLower(sliderScale.invert(lowerValue));
296
+ setUpper(sliderScale.invert(upperValue));
293
297
  } else {
294
298
  const [singleValue] = value;
295
- setSingle(singleValue);
299
+ setSingle(sliderScale.invert(singleValue));
296
300
  }
297
301
  },
298
302
  overrides: {
@@ -20,8 +20,10 @@ function MeasureColumn({
20
20
  const [css] = useStyletron();
21
21
  const ref = useRef();
22
22
  React.useEffect(() => {
23
- if (ref.current) {
24
- onLayout(columnIndex, ref.current.getBoundingClientRect());
23
+ if (typeof document !== 'undefined') {
24
+ if (ref.current) {
25
+ onLayout(columnIndex, ref.current.getBoundingClientRect());
26
+ }
25
27
  }
26
28
  }, []);
27
29
  return /*#__PURE__*/React.createElement("div", {
@@ -11,7 +11,7 @@ LICENSE file in the root directory of this source tree.
11
11
  import * as React from 'react';
12
12
  import { getOverride, getOverrideProps } from '../helpers/overrides.js';
13
13
  import { UIDConsumer } from 'react-uid';
14
- import { Label as StyledLabel, Caption as StyledCaption, ControlContainer as StyledControlContainer } from './styled-components.js';
14
+ import { Label as StyledLabel, LabelEndEnhancer as StyledLabelEndEnhancer, LabelContainer as StyledLabelContainer, Caption as StyledCaption, ControlContainer as StyledControlContainer } from './styled-components.js';
15
15
 
16
16
  function chooseRenderedHint(caption, error, positive, sharedProps) {
17
17
  if (error && typeof error !== 'boolean') {
@@ -34,6 +34,8 @@ export default class FormControl extends React.Component {
34
34
  const {
35
35
  overrides: {
36
36
  Label: LabelOverride,
37
+ LabelEndEnhancer: LabelEndEnhancerOverride,
38
+ LabelContainer: LabelContainerOverride,
37
39
  Caption: CaptionOverride,
38
40
  ControlContainer: ControlContainerOverride
39
41
  },
@@ -43,7 +45,8 @@ export default class FormControl extends React.Component {
43
45
  error,
44
46
  positive,
45
47
  htmlFor,
46
- children
48
+ children,
49
+ counter
47
50
  } = this.props;
48
51
  const onlyChildProps = React.Children.only(children).props;
49
52
  const sharedProps = {
@@ -52,6 +55,8 @@ export default class FormControl extends React.Component {
52
55
  $positive: !!positive
53
56
  };
54
57
  const Label = getOverride(LabelOverride) || StyledLabel;
58
+ const LabelEndEnhancer = getOverride(LabelEndEnhancerOverride) || StyledLabelEndEnhancer;
59
+ const LabelContainer = getOverride(LabelContainerOverride) || StyledLabelContainer;
55
60
  const Caption = getOverride(CaptionOverride) || StyledCaption;
56
61
  const ControlContainer = getOverride(ControlContainerOverride) || StyledControlContainer;
57
62
  const hint = chooseRenderedHint(caption, error, positive, sharedProps);
@@ -63,10 +68,55 @@ export default class FormControl extends React.Component {
63
68
  }
64
69
  }
65
70
 
66
- return /*#__PURE__*/React.createElement(React.Fragment, null, label && /*#__PURE__*/React.createElement(Label, _extends({
71
+ let labelEndEnhancer = this.props.labelEndEnhancer;
72
+
73
+ if (counter) {
74
+ // inferred values are preferred but if the user specifies the value
75
+ // that is then used as the default.
76
+ let maxLength = null;
77
+ let length = null;
78
+ let counterError = null;
79
+
80
+ if (typeof counter === 'object') {
81
+ length = counter.length;
82
+ maxLength = counter.maxLength;
83
+ counterError = counter.error;
84
+ }
85
+
86
+ maxLength = maxLength ? maxLength : onlyChildProps.maxLength;
87
+
88
+ if (length == null && typeof onlyChildProps.value === 'string') {
89
+ length = onlyChildProps.value.length;
90
+ }
91
+
92
+ if (length == null) {
93
+ length = 0;
94
+
95
+ if (process.env.NODE_ENV !== "production") {
96
+ console.warn(`[FromControl] \`length\` must either be explicitly set via \`counter\` object property, or \`value\` string property on the child component.`);
97
+ }
98
+ }
99
+
100
+ sharedProps.$length = length;
101
+
102
+ if (maxLength == null) {
103
+ if (!labelEndEnhancer) labelEndEnhancer = `${length}`;
104
+ } else {
105
+ sharedProps.$maxLength = length;
106
+ if (!labelEndEnhancer) labelEndEnhancer = `${length}/${maxLength}`;
107
+ if (length > maxLength && counterError == null) counterError = true;
108
+ }
109
+
110
+ if (counterError) {
111
+ sharedProps.$error = true;
112
+ sharedProps.$counterError = true;
113
+ }
114
+ }
115
+
116
+ return /*#__PURE__*/React.createElement(React.Fragment, null, label && /*#__PURE__*/React.createElement(LabelContainer, _extends({}, sharedProps, getOverrideProps(LabelContainerOverride)), /*#__PURE__*/React.createElement(Label, _extends({
67
117
  "data-baseweb": "form-control-label",
68
118
  htmlFor: htmlFor || onlyChildProps.id
69
- }, sharedProps, getOverrideProps(LabelOverride)), typeof label === 'function' ? label(sharedProps) : label), /*#__PURE__*/React.createElement(UIDConsumer, null, captionId => /*#__PURE__*/React.createElement(ControlContainer, _extends({
119
+ }, sharedProps, getOverrideProps(LabelOverride)), typeof label === 'function' ? label(sharedProps) : label), labelEndEnhancer && /*#__PURE__*/React.createElement(LabelEndEnhancer, _extends({}, sharedProps, getOverrideProps(LabelEndEnhancerOverride)), typeof labelEndEnhancer === 'function' ? labelEndEnhancer(sharedProps) : labelEndEnhancer)), /*#__PURE__*/React.createElement(UIDConsumer, null, captionId => /*#__PURE__*/React.createElement(ControlContainer, _extends({
70
120
  "data-baseweb": "form-control-container"
71
121
  }, sharedProps, getOverrideProps(ControlContainerOverride)), React.Children.map(children, (child, index) => {
72
122
  if (!child) return;
@@ -76,8 +126,8 @@ export default class FormControl extends React.Component {
76
126
  'aria-errormessage': error ? captionId : null,
77
127
  'aria-describedby': caption || positive ? captionId : null,
78
128
  disabled: onlyChildProps.disabled || disabled,
79
- error: typeof onlyChildProps.error !== 'undefined' ? onlyChildProps.error : error,
80
- positive: typeof onlyChildProps.positive !== 'undefined' ? onlyChildProps.positive : positive
129
+ error: typeof onlyChildProps.error !== 'undefined' ? onlyChildProps.error : sharedProps.$error,
130
+ positive: typeof onlyChildProps.positive !== 'undefined' ? onlyChildProps.positive : sharedProps.$positive
81
131
  });
82
132
  }), (caption || error || positive) && /*#__PURE__*/React.createElement(Caption, _extends({
83
133
  "data-baseweb": "form-control-caption",
@@ -91,5 +141,6 @@ _defineProperty(FormControl, "defaultProps", {
91
141
  overrides: {},
92
142
  label: null,
93
143
  caption: null,
94
- disabled: false
144
+ disabled: false,
145
+ counter: false
95
146
  });
@@ -10,7 +10,6 @@ export const Label = styled('label', props => {
10
10
  $disabled,
11
11
  $theme: {
12
12
  colors,
13
- sizing,
14
13
  typography
15
14
  }
16
15
  } = props;
@@ -22,14 +21,36 @@ export const Label = styled('label', props => {
22
21
  paddingTop: 0,
23
22
  paddingRight: 0,
24
23
  paddingBottom: 0,
25
- paddingLeft: 0,
26
- marginTop: sizing.scale300,
27
- marginRight: 0,
28
- marginBottom: sizing.scale300,
29
- marginLeft: 0
24
+ paddingLeft: 0
30
25
  };
31
26
  });
32
27
  Label.displayName = "Label";
28
+ export const LabelContainer = styled('span', ({
29
+ $theme: {
30
+ sizing
31
+ }
32
+ }) => ({
33
+ display: 'flex',
34
+ width: '100%',
35
+ marginTop: sizing.scale300,
36
+ marginRight: 0,
37
+ marginBottom: sizing.scale300,
38
+ marginLeft: 0
39
+ }));
40
+ LabelContainer.displayName = "LabelContainer";
41
+ export const LabelEndEnhancer = styled('span', ({
42
+ $disabled,
43
+ $counterError,
44
+ $theme: {
45
+ colors,
46
+ typography
47
+ }
48
+ }) => ({ ...typography.font100,
49
+ flex: 0,
50
+ width: '100%',
51
+ color: $counterError ? colors.negative400 : $disabled ? colors.contentSecondary : colors.contentPrimary
52
+ }));
53
+ LabelEndEnhancer.displayName = "LabelEndEnhancer";
33
54
  export const Caption = styled('div', props => {
34
55
  const {
35
56
  $error,
@@ -457,7 +457,7 @@ class PopoverInner extends React.Component {
457
457
  crossFrame: false,
458
458
  focusOptions: this.props.focusOptions
459
459
  }, this.renderPopover(renderedContent)) : /*#__PURE__*/React.createElement(MoveFocusInside, {
460
- disabled: !this.props.autoFocus && !this.state.autoFocusAfterPositioning
460
+ disabled: !this.props.autoFocus || !this.state.autoFocusAfterPositioning
461
461
  }, this.renderPopover(renderedContent)))));
462
462
  } else {
463
463
  rendered.push( /*#__PURE__*/React.createElement(Hidden, {
@@ -32,7 +32,7 @@ class TimezonePicker extends React.Component {
32
32
  try {
33
33
  const offset = getTimezoneOffset(zoneName, compareDate) / 3_600_000;
34
34
  const offsetFormatted = `${offset >= 0 ? '+' : '-'}${Math.abs(offset)}`;
35
- let label = `(GMT${offsetFormatted}) ${zoneName.replace('_', ' ')}`;
35
+ let label = `(GMT${offsetFormatted}) ${zoneName.replace(/_/g, ' ')}`;
36
36
 
37
37
  if (this.props.includeAbbreviations) {
38
38
  const abbreviation = format(compareDate, 'zzz', {
@@ -44,10 +44,12 @@ class TimezonePicker extends React.Component {
44
44
  }
45
45
  }
46
46
 
47
+ const offsetMinutes = offset * 60;
47
48
  timezones.push({
48
49
  id: zoneName,
49
50
  label,
50
- offset
51
+ // offset output is in minutes, difference of UTC and this zone (negative for hours ahead of UTC, positive for hours behind)
52
+ offset: offsetMinutes === 0 ? 0 : offsetMinutes * -1
51
53
  });
52
54
  } catch (error) {
53
55
  // Ignores timezones that are not available within a user's browser/operating system
@@ -259,10 +259,15 @@ function NumericalFilter(props) {
259
259
  }, [isRange, focused, sv, lv, uv, precision]),
260
260
  _React$useMemo5 = _slicedToArray(_React$useMemo4, 2),
261
261
  inputValueLower = _React$useMemo5[0],
262
- inputValueUpper = _React$useMemo5[1]; // We bound the values within our min and max even if a user enters a huge number
262
+ inputValueUpper = _React$useMemo5[1]; // We have our slider values range from 1 to the bin size, so we have a scale which
263
+ // takes in the data driven range and maps it to values the scale can always handle
263
264
 
264
265
 
265
- var sliderValue = isRange ? [Math.max(inputValueLower, min), Math.min(inputValueUpper, max)] : [Math.min(Math.max(inputValueLower, min), max)]; // keep the slider happy by sorting the two values
266
+ var sliderScale = React.useMemo(function () {
267
+ return scaleLinear().domain([min, max]).rangeRound([1, MAX_BIN_COUNT]) // We clamp the values within our min and max even if a user enters a huge number
268
+ .clamp(true);
269
+ }, [min, max]);
270
+ var sliderValue = isRange ? [sliderScale(inputValueLower), sliderScale(inputValueUpper)] : [sliderScale(inputValueLower)]; // keep the slider happy by sorting the two values
266
271
 
267
272
  if (isRange && sliderValue[0] > sliderValue[1]) {
268
273
  sliderValue = [sliderValue[1], sliderValue[0]];
@@ -353,28 +358,29 @@ function NumericalFilter(props) {
353
358
  // if we create a new instance these errors are prevented.
354
359
  , {
355
360
  key: isRange.toString(),
356
- min: min,
357
- max: max,
361
+ min: 1,
362
+ max: MAX_BIN_COUNT,
358
363
  value: sliderValue,
359
364
  onChange: function onChange(_ref3) {
360
365
  var value = _ref3.value;
361
366
 
362
367
  if (!value) {
363
368
  return;
364
- }
369
+ } // we convert back from the slider scale to the actual data's scale
370
+
365
371
 
366
372
  if (isRange) {
367
373
  var _value2 = _slicedToArray(value, 2),
368
374
  lowerValue = _value2[0],
369
375
  upperValue = _value2[1];
370
376
 
371
- setLower(lowerValue);
372
- setUpper(upperValue);
377
+ setLower(sliderScale.invert(lowerValue));
378
+ setUpper(sliderScale.invert(upperValue));
373
379
  } else {
374
380
  var _value3 = _slicedToArray(value, 1),
375
381
  singleValue = _value3[0];
376
382
 
377
- setSingle(singleValue);
383
+ setSingle(sliderScale.invert(singleValue));
378
384
  }
379
385
  },
380
386
  overrides: {
@@ -35,8 +35,10 @@ function MeasureColumn(_ref) {
35
35
 
36
36
  var ref = useRef();
37
37
  React.useEffect(function () {
38
- if (ref.current) {
39
- onLayout(columnIndex, ref.current.getBoundingClientRect());
38
+ if (typeof document !== 'undefined') {
39
+ if (ref.current) {
40
+ onLayout(columnIndex, ref.current.getBoundingClientRect());
41
+ }
40
42
  }
41
43
  }, []);
42
44
  return /*#__PURE__*/React.createElement("div", {
@@ -1,7 +1,7 @@
1
- function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
2
-
3
1
  function _extends() { _extends = Object.assign || 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); }
4
2
 
3
+ function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
4
+
5
5
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
6
6
 
7
7
  function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
@@ -33,7 +33,7 @@ LICENSE file in the root directory of this source tree.
33
33
  import * as React from 'react';
34
34
  import { getOverride, getOverrideProps } from '../helpers/overrides.js';
35
35
  import { UIDConsumer } from 'react-uid';
36
- import { Label as StyledLabel, Caption as StyledCaption, ControlContainer as StyledControlContainer } from './styled-components.js';
36
+ import { Label as StyledLabel, LabelEndEnhancer as StyledLabelEndEnhancer, LabelContainer as StyledLabelContainer, Caption as StyledCaption, ControlContainer as StyledControlContainer } from './styled-components.js';
37
37
 
38
38
  function chooseRenderedHint(caption, error, positive, sharedProps) {
39
39
  if (error && typeof error !== 'boolean') {
@@ -68,6 +68,8 @@ var FormControl = /*#__PURE__*/function (_React$Component) {
68
68
  var _this$props = this.props,
69
69
  _this$props$overrides = _this$props.overrides,
70
70
  LabelOverride = _this$props$overrides.Label,
71
+ LabelEndEnhancerOverride = _this$props$overrides.LabelEndEnhancer,
72
+ LabelContainerOverride = _this$props$overrides.LabelContainer,
71
73
  CaptionOverride = _this$props$overrides.Caption,
72
74
  ControlContainerOverride = _this$props$overrides.ControlContainer,
73
75
  label = _this$props.label,
@@ -76,7 +78,8 @@ var FormControl = /*#__PURE__*/function (_React$Component) {
76
78
  error = _this$props.error,
77
79
  positive = _this$props.positive,
78
80
  htmlFor = _this$props.htmlFor,
79
- children = _this$props.children;
81
+ children = _this$props.children,
82
+ counter = _this$props.counter;
80
83
  var onlyChildProps = React.Children.only(children).props;
81
84
  var sharedProps = {
82
85
  $disabled: !!disabled,
@@ -84,6 +87,8 @@ var FormControl = /*#__PURE__*/function (_React$Component) {
84
87
  $positive: !!positive
85
88
  };
86
89
  var Label = getOverride(LabelOverride) || StyledLabel;
90
+ var LabelEndEnhancer = getOverride(LabelEndEnhancerOverride) || StyledLabelEndEnhancer;
91
+ var LabelContainer = getOverride(LabelContainerOverride) || StyledLabelContainer;
87
92
  var Caption = getOverride(CaptionOverride) || StyledCaption;
88
93
  var ControlContainer = getOverride(ControlContainerOverride) || StyledControlContainer;
89
94
  var hint = chooseRenderedHint(caption, error, positive, sharedProps);
@@ -95,10 +100,55 @@ var FormControl = /*#__PURE__*/function (_React$Component) {
95
100
  }
96
101
  }
97
102
 
98
- return /*#__PURE__*/React.createElement(React.Fragment, null, label && /*#__PURE__*/React.createElement(Label, _extends({
103
+ var labelEndEnhancer = this.props.labelEndEnhancer;
104
+
105
+ if (counter) {
106
+ // inferred values are preferred but if the user specifies the value
107
+ // that is then used as the default.
108
+ var maxLength = null;
109
+ var length = null;
110
+ var counterError = null;
111
+
112
+ if (_typeof(counter) === 'object') {
113
+ length = counter.length;
114
+ maxLength = counter.maxLength;
115
+ counterError = counter.error;
116
+ }
117
+
118
+ maxLength = maxLength ? maxLength : onlyChildProps.maxLength;
119
+
120
+ if (length == null && typeof onlyChildProps.value === 'string') {
121
+ length = onlyChildProps.value.length;
122
+ }
123
+
124
+ if (length == null) {
125
+ length = 0;
126
+
127
+ if (process.env.NODE_ENV !== "production") {
128
+ console.warn("[FromControl] `length` must either be explicitly set via `counter` object property, or `value` string property on the child component.");
129
+ }
130
+ }
131
+
132
+ sharedProps.$length = length;
133
+
134
+ if (maxLength == null) {
135
+ if (!labelEndEnhancer) labelEndEnhancer = "".concat(length);
136
+ } else {
137
+ sharedProps.$maxLength = length;
138
+ if (!labelEndEnhancer) labelEndEnhancer = "".concat(length, "/").concat(maxLength);
139
+ if (length > maxLength && counterError == null) counterError = true;
140
+ }
141
+
142
+ if (counterError) {
143
+ sharedProps.$error = true;
144
+ sharedProps.$counterError = true;
145
+ }
146
+ }
147
+
148
+ return /*#__PURE__*/React.createElement(React.Fragment, null, label && /*#__PURE__*/React.createElement(LabelContainer, _extends({}, sharedProps, getOverrideProps(LabelContainerOverride)), /*#__PURE__*/React.createElement(Label, _extends({
99
149
  "data-baseweb": "form-control-label",
100
150
  htmlFor: htmlFor || onlyChildProps.id
101
- }, sharedProps, getOverrideProps(LabelOverride)), typeof label === 'function' ? label(sharedProps) : label), /*#__PURE__*/React.createElement(UIDConsumer, null, function (captionId) {
151
+ }, sharedProps, getOverrideProps(LabelOverride)), typeof label === 'function' ? label(sharedProps) : label), labelEndEnhancer && /*#__PURE__*/React.createElement(LabelEndEnhancer, _extends({}, sharedProps, getOverrideProps(LabelEndEnhancerOverride)), typeof labelEndEnhancer === 'function' ? labelEndEnhancer(sharedProps) : labelEndEnhancer)), /*#__PURE__*/React.createElement(UIDConsumer, null, function (captionId) {
102
152
  return /*#__PURE__*/React.createElement(ControlContainer, _extends({
103
153
  "data-baseweb": "form-control-container"
104
154
  }, sharedProps, getOverrideProps(ControlContainerOverride)), React.Children.map(children, function (child, index) {
@@ -109,8 +159,8 @@ var FormControl = /*#__PURE__*/function (_React$Component) {
109
159
  'aria-errormessage': error ? captionId : null,
110
160
  'aria-describedby': caption || positive ? captionId : null,
111
161
  disabled: onlyChildProps.disabled || disabled,
112
- error: typeof onlyChildProps.error !== 'undefined' ? onlyChildProps.error : error,
113
- positive: typeof onlyChildProps.positive !== 'undefined' ? onlyChildProps.positive : positive
162
+ error: typeof onlyChildProps.error !== 'undefined' ? onlyChildProps.error : sharedProps.$error,
163
+ positive: typeof onlyChildProps.positive !== 'undefined' ? onlyChildProps.positive : sharedProps.$positive
114
164
  });
115
165
  }), (caption || error || positive) && /*#__PURE__*/React.createElement(Caption, _extends({
116
166
  "data-baseweb": "form-control-caption",
@@ -127,7 +177,8 @@ _defineProperty(FormControl, "defaultProps", {
127
177
  overrides: {},
128
178
  label: null,
129
179
  caption: null,
130
- disabled: false
180
+ disabled: false,
181
+ counter: false
131
182
  });
132
183
 
133
184
  export { FormControl as default };
@@ -15,7 +15,6 @@ export var Label = styled('label', function (props) {
15
15
  var $disabled = props.$disabled,
16
16
  _props$$theme = props.$theme,
17
17
  colors = _props$$theme.colors,
18
- sizing = _props$$theme.sizing,
19
18
  typography = _props$$theme.typography;
20
19
  return _objectSpread(_objectSpread({}, typography.font250), {}, {
21
20
  fontWeight: 500,
@@ -25,14 +24,35 @@ export var Label = styled('label', function (props) {
25
24
  paddingTop: 0,
26
25
  paddingRight: 0,
27
26
  paddingBottom: 0,
28
- paddingLeft: 0,
27
+ paddingLeft: 0
28
+ });
29
+ });
30
+ Label.displayName = "Label";
31
+ export var LabelContainer = styled('span', function (_ref) {
32
+ var sizing = _ref.$theme.sizing;
33
+ return {
34
+ display: 'flex',
35
+ width: '100%',
29
36
  marginTop: sizing.scale300,
30
37
  marginRight: 0,
31
38
  marginBottom: sizing.scale300,
32
39
  marginLeft: 0
40
+ };
41
+ });
42
+ LabelContainer.displayName = "LabelContainer";
43
+ export var LabelEndEnhancer = styled('span', function (_ref2) {
44
+ var $disabled = _ref2.$disabled,
45
+ $counterError = _ref2.$counterError,
46
+ _ref2$$theme = _ref2.$theme,
47
+ colors = _ref2$$theme.colors,
48
+ typography = _ref2$$theme.typography;
49
+ return _objectSpread(_objectSpread({}, typography.font100), {}, {
50
+ flex: 0,
51
+ width: '100%',
52
+ color: $counterError ? colors.negative400 : $disabled ? colors.contentSecondary : colors.contentPrimary
33
53
  });
34
54
  });
35
- Label.displayName = "Label";
55
+ LabelEndEnhancer.displayName = "LabelEndEnhancer";
36
56
  export var Caption = styled('div', function (props) {
37
57
  var $error = props.$error,
38
58
  $positive = props.$positive,
@@ -520,7 +520,7 @@ var PopoverInner = /*#__PURE__*/function (_React$Component) {
520
520
  crossFrame: false,
521
521
  focusOptions: this.props.focusOptions
522
522
  }, this.renderPopover(renderedContent)) : /*#__PURE__*/React.createElement(MoveFocusInside, {
523
- disabled: !this.props.autoFocus && !this.state.autoFocusAfterPositioning
523
+ disabled: !this.props.autoFocus || !this.state.autoFocusAfterPositioning
524
524
  }, this.renderPopover(renderedContent)))));
525
525
  } else {
526
526
  rendered.push( /*#__PURE__*/React.createElement(Hidden, {
@@ -86,7 +86,7 @@ var TimezonePicker = /*#__PURE__*/function (_React$Component) {
86
86
  try {
87
87
  var offset = getTimezoneOffset(zoneName, compareDate) / 3600000;
88
88
  var offsetFormatted = "".concat(offset >= 0 ? '+' : '-').concat(Math.abs(offset));
89
- var label = "(GMT".concat(offsetFormatted, ") ").concat(zoneName.replace('_', ' '));
89
+ var label = "(GMT".concat(offsetFormatted, ") ").concat(zoneName.replace(/_/g, ' '));
90
90
 
91
91
  if (_this.props.includeAbbreviations) {
92
92
  var abbreviation = format(compareDate, 'zzz', {
@@ -98,10 +98,12 @@ var TimezonePicker = /*#__PURE__*/function (_React$Component) {
98
98
  }
99
99
  }
100
100
 
101
+ var offsetMinutes = offset * 60;
101
102
  timezones.push({
102
103
  id: zoneName,
103
104
  label: label,
104
- offset: offset
105
+ // offset output is in minutes, difference of UTC and this zone (negative for hours ahead of UTC, positive for hours behind)
106
+ offset: offsetMinutes === 0 ? 0 : offsetMinutes * -1
105
107
  });
106
108
  } catch (error) {
107
109
  // Ignores timezones that are not available within a user's browser/operating system
@@ -1,7 +1,5 @@
1
1
  "use strict";
2
2
 
3
- function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
4
-
5
3
  Object.defineProperty(exports, "__esModule", {
6
4
  value: true
7
5
  });
@@ -21,6 +19,8 @@ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj;
21
19
 
22
20
  function _extends() { _extends = Object.assign || 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); }
23
21
 
22
+ function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
23
+
24
24
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
25
25
 
26
26
  function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
@@ -76,6 +76,8 @@ var FormControl = /*#__PURE__*/function (_React$Component) {
76
76
  var _this$props = this.props,
77
77
  _this$props$overrides = _this$props.overrides,
78
78
  LabelOverride = _this$props$overrides.Label,
79
+ LabelEndEnhancerOverride = _this$props$overrides.LabelEndEnhancer,
80
+ LabelContainerOverride = _this$props$overrides.LabelContainer,
79
81
  CaptionOverride = _this$props$overrides.Caption,
80
82
  ControlContainerOverride = _this$props$overrides.ControlContainer,
81
83
  label = _this$props.label,
@@ -84,7 +86,8 @@ var FormControl = /*#__PURE__*/function (_React$Component) {
84
86
  error = _this$props.error,
85
87
  positive = _this$props.positive,
86
88
  htmlFor = _this$props.htmlFor,
87
- children = _this$props.children;
89
+ children = _this$props.children,
90
+ counter = _this$props.counter;
88
91
  var onlyChildProps = React.Children.only(children).props;
89
92
  var sharedProps = {
90
93
  $disabled: !!disabled,
@@ -94,6 +97,10 @@ var FormControl = /*#__PURE__*/function (_React$Component) {
94
97
 
95
98
  var Label = (0, _overrides.getOverride)(LabelOverride) || _styledComponents.Label;
96
99
 
100
+ var LabelEndEnhancer = (0, _overrides.getOverride)(LabelEndEnhancerOverride) || _styledComponents.LabelEndEnhancer;
101
+
102
+ var LabelContainer = (0, _overrides.getOverride)(LabelContainerOverride) || _styledComponents.LabelContainer;
103
+
97
104
  var Caption = (0, _overrides.getOverride)(CaptionOverride) || _styledComponents.Caption;
98
105
 
99
106
  var ControlContainer = (0, _overrides.getOverride)(ControlContainerOverride) || _styledComponents.ControlContainer;
@@ -107,10 +114,55 @@ var FormControl = /*#__PURE__*/function (_React$Component) {
107
114
  }
108
115
  }
109
116
 
110
- return /*#__PURE__*/React.createElement(React.Fragment, null, label && /*#__PURE__*/React.createElement(Label, _extends({
117
+ var labelEndEnhancer = this.props.labelEndEnhancer;
118
+
119
+ if (counter) {
120
+ // inferred values are preferred but if the user specifies the value
121
+ // that is then used as the default.
122
+ var maxLength = null;
123
+ var length = null;
124
+ var counterError = null;
125
+
126
+ if (_typeof(counter) === 'object') {
127
+ length = counter.length;
128
+ maxLength = counter.maxLength;
129
+ counterError = counter.error;
130
+ }
131
+
132
+ maxLength = maxLength ? maxLength : onlyChildProps.maxLength;
133
+
134
+ if (length == null && typeof onlyChildProps.value === 'string') {
135
+ length = onlyChildProps.value.length;
136
+ }
137
+
138
+ if (length == null) {
139
+ length = 0;
140
+
141
+ if (process.env.NODE_ENV !== "production") {
142
+ console.warn("[FromControl] `length` must either be explicitly set via `counter` object property, or `value` string property on the child component.");
143
+ }
144
+ }
145
+
146
+ sharedProps.$length = length;
147
+
148
+ if (maxLength == null) {
149
+ if (!labelEndEnhancer) labelEndEnhancer = "".concat(length);
150
+ } else {
151
+ sharedProps.$maxLength = length;
152
+ if (!labelEndEnhancer) labelEndEnhancer = "".concat(length, "/").concat(maxLength);
153
+ if (length > maxLength && counterError == null) counterError = true;
154
+ }
155
+
156
+ if (counterError) {
157
+ sharedProps.$error = true;
158
+ sharedProps.$counterError = true;
159
+ }
160
+ }
161
+
162
+ return /*#__PURE__*/React.createElement(React.Fragment, null, label && /*#__PURE__*/React.createElement(LabelContainer, _extends({}, sharedProps, (0, _overrides.getOverrideProps)(LabelContainerOverride)), /*#__PURE__*/React.createElement(Label, _extends({
111
163
  "data-baseweb": "form-control-label",
112
164
  htmlFor: htmlFor || onlyChildProps.id
113
- }, sharedProps, (0, _overrides.getOverrideProps)(LabelOverride)), typeof label === 'function' ? label(sharedProps) : label), /*#__PURE__*/React.createElement(_reactUid.UIDConsumer, null, function (captionId) {
165
+ }, sharedProps, (0, _overrides.getOverrideProps)(LabelOverride)), typeof label === 'function' ? label(sharedProps) : label), labelEndEnhancer && /*#__PURE__*/React.createElement(LabelEndEnhancer, _extends({}, sharedProps, (0, _overrides.getOverrideProps)(LabelEndEnhancerOverride)), typeof labelEndEnhancer === 'function' ? labelEndEnhancer(sharedProps) : labelEndEnhancer)), /*#__PURE__*/React.createElement(_reactUid.UIDConsumer, null, function (captionId) {
114
166
  return /*#__PURE__*/React.createElement(ControlContainer, _extends({
115
167
  "data-baseweb": "form-control-container"
116
168
  }, sharedProps, (0, _overrides.getOverrideProps)(ControlContainerOverride)), React.Children.map(children, function (child, index) {
@@ -121,8 +173,8 @@ var FormControl = /*#__PURE__*/function (_React$Component) {
121
173
  'aria-errormessage': error ? captionId : null,
122
174
  'aria-describedby': caption || positive ? captionId : null,
123
175
  disabled: onlyChildProps.disabled || disabled,
124
- error: typeof onlyChildProps.error !== 'undefined' ? onlyChildProps.error : error,
125
- positive: typeof onlyChildProps.positive !== 'undefined' ? onlyChildProps.positive : positive
176
+ error: typeof onlyChildProps.error !== 'undefined' ? onlyChildProps.error : sharedProps.$error,
177
+ positive: typeof onlyChildProps.positive !== 'undefined' ? onlyChildProps.positive : sharedProps.$positive
126
178
  });
127
179
  }), (caption || error || positive) && /*#__PURE__*/React.createElement(Caption, _extends({
128
180
  "data-baseweb": "form-control-caption",
@@ -141,5 +193,6 @@ _defineProperty(FormControl, "defaultProps", {
141
193
  overrides: {},
142
194
  label: null,
143
195
  caption: null,
144
- disabled: false
196
+ disabled: false,
197
+ counter: false
145
198
  });
@@ -11,10 +11,16 @@ import {getOverride, getOverrideProps} from '../helpers/overrides.js';
11
11
  import {UIDConsumer} from 'react-uid';
12
12
  import {
13
13
  Label as StyledLabel,
14
+ LabelEndEnhancer as StyledLabelEndEnhancer,
15
+ LabelContainer as StyledLabelContainer,
14
16
  Caption as StyledCaption,
15
17
  ControlContainer as StyledControlContainer,
16
18
  } from './styled-components.js';
17
- import type {FormControlPropsT, FormControlStateT} from './types.js';
19
+ import type {
20
+ FormControlPropsT,
21
+ FormControlStateT,
22
+ StylePropsT,
23
+ } from './types.js';
18
24
 
19
25
  function chooseRenderedHint(caption, error, positive, sharedProps) {
20
26
  if (error && typeof error !== 'boolean') {
@@ -41,12 +47,15 @@ export default class FormControl extends React.Component<
41
47
  label: null,
42
48
  caption: null,
43
49
  disabled: false,
50
+ counter: false,
44
51
  };
45
52
 
46
53
  render() {
47
54
  const {
48
55
  overrides: {
49
56
  Label: LabelOverride,
57
+ LabelEndEnhancer: LabelEndEnhancerOverride,
58
+ LabelContainer: LabelContainerOverride,
50
59
  Caption: CaptionOverride,
51
60
  ControlContainer: ControlContainerOverride,
52
61
  },
@@ -57,17 +66,22 @@ export default class FormControl extends React.Component<
57
66
  positive,
58
67
  htmlFor,
59
68
  children,
69
+ counter,
60
70
  } = this.props;
61
71
 
62
72
  const onlyChildProps = React.Children.only(children).props;
63
73
 
64
- const sharedProps = {
74
+ const sharedProps: StylePropsT = {
65
75
  $disabled: !!disabled,
66
76
  $error: !!error,
67
77
  $positive: !!positive,
68
78
  };
69
79
 
70
80
  const Label = getOverride(LabelOverride) || StyledLabel;
81
+ const LabelEndEnhancer =
82
+ getOverride(LabelEndEnhancerOverride) || StyledLabelEndEnhancer;
83
+ const LabelContainer =
84
+ getOverride(LabelContainerOverride) || StyledLabelContainer;
71
85
  const Caption = getOverride(CaptionOverride) || StyledCaption;
72
86
  const ControlContainer =
73
87
  getOverride(ControlContainerOverride) || StyledControlContainer;
@@ -83,17 +97,75 @@ export default class FormControl extends React.Component<
83
97
  }
84
98
  }
85
99
 
100
+ let labelEndEnhancer = this.props.labelEndEnhancer;
101
+ if (counter) {
102
+ // inferred values are preferred but if the user specifies the value
103
+ // that is then used as the default.
104
+ let maxLength: ?number = null;
105
+ let length: ?number = null;
106
+ let counterError: ?boolean = null;
107
+
108
+ if (typeof counter === 'object') {
109
+ length = counter.length;
110
+ maxLength = counter.maxLength;
111
+ counterError = counter.error;
112
+ }
113
+
114
+ maxLength = maxLength ? maxLength : onlyChildProps.maxLength;
115
+ if (length == null && typeof onlyChildProps.value === 'string') {
116
+ length = onlyChildProps.value.length;
117
+ }
118
+
119
+ if (length == null) {
120
+ length = 0;
121
+ if (__DEV__) {
122
+ console.warn(
123
+ `[FromControl] \`length\` must either be explicitly set via \`counter\` object property, or \`value\` string property on the child component.`,
124
+ );
125
+ }
126
+ }
127
+
128
+ sharedProps.$length = length;
129
+ if (maxLength == null) {
130
+ if (!labelEndEnhancer) labelEndEnhancer = `${length}`;
131
+ } else {
132
+ sharedProps.$maxLength = length;
133
+ if (!labelEndEnhancer) labelEndEnhancer = `${length}/${maxLength}`;
134
+ if (length > maxLength && counterError == null) counterError = true;
135
+ }
136
+
137
+ if (counterError) {
138
+ sharedProps.$error = true;
139
+ sharedProps.$counterError = true;
140
+ }
141
+ }
142
+
86
143
  return (
87
144
  <React.Fragment>
88
145
  {label && (
89
- <Label
90
- data-baseweb="form-control-label"
91
- htmlFor={htmlFor || onlyChildProps.id}
146
+ <LabelContainer
92
147
  {...sharedProps}
93
- {...getOverrideProps(LabelOverride)}
148
+ {...getOverrideProps(LabelContainerOverride)}
94
149
  >
95
- {typeof label === 'function' ? label(sharedProps) : label}
96
- </Label>
150
+ <Label
151
+ data-baseweb="form-control-label"
152
+ htmlFor={htmlFor || onlyChildProps.id}
153
+ {...sharedProps}
154
+ {...getOverrideProps(LabelOverride)}
155
+ >
156
+ {typeof label === 'function' ? label(sharedProps) : label}
157
+ </Label>
158
+ {labelEndEnhancer && (
159
+ <LabelEndEnhancer
160
+ {...sharedProps}
161
+ {...getOverrideProps(LabelEndEnhancerOverride)}
162
+ >
163
+ {typeof labelEndEnhancer === 'function'
164
+ ? labelEndEnhancer(sharedProps)
165
+ : labelEndEnhancer}
166
+ </LabelEndEnhancer>
167
+ )}
168
+ </LabelContainer>
97
169
  )}
98
170
  <UIDConsumer>
99
171
  {captionId => (
@@ -114,11 +186,11 @@ export default class FormControl extends React.Component<
114
186
  error:
115
187
  typeof onlyChildProps.error !== 'undefined'
116
188
  ? onlyChildProps.error
117
- : error,
189
+ : sharedProps.$error,
118
190
  positive:
119
191
  typeof onlyChildProps.positive !== 'undefined'
120
192
  ? onlyChildProps.positive
121
- : positive,
193
+ : sharedProps.$positive,
122
194
  });
123
195
  })}
124
196
  {(caption || error || positive) && (
@@ -25,6 +25,7 @@ export interface FormControlProps {
25
25
  error?: boolean | React.ReactNode;
26
26
  positive?: React.ReactNode;
27
27
  htmlFor?: string;
28
+ counter?: boolean | {length?: number; maxLength?: number; error?: boolean};
28
29
  }
29
30
 
30
31
  export class FormControl extends React.Component<
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.ControlContainer = exports.Caption = exports.Label = void 0;
6
+ exports.ControlContainer = exports.Caption = exports.LabelEndEnhancer = exports.LabelContainer = exports.Label = void 0;
7
7
 
8
8
  var _index = require("../styles/index.js");
9
9
 
@@ -17,7 +17,6 @@ var Label = (0, _index.styled)('label', function (props) {
17
17
  var $disabled = props.$disabled,
18
18
  _props$$theme = props.$theme,
19
19
  colors = _props$$theme.colors,
20
- sizing = _props$$theme.sizing,
21
20
  typography = _props$$theme.typography;
22
21
  return _objectSpread(_objectSpread({}, typography.font250), {}, {
23
22
  fontWeight: 500,
@@ -27,15 +26,38 @@ var Label = (0, _index.styled)('label', function (props) {
27
26
  paddingTop: 0,
28
27
  paddingRight: 0,
29
28
  paddingBottom: 0,
30
- paddingLeft: 0,
29
+ paddingLeft: 0
30
+ });
31
+ });
32
+ exports.Label = Label;
33
+ Label.displayName = "Label";
34
+ var LabelContainer = (0, _index.styled)('span', function (_ref) {
35
+ var sizing = _ref.$theme.sizing;
36
+ return {
37
+ display: 'flex',
38
+ width: '100%',
31
39
  marginTop: sizing.scale300,
32
40
  marginRight: 0,
33
41
  marginBottom: sizing.scale300,
34
42
  marginLeft: 0
43
+ };
44
+ });
45
+ exports.LabelContainer = LabelContainer;
46
+ LabelContainer.displayName = "LabelContainer";
47
+ var LabelEndEnhancer = (0, _index.styled)('span', function (_ref2) {
48
+ var $disabled = _ref2.$disabled,
49
+ $counterError = _ref2.$counterError,
50
+ _ref2$$theme = _ref2.$theme,
51
+ colors = _ref2$$theme.colors,
52
+ typography = _ref2$$theme.typography;
53
+ return _objectSpread(_objectSpread({}, typography.font100), {}, {
54
+ flex: 0,
55
+ width: '100%',
56
+ color: $counterError ? colors.negative400 : $disabled ? colors.contentSecondary : colors.contentPrimary
35
57
  });
36
58
  });
37
- exports.Label = Label;
38
- Label.displayName = "Label";
59
+ exports.LabelEndEnhancer = LabelEndEnhancer;
60
+ LabelEndEnhancer.displayName = "LabelEndEnhancer";
39
61
  var Caption = (0, _index.styled)('div', function (props) {
40
62
  var $error = props.$error,
41
63
  $positive = props.$positive,
@@ -12,7 +12,7 @@ import type {StylePropsT} from './types.js';
12
12
  export const Label = styled<StylePropsT>('label', props => {
13
13
  const {
14
14
  $disabled,
15
- $theme: {colors, sizing, typography},
15
+ $theme: {colors, typography},
16
16
  } = props;
17
17
  return {
18
18
  ...typography.font250,
@@ -24,12 +24,34 @@ export const Label = styled<StylePropsT>('label', props => {
24
24
  paddingRight: 0,
25
25
  paddingBottom: 0,
26
26
  paddingLeft: 0,
27
+ };
28
+ });
29
+
30
+ export const LabelContainer = styled<StylePropsT>(
31
+ 'span',
32
+ ({$theme: {sizing}}) => ({
33
+ display: 'flex',
34
+ width: '100%',
27
35
  marginTop: sizing.scale300,
28
36
  marginRight: 0,
29
37
  marginBottom: sizing.scale300,
30
38
  marginLeft: 0,
31
- };
32
- });
39
+ }),
40
+ );
41
+
42
+ export const LabelEndEnhancer = styled<StylePropsT>(
43
+ 'span',
44
+ ({$disabled, $counterError, $theme: {colors, typography}}) => ({
45
+ ...typography.font100,
46
+ flex: 0,
47
+ width: '100%',
48
+ color: $counterError
49
+ ? colors.negative400
50
+ : $disabled
51
+ ? colors.contentSecondary
52
+ : colors.contentPrimary,
53
+ }),
54
+ );
33
55
 
34
56
  export const Caption = styled<StylePropsT>('div', props => {
35
57
  const {
@@ -13,15 +13,20 @@ export type FormControlStateT = {|
13
13
  captionId: string,
14
14
  |};
15
15
 
16
+ export type OverridesT = {
17
+ /** Customizes the label element. */
18
+ Label?: OverrideT,
19
+ /** Customizes the label end enhancer element. */
20
+ LabelEndEnhancer?: OverrideT,
21
+ /** Customizes the label container element. */
22
+ LabelContainer?: OverrideT,
23
+ /** Customizes the caption element. */
24
+ Caption?: OverrideT,
25
+ /** Customizes the container element. */
26
+ ControlContainer?: OverrideT,
27
+ };
16
28
  export type FormControlPropsT = {
17
- overrides: {
18
- /** Customizes the label element. */
19
- Label?: OverrideT,
20
- /** Customizes the caption element. */
21
- Caption?: OverrideT,
22
- /** Customizes the container element. */
23
- ControlContainer?: OverrideT,
24
- },
29
+ overrides: OverridesT,
25
30
  /** A label rendered above the input field. */
26
31
  label: ?(React.Node | ((props: {}) => React.Node)),
27
32
  /** A caption rendered below the input field. */
@@ -34,6 +39,10 @@ export type FormControlPropsT = {
34
39
  positive?: React.Node | ((props: {}) => React.Node),
35
40
  /** The id of the related form element. Defaults to the id property of the child, if any. */
36
41
  htmlFor?: string,
42
+ /** Adds a label end enhancer to the label */
43
+ labelEndEnhancer?: ?(React.Node | ((props: {}) => React.Node)),
44
+ /** Adds a length counter to the form control. If your input does not have a "string" value exposed as a prop, you provide the length as an object.*/
45
+ counter?: boolean | {|length?: number, maxLength?: number, error?: boolean|},
37
46
  children: React.Node,
38
47
  };
39
48
 
@@ -41,6 +50,9 @@ export type StylePropsT = {
41
50
  $disabled?: boolean,
42
51
  $error?: boolean,
43
52
  $positive?: boolean,
53
+ $length?: number,
54
+ $maxLength?: number,
55
+ $counterError?: boolean,
44
56
  };
45
57
 
46
58
  declare var __DEV__: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "baseui",
3
- "version": "10.9.0",
3
+ "version": "10.10.0",
4
4
  "description": "A React Component library implementing the Base design language",
5
5
  "keywords": [
6
6
  "react",
@@ -193,7 +193,7 @@
193
193
  "dependencies": {
194
194
  "@date-io/date-fns": "^2.6.2",
195
195
  "card-validator": "^6.2.0",
196
- "d3": "^7.3.0",
196
+ "d3": "^6.7.0",
197
197
  "date-fns": "^2.6.0",
198
198
  "date-fns-tz": "^1.2.2",
199
199
  "glob": "^7.1.6",
@@ -535,7 +535,7 @@ var PopoverInner = /*#__PURE__*/function (_React$Component) {
535
535
  crossFrame: false,
536
536
  focusOptions: this.props.focusOptions
537
537
  }, this.renderPopover(renderedContent)) : /*#__PURE__*/React.createElement(_reactFocusLock.MoveFocusInside, {
538
- disabled: !this.props.autoFocus && !this.state.autoFocusAfterPositioning
538
+ disabled: !this.props.autoFocus || !this.state.autoFocusAfterPositioning
539
539
  }, this.renderPopover(renderedContent)))));
540
540
  } else {
541
541
  rendered.push( /*#__PURE__*/React.createElement(_styledComponents.Hidden, {
@@ -486,7 +486,7 @@ class PopoverInner extends React.Component<
486
486
  ) : (
487
487
  <MoveFocusInside
488
488
  disabled={
489
- !this.props.autoFocus &&
489
+ !this.props.autoFocus ||
490
490
  !this.state.autoFocusAfterPositioning
491
491
  }
492
492
  >
@@ -95,7 +95,7 @@ var TimezonePicker = /*#__PURE__*/function (_React$Component) {
95
95
  try {
96
96
  var offset = (0, _dateFnsTz.getTimezoneOffset)(zoneName, compareDate) / 3600000;
97
97
  var offsetFormatted = "".concat(offset >= 0 ? '+' : '-').concat(Math.abs(offset));
98
- var label = "(GMT".concat(offsetFormatted, ") ").concat(zoneName.replace('_', ' '));
98
+ var label = "(GMT".concat(offsetFormatted, ") ").concat(zoneName.replace(/_/g, ' '));
99
99
 
100
100
  if (_this.props.includeAbbreviations) {
101
101
  var abbreviation = (0, _dateFnsTz.format)(compareDate, 'zzz', {
@@ -107,10 +107,12 @@ var TimezonePicker = /*#__PURE__*/function (_React$Component) {
107
107
  }
108
108
  }
109
109
 
110
+ var offsetMinutes = offset * 60;
110
111
  timezones.push({
111
112
  id: zoneName,
112
113
  label: label,
113
- offset: offset
114
+ // offset output is in minutes, difference of UTC and this zone (negative for hours ahead of UTC, positive for hours behind)
115
+ offset: offsetMinutes === 0 ? 0 : offsetMinutes * -1
114
116
  });
115
117
  } catch (error) {
116
118
  // Ignores timezones that are not available within a user's browser/operating system
@@ -64,7 +64,7 @@ class TimezonePicker extends React.Component<
64
64
  const offset = getTimezoneOffset(zoneName, compareDate) / 3_600_000;
65
65
 
66
66
  const offsetFormatted = `${offset >= 0 ? '+' : '-'}${Math.abs(offset)}`;
67
- let label = `(GMT${offsetFormatted}) ${zoneName.replace('_', ' ')}`;
67
+ let label = `(GMT${offsetFormatted}) ${zoneName.replace(/_/g, ' ')}`;
68
68
 
69
69
  if (this.props.includeAbbreviations) {
70
70
  const abbreviation = format(compareDate, 'zzz', {timeZone: zoneName});
@@ -73,10 +73,13 @@ class TimezonePicker extends React.Component<
73
73
  }
74
74
  }
75
75
 
76
+ const offsetMinutes = offset * 60;
77
+
76
78
  timezones.push({
77
79
  id: zoneName,
78
80
  label,
79
- offset,
81
+ // offset output is in minutes, difference of UTC and this zone (negative for hours ahead of UTC, positive for hours behind)
82
+ offset: offsetMinutes === 0 ? 0 : offsetMinutes * -1,
80
83
  });
81
84
  } catch (error) {
82
85
  // Ignores timezones that are not available within a user's browser/operating system
@@ -22,6 +22,11 @@ export type TimezonePickerStateT = {
22
22
  export type TimezoneT = {
23
23
  id: string,
24
24
  label: string,
25
+ /**
26
+ * The difference, in minutes, between a UTC date, and a date in the indicated time zone.
27
+ * Positive values indicate hours behind UTC, negative values indicate hours ahead.
28
+ * This aligns with Date.getTimezoneOffset()
29
+ */
25
30
  offset: number,
26
31
  };
27
32
  export type TimezonePickerPropsT = {