carbon-react 106.2.1 → 106.3.1

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.
@@ -76,7 +76,7 @@ function findMatchWithNoSeparators(valueString, formatString) {
76
76
  const valueArray = makeSeparatedValues(indexArray, valueString);
77
77
 
78
78
  if (checkForCompleteMatch(formatArray, valueArray)) {
79
- return [formatArray.join("."), valueArray.join(".")];
79
+ return [formatArray.join(" "), valueArray.join(" ")];
80
80
  }
81
81
 
82
82
  return null;
@@ -119,8 +119,10 @@ const DateInput = ({
119
119
 
120
120
  if (isDateValid(selectedDays)) {
121
121
  event = buildCustomEvent(ev);
122
+ const currentValue = checkISOFormatAndLength(value) ? formattedValue(format, parseISODate(value)) : value;
123
+ const [, matchedValue] = findMatchedFormatAndValue(currentValue, formats);
122
124
 
123
- if (formattedValue(format, selectedDays) !== value) {
125
+ if (formattedValue(format, selectedDays) !== matchedValue) {
124
126
  onChange(event);
125
127
  }
126
128
  } else {
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import Modal, { ModalProps } from "../modal/modal";
2
+ import { ModalProps } from "../modal/modal";
3
3
 
4
4
  export interface DialogFullScreenProps extends ModalProps {
5
5
  /** Prop to specify the aria-describedby property of the DialogFullscreen component */
@@ -18,7 +18,7 @@ export interface DialogFullScreenProps extends ModalProps {
18
18
  /** Child elements */
19
19
  children?: React.ReactNode;
20
20
  /** Reference to the scrollable content element */
21
- contentRef:
21
+ contentRef?:
22
22
  | React.MutableRefObject<HTMLElement>
23
23
  | (() => React.MutableRefObject<HTMLElement>);
24
24
  /** Disables auto focus functionality on child elements */
@@ -1,5 +1,5 @@
1
1
  export default ProgressTracker;
2
- declare function ProgressTracker({ "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, "aria-valuenow": ariaValueNow, "aria-valuemin": ariaValueMin, "aria-valuemax": ariaValueMax, "aria-valuetext": ariaValueText, size, progress, showDefaultLabels, currentProgressLabel, maxProgressLabel, orientation, direction, labelsPosition, ...rest }: {
2
+ declare function ProgressTracker({ "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, "aria-valuenow": ariaValueNow, "aria-valuemin": ariaValueMin, "aria-valuemax": ariaValueMax, "aria-valuetext": ariaValueText, size, length, progress, showDefaultLabels, currentProgressLabel, maxProgressLabel, orientation, direction, labelsPosition, ...rest }: {
3
3
  [x: string]: any;
4
4
  "aria-label"?: string | undefined;
5
5
  "aria-describedby": any;
@@ -8,6 +8,7 @@ declare function ProgressTracker({ "aria-label": ariaLabel, "aria-describedby":
8
8
  "aria-valuemax": any;
9
9
  "aria-valuetext": any;
10
10
  size?: string | undefined;
11
+ length?: string | undefined;
11
12
  progress?: number | undefined;
12
13
  showDefaultLabels?: boolean | undefined;
13
14
  currentProgressLabel: any;
@@ -34,6 +35,8 @@ declare namespace ProgressTracker {
34
35
  "aria-valuetext": PropTypes.Requireable<string>;
35
36
  /** Size of the progress bar. */
36
37
  size: PropTypes.Requireable<string>;
38
+ /** Length of the progress bar, any valid css string. */
39
+ length: PropTypes.Requireable<string>;
37
40
  /** Current progress (percentage). */
38
41
  progress: PropTypes.Requireable<number>;
39
42
  /** Flag to control whether the default value labels (as percentages) should be rendered. */
@@ -1,11 +1,12 @@
1
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); }
2
2
 
3
- import React from "react";
3
+ import React, { useCallback, useLayoutEffect, useRef, useState } from "react";
4
4
  import PropTypes from "prop-types";
5
5
  import styledSystemPropTypes from "@styled-system/prop-types";
6
6
  import tagComponent from "../../__internal__/utils/helpers/tags";
7
7
  import { filterStyledSystemMarginProps } from "../../style/utils";
8
8
  import { StyledProgressBar, InnerBar, StyledValuesLabel, StyledProgressTracker, StyledValue } from "./progress-tracker.style";
9
+ import useResizeObserver from "../../hooks/__internal__/useResizeObserver";
9
10
  const marginPropTypes = filterStyledSystemMarginProps(styledSystemPropTypes.space);
10
11
 
11
12
  const ProgressTracker = ({
@@ -16,6 +17,7 @@ const ProgressTracker = ({
16
17
  "aria-valuemax": ariaValueMax,
17
18
  "aria-valuetext": ariaValueText,
18
19
  size = "medium",
20
+ length = "256px",
19
21
  progress = 0,
20
22
  showDefaultLabels = false,
21
23
  currentProgressLabel,
@@ -25,8 +27,23 @@ const ProgressTracker = ({
25
27
  labelsPosition,
26
28
  ...rest
27
29
  }) => {
30
+ const barRef = useRef();
31
+ const [barLength, setBarLength] = useState(0);
28
32
  const isVertical = orientation === "vertical";
29
33
  const prefixLabels = !isVertical && labelsPosition !== "bottom" || isVertical && labelsPosition === "left";
34
+ const updateBarLength = useCallback(() => {
35
+ if (orientation === "horizontal") {
36
+ setBarLength(`${barRef.current.offsetWidth}px`);
37
+ } else {
38
+ setBarLength(`${barRef.current.offsetHeight}px`);
39
+ }
40
+ }, [barRef, orientation]);
41
+ useLayoutEffect(() => {
42
+ updateBarLength();
43
+ }, [barRef, orientation, updateBarLength]);
44
+ useResizeObserver(barRef, () => {
45
+ updateBarLength();
46
+ });
30
47
 
31
48
  const renderValueLabels = () => {
32
49
  if (!showDefaultLabels && !currentProgressLabel && !maxProgressLabel) {
@@ -53,6 +70,7 @@ const ProgressTracker = ({
53
70
 
54
71
  return /*#__PURE__*/React.createElement(StyledProgressTracker, _extends({
55
72
  size: size,
73
+ length: length,
56
74
  isVertical: isVertical
57
75
  }, rest, tagComponent("progress-bar", rest), {
58
76
  role: "progressbar",
@@ -65,10 +83,12 @@ const ProgressTracker = ({
65
83
  }), prefixLabels && renderValueLabels(), /*#__PURE__*/React.createElement(StyledProgressBar, {
66
84
  direction: isVertical ? direction : undefined,
67
85
  isVertical: isVertical,
68
- size: size
86
+ size: size,
87
+ ref: barRef
69
88
  }, /*#__PURE__*/React.createElement(InnerBar, {
70
89
  isVertical: isVertical,
71
90
  size: size,
91
+ length: barLength,
72
92
  progress: progress
73
93
  })), !prefixLabels && renderValueLabels());
74
94
  };
@@ -98,6 +118,9 @@ ProgressTracker.propTypes = { ...marginPropTypes,
98
118
  /** Size of the progress bar. */
99
119
  size: PropTypes.oneOf(["small", "medium", "large"]),
100
120
 
121
+ /** Length of the progress bar, any valid css string. */
122
+ length: PropTypes.string,
123
+
101
124
  /** Current progress (percentage). */
102
125
  progress: PropTypes.number,
103
126
 
@@ -1,2 +1 @@
1
- export const OUTER_TRACKER_LENGTH: "256px";
2
1
  export const PROGRESS_TRACKER_SIZES: string[];
@@ -1,2 +1,2 @@
1
- export const OUTER_TRACKER_LENGTH = "256px";
1
+ /* eslint-disable import/prefer-default-export */
2
2
  export const PROGRESS_TRACKER_SIZES = ["small", "medium", "large"];
@@ -1,6 +1,6 @@
1
1
  import { MarginProps } from "styled-system";
2
2
 
3
- export interface ProgressBarProps extends MarginProps {
3
+ export interface ProgressTrackerProps extends MarginProps {
4
4
  /** Specifies an aria-label to the component */
5
5
  "aria-label"?: string;
6
6
  /** Specifies the aria-describedby for the component */
@@ -16,6 +16,8 @@ export interface ProgressBarProps extends MarginProps {
16
16
  "aria-valuetext"?: string;
17
17
  /** Size of the progressBar. */
18
18
  size?: "small" | "medium" | "large";
19
+ /** Length of the progress bar, any valid css string. */
20
+ length?: string;
19
21
  /** Current progress (percentage). */
20
22
  progress?: number;
21
23
  /** Flag to control whether the default value labels (as percentages) should be rendered. */
@@ -35,6 +37,6 @@ export interface ProgressBarProps extends MarginProps {
35
37
  labelsPosition?: "top" | "bottom" | "left" | "right";
36
38
  }
37
39
 
38
- declare function ProgressBar(props: ProgressBarProps): JSX.Element;
40
+ declare function ProgressTracker(props: ProgressTrackerProps): JSX.Element;
39
41
 
40
- export default ProgressBar;
42
+ export default ProgressTracker;
@@ -2,20 +2,21 @@ import styled, { css } from "styled-components";
2
2
  import PropTypes from "prop-types";
3
3
  import { margin } from "styled-system";
4
4
  import baseTheme from "../../style/themes/base";
5
- import { OUTER_TRACKER_LENGTH, PROGRESS_TRACKER_SIZES } from "./progress-tracker.config";
5
+ import { PROGRESS_TRACKER_SIZES } from "./progress-tracker.config";
6
6
  const StyledProgressTracker = styled.div`
7
7
  ${margin}
8
8
  text-align: center;
9
9
  white-space: nowrap;
10
10
 
11
11
  ${({
12
- isVertical
12
+ isVertical,
13
+ length
13
14
  }) => css`
14
15
  ${!isVertical && `
15
- width: ${OUTER_TRACKER_LENGTH};
16
+ width: ${length};
16
17
  `}
17
18
  ${isVertical && `
18
- height: ${OUTER_TRACKER_LENGTH};
19
+ height: ${length};
19
20
  display: flex;
20
21
  `}
21
22
  `}
@@ -94,19 +95,20 @@ const InnerBar = styled.span`
94
95
  ${({
95
96
  isVertical,
96
97
  progress,
97
- size
98
+ size,
99
+ length
98
100
  }) => css`
99
101
  position: absolute;
100
102
  left: 0;
101
103
  background-color: ${getInnerBarColour(progress)};
102
104
 
103
105
  ${!isVertical && css`
104
- width: calc(${OUTER_TRACKER_LENGTH} * ${progress / 100});
106
+ width: calc(${length} * ${progress / 100});
105
107
  min-width: 2px;
106
108
  height: ${getHeight(size)};
107
109
  `}
108
110
  ${isVertical && css`
109
- height: calc(${OUTER_TRACKER_LENGTH} * ${progress / 100});
111
+ height: calc(${length} * ${progress / 100});
110
112
  min-height: 2px;
111
113
  width: ${getHeight(size)};
112
114
  `}
@@ -97,7 +97,7 @@ function findMatchWithNoSeparators(valueString, formatString) {
97
97
  const valueArray = makeSeparatedValues(indexArray, valueString);
98
98
 
99
99
  if (checkForCompleteMatch(formatArray, valueArray)) {
100
- return [formatArray.join("."), valueArray.join(".")];
100
+ return [formatArray.join(" "), valueArray.join(" ")];
101
101
  }
102
102
 
103
103
  return null;
@@ -144,8 +144,10 @@ const DateInput = ({
144
144
 
145
145
  if ((0, _utils.isDateValid)(selectedDays)) {
146
146
  event = buildCustomEvent(ev);
147
+ const currentValue = (0, _utils.checkISOFormatAndLength)(value) ? (0, _utils.formattedValue)(format, (0, _utils.parseISODate)(value)) : value;
148
+ const [, matchedValue] = (0, _utils.findMatchedFormatAndValue)(currentValue, formats);
147
149
 
148
- if ((0, _utils.formattedValue)(format, selectedDays) !== value) {
150
+ if ((0, _utils.formattedValue)(format, selectedDays) !== matchedValue) {
149
151
  onChange(event);
150
152
  }
151
153
  } else {
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import Modal, { ModalProps } from "../modal/modal";
2
+ import { ModalProps } from "../modal/modal";
3
3
 
4
4
  export interface DialogFullScreenProps extends ModalProps {
5
5
  /** Prop to specify the aria-describedby property of the DialogFullscreen component */
@@ -18,7 +18,7 @@ export interface DialogFullScreenProps extends ModalProps {
18
18
  /** Child elements */
19
19
  children?: React.ReactNode;
20
20
  /** Reference to the scrollable content element */
21
- contentRef:
21
+ contentRef?:
22
22
  | React.MutableRefObject<HTMLElement>
23
23
  | (() => React.MutableRefObject<HTMLElement>);
24
24
  /** Disables auto focus functionality on child elements */
@@ -1,5 +1,5 @@
1
1
  export default ProgressTracker;
2
- declare function ProgressTracker({ "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, "aria-valuenow": ariaValueNow, "aria-valuemin": ariaValueMin, "aria-valuemax": ariaValueMax, "aria-valuetext": ariaValueText, size, progress, showDefaultLabels, currentProgressLabel, maxProgressLabel, orientation, direction, labelsPosition, ...rest }: {
2
+ declare function ProgressTracker({ "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, "aria-valuenow": ariaValueNow, "aria-valuemin": ariaValueMin, "aria-valuemax": ariaValueMax, "aria-valuetext": ariaValueText, size, length, progress, showDefaultLabels, currentProgressLabel, maxProgressLabel, orientation, direction, labelsPosition, ...rest }: {
3
3
  [x: string]: any;
4
4
  "aria-label"?: string | undefined;
5
5
  "aria-describedby": any;
@@ -8,6 +8,7 @@ declare function ProgressTracker({ "aria-label": ariaLabel, "aria-describedby":
8
8
  "aria-valuemax": any;
9
9
  "aria-valuetext": any;
10
10
  size?: string | undefined;
11
+ length?: string | undefined;
11
12
  progress?: number | undefined;
12
13
  showDefaultLabels?: boolean | undefined;
13
14
  currentProgressLabel: any;
@@ -34,6 +35,8 @@ declare namespace ProgressTracker {
34
35
  "aria-valuetext": PropTypes.Requireable<string>;
35
36
  /** Size of the progress bar. */
36
37
  size: PropTypes.Requireable<string>;
38
+ /** Length of the progress bar, any valid css string. */
39
+ length: PropTypes.Requireable<string>;
37
40
  /** Current progress (percentage). */
38
41
  progress: PropTypes.Requireable<number>;
39
42
  /** Flag to control whether the default value labels (as percentages) should be rendered. */
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = void 0;
7
7
 
8
- var _react = _interopRequireDefault(require("react"));
8
+ var _react = _interopRequireWildcard(require("react"));
9
9
 
10
10
  var _propTypes = _interopRequireDefault(require("prop-types"));
11
11
 
@@ -17,8 +17,14 @@ var _utils = require("../../style/utils");
17
17
 
18
18
  var _progressTracker = require("./progress-tracker.style");
19
19
 
20
+ var _useResizeObserver = _interopRequireDefault(require("../../hooks/__internal__/useResizeObserver"));
21
+
20
22
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
23
 
24
+ function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
25
+
26
+ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (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; }
27
+
22
28
  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
29
 
24
30
  const marginPropTypes = (0, _utils.filterStyledSystemMarginProps)(_propTypes2.default.space);
@@ -31,6 +37,7 @@ const ProgressTracker = ({
31
37
  "aria-valuemax": ariaValueMax,
32
38
  "aria-valuetext": ariaValueText,
33
39
  size = "medium",
40
+ length = "256px",
34
41
  progress = 0,
35
42
  showDefaultLabels = false,
36
43
  currentProgressLabel,
@@ -40,8 +47,23 @@ const ProgressTracker = ({
40
47
  labelsPosition,
41
48
  ...rest
42
49
  }) => {
50
+ const barRef = (0, _react.useRef)();
51
+ const [barLength, setBarLength] = (0, _react.useState)(0);
43
52
  const isVertical = orientation === "vertical";
44
53
  const prefixLabels = !isVertical && labelsPosition !== "bottom" || isVertical && labelsPosition === "left";
54
+ const updateBarLength = (0, _react.useCallback)(() => {
55
+ if (orientation === "horizontal") {
56
+ setBarLength(`${barRef.current.offsetWidth}px`);
57
+ } else {
58
+ setBarLength(`${barRef.current.offsetHeight}px`);
59
+ }
60
+ }, [barRef, orientation]);
61
+ (0, _react.useLayoutEffect)(() => {
62
+ updateBarLength();
63
+ }, [barRef, orientation, updateBarLength]);
64
+ (0, _useResizeObserver.default)(barRef, () => {
65
+ updateBarLength();
66
+ });
45
67
 
46
68
  const renderValueLabels = () => {
47
69
  if (!showDefaultLabels && !currentProgressLabel && !maxProgressLabel) {
@@ -68,6 +90,7 @@ const ProgressTracker = ({
68
90
 
69
91
  return /*#__PURE__*/_react.default.createElement(_progressTracker.StyledProgressTracker, _extends({
70
92
  size: size,
93
+ length: length,
71
94
  isVertical: isVertical
72
95
  }, rest, (0, _tags.default)("progress-bar", rest), {
73
96
  role: "progressbar",
@@ -80,10 +103,12 @@ const ProgressTracker = ({
80
103
  }), prefixLabels && renderValueLabels(), /*#__PURE__*/_react.default.createElement(_progressTracker.StyledProgressBar, {
81
104
  direction: isVertical ? direction : undefined,
82
105
  isVertical: isVertical,
83
- size: size
106
+ size: size,
107
+ ref: barRef
84
108
  }, /*#__PURE__*/_react.default.createElement(_progressTracker.InnerBar, {
85
109
  isVertical: isVertical,
86
110
  size: size,
111
+ length: barLength,
87
112
  progress: progress
88
113
  })), !prefixLabels && renderValueLabels());
89
114
  };
@@ -113,6 +138,9 @@ ProgressTracker.propTypes = { ...marginPropTypes,
113
138
  /** Size of the progress bar. */
114
139
  size: _propTypes.default.oneOf(["small", "medium", "large"]),
115
140
 
141
+ /** Length of the progress bar, any valid css string. */
142
+ length: _propTypes.default.string,
143
+
116
144
  /** Current progress (percentage). */
117
145
  progress: _propTypes.default.number,
118
146
 
@@ -1,2 +1 @@
1
- export const OUTER_TRACKER_LENGTH: "256px";
2
1
  export const PROGRESS_TRACKER_SIZES: string[];
@@ -3,8 +3,8 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.PROGRESS_TRACKER_SIZES = exports.OUTER_TRACKER_LENGTH = void 0;
7
- const OUTER_TRACKER_LENGTH = "256px";
8
- exports.OUTER_TRACKER_LENGTH = OUTER_TRACKER_LENGTH;
6
+ exports.PROGRESS_TRACKER_SIZES = void 0;
7
+
8
+ /* eslint-disable import/prefer-default-export */
9
9
  const PROGRESS_TRACKER_SIZES = ["small", "medium", "large"];
10
10
  exports.PROGRESS_TRACKER_SIZES = PROGRESS_TRACKER_SIZES;
@@ -1,6 +1,6 @@
1
1
  import { MarginProps } from "styled-system";
2
2
 
3
- export interface ProgressBarProps extends MarginProps {
3
+ export interface ProgressTrackerProps extends MarginProps {
4
4
  /** Specifies an aria-label to the component */
5
5
  "aria-label"?: string;
6
6
  /** Specifies the aria-describedby for the component */
@@ -16,6 +16,8 @@ export interface ProgressBarProps extends MarginProps {
16
16
  "aria-valuetext"?: string;
17
17
  /** Size of the progressBar. */
18
18
  size?: "small" | "medium" | "large";
19
+ /** Length of the progress bar, any valid css string. */
20
+ length?: string;
19
21
  /** Current progress (percentage). */
20
22
  progress?: number;
21
23
  /** Flag to control whether the default value labels (as percentages) should be rendered. */
@@ -35,6 +37,6 @@ export interface ProgressBarProps extends MarginProps {
35
37
  labelsPosition?: "top" | "bottom" | "left" | "right";
36
38
  }
37
39
 
38
- declare function ProgressBar(props: ProgressBarProps): JSX.Element;
40
+ declare function ProgressTracker(props: ProgressTrackerProps): JSX.Element;
39
41
 
40
- export default ProgressBar;
42
+ export default ProgressTracker;
@@ -27,13 +27,14 @@ const StyledProgressTracker = _styledComponents.default.div`
27
27
  white-space: nowrap;
28
28
 
29
29
  ${({
30
- isVertical
30
+ isVertical,
31
+ length
31
32
  }) => (0, _styledComponents.css)`
32
33
  ${!isVertical && `
33
- width: ${_progressTracker.OUTER_TRACKER_LENGTH};
34
+ width: ${length};
34
35
  `}
35
36
  ${isVertical && `
36
- height: ${_progressTracker.OUTER_TRACKER_LENGTH};
37
+ height: ${length};
37
38
  display: flex;
38
39
  `}
39
40
  `}
@@ -116,19 +117,20 @@ const InnerBar = _styledComponents.default.span`
116
117
  ${({
117
118
  isVertical,
118
119
  progress,
119
- size
120
+ size,
121
+ length
120
122
  }) => (0, _styledComponents.css)`
121
123
  position: absolute;
122
124
  left: 0;
123
125
  background-color: ${getInnerBarColour(progress)};
124
126
 
125
127
  ${!isVertical && (0, _styledComponents.css)`
126
- width: calc(${_progressTracker.OUTER_TRACKER_LENGTH} * ${progress / 100});
128
+ width: calc(${length} * ${progress / 100});
127
129
  min-width: 2px;
128
130
  height: ${getHeight(size)};
129
131
  `}
130
132
  ${isVertical && (0, _styledComponents.css)`
131
- height: calc(${_progressTracker.OUTER_TRACKER_LENGTH} * ${progress / 100});
133
+ height: calc(${length} * ${progress / 100});
132
134
  min-height: 2px;
133
135
  width: ${getHeight(size)};
134
136
  `}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "carbon-react",
3
- "version": "106.2.1",
3
+ "version": "106.3.1",
4
4
  "description": "A library of reusable React components for easily building user interfaces.",
5
5
  "engineStrict": true,
6
6
  "engines": {