@pareto-engineering/design-system 5.0.0 → 5.0.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.
Files changed (112) hide show
  1. package/dist/cjs/a/{AreaChart → Charts/AreaChart}/AreaChart.js +89 -63
  2. package/dist/cjs/a/Charts/AreaChart/styles.scss +48 -0
  3. package/dist/cjs/a/Charts/BarChart/BarChart.js +135 -0
  4. package/dist/cjs/a/Charts/BarChart/index.js +13 -0
  5. package/dist/cjs/a/Charts/BarChart/styles.scss +48 -0
  6. package/dist/cjs/a/Charts/Common/CustomLegend/CustomLegend.js +69 -0
  7. package/dist/cjs/a/Charts/Common/CustomLegend/index.js +13 -0
  8. package/dist/cjs/a/Charts/Common/CustomLegend/styles.scss +40 -0
  9. package/dist/cjs/a/Charts/Common/CustomTooltipContent/CustomTooltipContent.js +86 -0
  10. package/dist/cjs/a/Charts/Common/CustomTooltipContent/index.js +13 -0
  11. package/dist/cjs/a/Charts/Common/CustomTooltipContent/styles.scss +22 -0
  12. package/dist/cjs/a/Charts/Common/YLabelsDropDown/YlabelsDropDown.js +98 -0
  13. package/dist/cjs/a/Charts/Common/YLabelsDropDown/index.js +13 -0
  14. package/dist/cjs/a/Charts/Common/YLabelsDropDown/styles.scss +88 -0
  15. package/dist/cjs/a/Charts/Common/index.js +26 -0
  16. package/dist/cjs/a/Charts/index.js +19 -0
  17. package/dist/cjs/a/Tooltip/styles.scss +1 -1
  18. package/dist/cjs/a/index.js +8 -2
  19. package/dist/cjs/f/FormInput/FormInput.js +6 -0
  20. package/dist/cjs/f/fields/FileUpload/FileUpload.js +18 -4
  21. package/dist/cjs/f/fields/LatexPreviewInput/LatexPreviewInput.js +78 -0
  22. package/dist/cjs/f/fields/LatexPreviewInput/convertLatexToHtml.js +46 -0
  23. package/dist/cjs/f/fields/LatexPreviewInput/index.js +20 -0
  24. package/dist/cjs/f/fields/LatexPreviewInput/styles.scss +24 -0
  25. package/dist/cjs/f/fields/index.js +13 -0
  26. package/dist/cjs/g/FormBuilder/FormBuilder.js +3 -6
  27. package/dist/cjs/g/FormBuilder/common/Builder/Builder.js +1 -3
  28. package/dist/cjs/g/FormBuilder/common/Builder/common/InputBuilder/InputBuilder.js +5 -7
  29. package/dist/cjs/g/FormBuilder/common/Builder/common/Section/Section.js +2 -4
  30. package/dist/cjs/g/FormBuilder/common/Renderer/Renderer.js +2 -4
  31. package/dist/cjs/g/FormBuilder/common/Renderer/common/Section/Section.js +2 -10
  32. package/dist/cjs/utils/formatting.js +111 -0
  33. package/dist/cjs/utils/index.js +20 -1
  34. package/dist/es/a/{AreaChart → Charts/AreaChart}/AreaChart.js +88 -59
  35. package/dist/es/a/Charts/AreaChart/styles.scss +48 -0
  36. package/dist/es/a/Charts/BarChart/BarChart.js +126 -0
  37. package/dist/es/a/Charts/BarChart/index.js +1 -0
  38. package/dist/es/a/Charts/BarChart/styles.scss +48 -0
  39. package/dist/es/a/Charts/Common/CustomLegend/CustomLegend.js +59 -0
  40. package/dist/es/a/Charts/Common/CustomLegend/index.js +1 -0
  41. package/dist/es/a/Charts/Common/CustomLegend/styles.scss +40 -0
  42. package/dist/es/a/Charts/Common/CustomTooltipContent/CustomTooltipContent.js +76 -0
  43. package/dist/es/a/Charts/Common/CustomTooltipContent/index.js +1 -0
  44. package/dist/es/a/Charts/Common/CustomTooltipContent/styles.scss +22 -0
  45. package/dist/es/a/Charts/Common/YLabelsDropDown/YlabelsDropDown.js +88 -0
  46. package/dist/es/a/Charts/Common/YLabelsDropDown/index.js +1 -0
  47. package/dist/es/a/Charts/Common/YLabelsDropDown/styles.scss +88 -0
  48. package/dist/es/a/Charts/Common/index.js +3 -0
  49. package/dist/es/a/Charts/index.js +2 -0
  50. package/dist/es/a/Tooltip/styles.scss +1 -1
  51. package/dist/es/a/index.js +1 -1
  52. package/dist/es/f/FormInput/FormInput.js +7 -1
  53. package/dist/es/f/fields/FileUpload/FileUpload.js +18 -4
  54. package/dist/es/f/fields/LatexPreviewInput/LatexPreviewInput.js +70 -0
  55. package/dist/es/f/fields/LatexPreviewInput/convertLatexToHtml.js +31 -0
  56. package/dist/es/f/fields/LatexPreviewInput/index.js +3 -0
  57. package/dist/es/f/fields/LatexPreviewInput/styles.scss +24 -0
  58. package/dist/es/f/fields/index.js +1 -0
  59. package/dist/es/g/FormBuilder/FormBuilder.js +3 -6
  60. package/dist/es/g/FormBuilder/common/Builder/Builder.js +1 -3
  61. package/dist/es/g/FormBuilder/common/Builder/common/InputBuilder/InputBuilder.js +5 -7
  62. package/dist/es/g/FormBuilder/common/Builder/common/Section/Section.js +2 -4
  63. package/dist/es/g/FormBuilder/common/Renderer/Renderer.js +2 -4
  64. package/dist/es/g/FormBuilder/common/Renderer/common/Section/Section.js +32 -42
  65. package/dist/es/utils/formatting.js +102 -0
  66. package/dist/es/utils/index.js +2 -1
  67. package/jest.config.js +3 -0
  68. package/package.json +7 -3
  69. package/src/stories/a/BarChart.stories.jsx +89 -0
  70. package/src/ui/a/{AreaChart → Charts/AreaChart}/AreaChart.jsx +109 -54
  71. package/src/ui/a/Charts/AreaChart/styles.scss +48 -0
  72. package/src/ui/a/Charts/BarChart/BarChart.jsx +165 -0
  73. package/src/ui/a/Charts/BarChart/index.js +1 -0
  74. package/src/ui/a/Charts/BarChart/styles.scss +48 -0
  75. package/src/ui/a/Charts/Common/CustomLegend/CustomLegend.jsx +84 -0
  76. package/src/ui/a/Charts/Common/CustomLegend/index.js +1 -0
  77. package/src/ui/a/Charts/Common/CustomLegend/styles.scss +40 -0
  78. package/src/ui/a/Charts/Common/CustomTooltipContent/CustomTooltipContent.jsx +105 -0
  79. package/src/ui/a/Charts/Common/CustomTooltipContent/index.js +1 -0
  80. package/src/ui/a/Charts/Common/CustomTooltipContent/styles.scss +22 -0
  81. package/src/ui/a/Charts/Common/YLabelsDropDown/YlabelsDropDown.jsx +121 -0
  82. package/src/ui/a/Charts/Common/YLabelsDropDown/index.js +1 -0
  83. package/src/ui/a/Charts/Common/YLabelsDropDown/styles.scss +88 -0
  84. package/src/ui/a/Charts/Common/index.js +3 -0
  85. package/src/ui/a/Charts/index.js +2 -0
  86. package/src/ui/a/Tooltip/styles.scss +1 -1
  87. package/src/ui/a/index.js +1 -1
  88. package/src/ui/f/FormInput/FormInput.jsx +11 -0
  89. package/src/ui/f/fields/FileUpload/FileUpload.jsx +24 -4
  90. package/src/ui/f/fields/LatexPreviewInput/LatexPreviewInput.jsx +91 -0
  91. package/src/ui/f/fields/LatexPreviewInput/convertLatexToHtml.jsx +38 -0
  92. package/src/ui/f/fields/LatexPreviewInput/index.js +3 -0
  93. package/src/ui/f/fields/LatexPreviewInput/styles.scss +24 -0
  94. package/src/ui/f/fields/index.js +4 -0
  95. package/src/ui/g/FormBuilder/FormBuilder.jsx +0 -3
  96. package/src/ui/g/FormBuilder/common/Builder/Builder.jsx +0 -2
  97. package/src/ui/g/FormBuilder/common/Builder/common/InputBuilder/InputBuilder.jsx +4 -7
  98. package/src/ui/g/FormBuilder/common/Builder/common/Section/Section.jsx +0 -2
  99. package/src/ui/g/FormBuilder/common/Renderer/Renderer.jsx +0 -2
  100. package/src/ui/g/FormBuilder/common/Renderer/common/Section/Section.jsx +49 -64
  101. package/src/ui/utils/formatting.js +125 -0
  102. package/src/ui/utils/index.js +1 -0
  103. package/tests/__snapshots__/Storyshots.test.js.snap +1257 -62
  104. package/tests/emptyMock.js +3 -0
  105. package/tests/mockTextEncoder.js +7 -0
  106. package/tests/test-setup.js +7 -0
  107. package/dist/cjs/a/AreaChart/styles.scss +0 -89
  108. package/dist/es/a/AreaChart/styles.scss +0 -89
  109. package/src/ui/a/AreaChart/styles.scss +0 -89
  110. /package/dist/cjs/a/{AreaChart → Charts/AreaChart}/index.js +0 -0
  111. /package/dist/es/a/{AreaChart → Charts/AreaChart}/index.js +0 -0
  112. /package/src/ui/a/{AreaChart → Charts/AreaChart}/index.js +0 -0
@@ -0,0 +1,70 @@
1
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
2
+ /* @pareto-engineering/generator-front 1.0.12 */
3
+ import * as React from 'react';
4
+ import { memo, useMemo } from 'react';
5
+ import PropTypes from 'prop-types';
6
+ import styleNames from '@pareto-engineering/bem/exports';
7
+ import { useFormikContext } from 'formik';
8
+ import convertLatexToHtml from "./convertLatexToHtml";
9
+ import { TextareaInput } from "../TextareaInput";
10
+ import "./styles.scss";
11
+
12
+ // Local Definitions
13
+
14
+ const baseClassName = styleNames.base;
15
+ const componentClassName = 'latex-preview-input';
16
+
17
+ /**
18
+ * This is the component description.
19
+ */
20
+ const LatexPreviewInput = ({
21
+ id,
22
+ className,
23
+ userClassName,
24
+ disabled,
25
+ style,
26
+ ...otherProps
27
+ }) => {
28
+ const {
29
+ name
30
+ } = otherProps;
31
+ const {
32
+ values
33
+ } = useFormikContext();
34
+ const LatexPreview = useMemo(() => convertLatexToHtml(values[name]), [values[name]]);
35
+ return /*#__PURE__*/React.createElement("div", {
36
+ id: id,
37
+ className: [baseClassName, componentClassName, userClassName, 'form-input'].filter(e => e).join(' '),
38
+ style: style
39
+ }, /*#__PURE__*/React.createElement(TextareaInput, _extends({
40
+ className: "preview-child",
41
+ disabled: disabled
42
+ }, otherProps)), /*#__PURE__*/React.createElement("div", {
43
+ className: "latex-container preview-child",
44
+ dangerouslySetInnerHTML: {
45
+ __html: LatexPreview
46
+ }
47
+ }));
48
+ };
49
+ LatexPreviewInput.propTypes = {
50
+ /**
51
+ * The HTML id for this element
52
+ */
53
+ id: PropTypes.string,
54
+ /**
55
+ * The HTML class names for this element
56
+ */
57
+ className: PropTypes.string,
58
+ /**
59
+ * The React-written, css properties for this element.
60
+ */
61
+ style: PropTypes.objectOf(PropTypes.string),
62
+ /**
63
+ * Whether the Form input input should be disabled
64
+ */
65
+ disabled: PropTypes.bool
66
+ };
67
+ LatexPreviewInput.defaultProps = {
68
+ disabled: false
69
+ };
70
+ export default /*#__PURE__*/memo(LatexPreviewInput);
@@ -0,0 +1,31 @@
1
+ import * as React from 'react';
2
+ import ReactMarkdown from 'react-markdown';
3
+ import RemarkMathPlugin from 'remark-math';
4
+ import { MathJax, MathJaxContext } from 'better-react-mathjax';
5
+ import rehypeMathjax from 'rehype-mathjax/svg';
6
+ import ReactDOMServer from 'react-dom/server';
7
+ const convertLatexToHtml = content => {
8
+ if (content.includes('https://forte-assets.pareto.ai/')) {
9
+ return content;
10
+ }
11
+ const processedContent = content.replaceAll(/\\\\/g, '\n\n');
12
+ const renderedContent = ReactDOMServer.renderToString(/*#__PURE__*/React.createElement(MathJaxContext, null, /*#__PURE__*/React.createElement(ReactMarkdown, {
13
+ remarkPlugins: [RemarkMathPlugin],
14
+ rehypePlugins: [rehypeMathjax],
15
+ components: {
16
+ math: ({
17
+ value
18
+ }) => /*#__PURE__*/React.createElement(MathJax.Node, {
19
+ formula: value
20
+ }),
21
+ inlineMath: ({
22
+ value
23
+ }) => /*#__PURE__*/React.createElement(MathJax.Node, {
24
+ inline: true,
25
+ formula: value
26
+ })
27
+ }
28
+ }, processedContent)));
29
+ return renderedContent;
30
+ };
31
+ export default convertLatexToHtml;
@@ -0,0 +1,3 @@
1
+ /* @pareto-engineering/generator-front 1.0.12 */
2
+ export { default as LatexPreviewInput } from "./LatexPreviewInput";
3
+ export { default as convertLatexToHtml } from "./convertLatexToHtml";
@@ -0,0 +1,24 @@
1
+ /* @pareto-engineering/generator-front 1.0.12 */
2
+
3
+ @use "@pareto-engineering/bem";
4
+
5
+ $default-margin: 1em;
6
+
7
+ .#{bem.$base}.latex-preview-input {
8
+ display: flex;
9
+ flex-direction: row;
10
+ gap: $default-margin;
11
+
12
+ > .preview-child {
13
+ flex: 1;
14
+ }
15
+
16
+ > .latex-container {
17
+ border: 1px solid var(--ui-lines);
18
+ border-radius: var(--theme-default-border-radius);
19
+ margin-top: calc($default-margin * 2.5);
20
+ max-width: 50%;
21
+ overflow: auto;
22
+ padding: 0 $default-margin;
23
+ }
24
+ }
@@ -9,4 +9,5 @@ export { Checkbox } from "./Checkbox";
9
9
  export { QueryChoices } from "./QueryChoices";
10
10
  export { LinkInput } from "./LinkInput";
11
11
  export { EditorInput } from "./EditorInput";
12
+ export { LatexPreviewInput, convertLatexToHtml } from "./LatexPreviewInput";
12
13
  export { FileUpload, fileUploadOptions, getFileType, getFileTypeFromUrl } from "./FileUpload";
@@ -30,8 +30,7 @@ const FormBuilder = ({
30
30
  initialBuilderValues,
31
31
  fileUploadStatus,
32
32
  handleFileDelete,
33
- taskData,
34
- customInputMap
33
+ taskData
35
34
  // ...otherProps
36
35
  }) => {
37
36
  const formattedJson = JSON.stringify(taskData, null, 2);
@@ -47,8 +46,7 @@ const FormBuilder = ({
47
46
  formBuilderId: formBuilderId,
48
47
  onSave: onBuilderFormSave,
49
48
  onError: onBuilderError,
50
- validate: onBuilderValidate,
51
- customInputMap: customInputMap
49
+ validate: onBuilderValidate
52
50
  }), mode === 'render' && /*#__PURE__*/React.createElement(Renderer, {
53
51
  formData: formData,
54
52
  onSave: onRendererFormSave,
@@ -56,8 +54,7 @@ const FormBuilder = ({
56
54
  shouldSubmit: shouldSubmit,
57
55
  fileUploadStatus: fileUploadStatus,
58
56
  handleFileDelete: handleFileDelete,
59
- onFileUpload: onFileUpload,
60
- customInputMap: customInputMap
57
+ onFileUpload: onFileUpload
61
58
  }));
62
59
  };
63
60
  FormBuilder.propTypes = {
@@ -32,7 +32,6 @@ const Builder = ({
32
32
  onError,
33
33
  validate,
34
34
  formBuilderId,
35
- customInputMap,
36
35
  initialValues = {}
37
36
  // ...otherProps
38
37
  }) => {
@@ -107,8 +106,7 @@ const Builder = ({
107
106
  remove,
108
107
  values,
109
108
  setFieldValue
110
- }),
111
- customInputMap: customInputMap
109
+ })
112
110
  })), /*#__PURE__*/React.createElement("div", {
113
111
  className: "section-footer"
114
112
  }, /*#__PURE__*/React.createElement("button", {
@@ -26,8 +26,7 @@ const InputBuilder = ({
26
26
  style,
27
27
  sectionIndex,
28
28
  inputIndex,
29
- onDelete,
30
- customInputMap
29
+ onDelete
31
30
  // ...otherProps
32
31
  }) => {
33
32
  const {
@@ -54,7 +53,6 @@ const InputBuilder = ({
54
53
  const handleToggleShowSpecificFileTypes = () => {
55
54
  setFieldValue(`sections.${sectionIndex}.inputs.${inputIndex}.showSpecificFileTypes`, !input.showSpecificFileTypes);
56
55
  };
57
- const customInputTypes = customInputMap ? Object.keys(customInputMap) : [];
58
56
  return /*#__PURE__*/React.createElement("div", {
59
57
  id: id,
60
58
  className: [baseClassName, componentClassName, userClassName].filter(e => e).join(' '),
@@ -94,10 +92,10 @@ const InputBuilder = ({
94
92
  }, {
95
93
  value: 'file',
96
94
  label: 'File upload'
97
- }, ...(customInputTypes && customInputTypes.map(customInputKey => ({
98
- value: customInputKey,
99
- label: customInputMap[customInputKey].label
100
- })))]
95
+ }, {
96
+ value: 'latex-preview-input',
97
+ label: 'Textbox with LaTeX preview'
98
+ }]
101
99
  }), /*#__PURE__*/React.createElement("div", {
102
100
  className: "controls"
103
101
  }, /*#__PURE__*/React.createElement("button", {
@@ -23,8 +23,7 @@ const Section = ({
23
23
  className: userClassName,
24
24
  style,
25
25
  index,
26
- handleDeleteSection,
27
- customInputMap
26
+ handleDeleteSection
28
27
  // ...otherProps
29
28
  }) => {
30
29
  const {
@@ -56,8 +55,7 @@ const Section = ({
56
55
  sectionIndex: index,
57
56
  inputIndex: indx,
58
57
  onDelete: handleDeleteInput,
59
- onCopy: handleCopyInput,
60
- customInputMap: customInputMap
58
+ onCopy: handleCopyInput
61
59
  }),
62
60
  identifier: input.name
63
61
  }));
@@ -65,8 +65,7 @@ const Renderer = ({
65
65
  fileUploadStatus,
66
66
  handleFileDelete,
67
67
  onFileUpload,
68
- shouldUpdateInputStateInRealTime = true,
69
- customInputMap
68
+ shouldUpdateInputStateInRealTime = true
70
69
  // ...otherProps
71
70
  }) => {
72
71
  const [currentSectionIndex, setCurrentSectionIndex] = useState(0);
@@ -143,8 +142,7 @@ const Renderer = ({
143
142
  fileUploadStatus: fileUploadStatus,
144
143
  handleFileDelete: handleFileDelete,
145
144
  onFileUpload: onFileUpload,
146
- sectionIndex: sectionIndex,
147
- customInputMap: customInputMap
145
+ sectionIndex: sectionIndex
148
146
  }))), /*#__PURE__*/React.createElement("div", {
149
147
  className: "navigator-container"
150
148
  }, updatedFormData.sections.length > 1 && /*#__PURE__*/React.createElement(Button, {
@@ -34,50 +34,40 @@ const Section = ({
34
34
  fileUploadStatus,
35
35
  handleFileDelete,
36
36
  onFileUpload,
37
- sectionIndex,
38
- customInputMap
37
+ sectionIndex
39
38
  // ...otherProps
40
- }) => {
41
- const customInputTypes = customInputMap ? Object.keys(customInputMap) : [];
42
- return /*#__PURE__*/React.createElement("div", {
43
- id: id,
44
- className: [baseClassName, componentClassName, userClassName].filter(e => e).join(' '),
45
- style: style
46
- }, /*#__PURE__*/React.createElement("p", {
47
- className: "h3"
48
- }, title), /*#__PURE__*/React.createElement(ExpandableLexicalPreview, {
49
- nodes: description,
50
- name: "instructions"
51
- }), inputs?.map((input, inputIndex) => {
52
- const isFileInput = input.type === 'file';
53
- const isCustomInput = customInputTypes.includes(input.type);
54
- const CustomInputComponent = isCustomInput ? customInputMap[input.type].component : null;
55
- return !isCustomInput ? /*#__PURE__*/React.createElement(FormInput, _extends({
56
- key: input.name
57
- }, input, {
58
- disabled: readOnly
59
- }, isFileInput && {
60
- uploadStatus: fileUploadStatus,
61
- handleFileDelete,
62
- onChange: files => {
63
- const filesToUpload = files?.filter(file => file instanceof File).map(file => ({
64
- file,
65
- name: file.name,
66
- mimeType: file.type,
67
- type: fileTypeMapper[getFileType(file)] || 'Generic',
68
- title: file.name,
69
- sectionIndex,
70
- inputIndex
71
- }));
72
- onFileUpload(filesToUpload);
73
- }
74
- })) : /*#__PURE__*/React.createElement(CustomInputComponent, _extends({
75
- key: input.name
76
- }, input, {
77
- disabled: readOnly
78
- }));
39
+ }) => /*#__PURE__*/React.createElement("div", {
40
+ id: id,
41
+ className: [baseClassName, componentClassName, userClassName].filter(e => e).join(' '),
42
+ style: style
43
+ }, /*#__PURE__*/React.createElement("p", {
44
+ className: "h3"
45
+ }, title), /*#__PURE__*/React.createElement(ExpandableLexicalPreview, {
46
+ nodes: description,
47
+ name: "instructions"
48
+ }), inputs?.map((input, inputIndex) => {
49
+ const isFileInput = input.type === 'file';
50
+ return /*#__PURE__*/React.createElement(FormInput, _extends({
51
+ key: input.name
52
+ }, input, {
53
+ disabled: readOnly
54
+ }, isFileInput && {
55
+ uploadStatus: fileUploadStatus,
56
+ handleFileDelete,
57
+ onChange: files => {
58
+ const filesToUpload = files?.filter(file => file instanceof File).map(file => ({
59
+ file,
60
+ name: file.name,
61
+ mimeType: file.type,
62
+ type: fileTypeMapper[getFileType(file)] || 'Generic',
63
+ title: file.name,
64
+ sectionIndex,
65
+ inputIndex
66
+ }));
67
+ onFileUpload(filesToUpload);
68
+ }
79
69
  }));
80
- };
70
+ }));
81
71
  Section.propTypes = {
82
72
  /**
83
73
  * The HTML id for this element
@@ -0,0 +1,102 @@
1
+ export const DATE_FORMATS = {
2
+ HUMAN_READABLE: 'human_readable',
3
+ TIME: 'time',
4
+ DATETIME: 'datetime',
5
+ CHART_DATE: 'chart_date',
6
+ CHART_TIME: 'chart_time',
7
+ WEEKDAY_DATE: 'weekday_date',
8
+ DAY_VIEW: 'day_view'
9
+ };
10
+ const isValidDate = date => date instanceof Date && !Number.isNaN(date);
11
+ const isTimeSliceFormat = input => {
12
+ const timeSliceRegex = /^([01]?[0-9]|2[0-3]):[0-5][0-9]$/;
13
+ return timeSliceRegex.test(input);
14
+ };
15
+ const createTimeFromSlice = timeSlice => {
16
+ const [hours, minutes] = timeSlice.split(':').map(Number);
17
+ const date = new Date();
18
+ date.setHours(hours, minutes, 0, 0);
19
+ return date;
20
+ };
21
+ const format12Hour = date => {
22
+ const hour = date.getHours();
23
+ const ampm = hour >= 12 ? 'PM' : 'AM';
24
+ const hour12 = hour % 12 || 12;
25
+ return `${hour12} ${ampm}`;
26
+ };
27
+ const shouldShowYear = date => {
28
+ const currentYear = new Date().getFullYear();
29
+ return date.getFullYear() !== currentYear;
30
+ };
31
+ export const formatTime = seconds => {
32
+ if (!seconds) return '0s';
33
+ const hours = Math.floor(seconds / 3600);
34
+ const minutes = Math.floor(seconds % 3600 / 60);
35
+ const remainingSeconds = Math.floor(seconds % 60);
36
+ const parts = [];
37
+ if (hours > 0) parts.push(`${hours}h`);
38
+ if (minutes > 0 || hours > 0 && remainingSeconds > 0) parts.push(`${minutes}m`);
39
+ if (remainingSeconds > 0) parts.push(`${remainingSeconds}s`);
40
+ return parts.join(' ');
41
+ };
42
+ const parseDate = input => {
43
+ if (input instanceof Date) return input;
44
+ if (typeof input === 'number') return new Date(input);
45
+ if (typeof input === 'string') {
46
+ if (isTimeSliceFormat(input)) {
47
+ return createTimeFromSlice(input);
48
+ }
49
+ const parsed = new Date(input);
50
+ if (isValidDate(parsed)) return parsed;
51
+ const timestamp = parseInt(input, 10);
52
+ if (!Number.isNaN(timestamp)) {
53
+ const date = new Date(timestamp * 1000);
54
+ if (isValidDate(date)) return date;
55
+ }
56
+ }
57
+ return null;
58
+ };
59
+ const formatStrategies = {
60
+ [DATE_FORMATS.CHART_DATE]: date => {
61
+ const monthDay = date.toLocaleDateString('en-US', {
62
+ month: 'short',
63
+ day: 'numeric',
64
+ timeZone: 'UTC'
65
+ });
66
+ return shouldShowYear(date) ? `${monthDay} ${date.getFullYear()}` : monthDay;
67
+ },
68
+ [DATE_FORMATS.CHART_TIME]: date => format12Hour(date),
69
+ [DATE_FORMATS.HUMAN_READABLE]: date => date.toLocaleDateString('en-US', {
70
+ year: 'numeric',
71
+ month: 'short',
72
+ day: 'numeric',
73
+ timeZone: 'UTC'
74
+ }),
75
+ default: date => date.toISOString()
76
+ };
77
+ export const formatDate = (input, format = DATE_FORMATS.HUMAN_READABLE) => {
78
+ try {
79
+ if (typeof input === 'string' && isTimeSliceFormat(input)) {
80
+ if (format === DATE_FORMATS.CHART_TIME || format === DATE_FORMATS.TIME) {
81
+ const date = createTimeFromSlice(input);
82
+ if (format === DATE_FORMATS.CHART_TIME) {
83
+ return format12Hour(date);
84
+ }
85
+ return date.toLocaleTimeString('en-US', {
86
+ hour: '2-digit',
87
+ minute: '2-digit',
88
+ timeZone: 'UTC'
89
+ });
90
+ }
91
+ return input;
92
+ }
93
+ const date = parseDate(input);
94
+ if (!date && (typeof input === 'string' || typeof input === 'number')) {
95
+ return input.toString();
96
+ }
97
+ const formatStrategy = formatStrategies[format] || formatStrategies.default;
98
+ return formatStrategy(date);
99
+ } catch (error) {
100
+ return 'Invalid Date';
101
+ }
102
+ };
@@ -1 +1,2 @@
1
- export { useWindowSize, useDynamicPosition, useOutsideClick } from "./hooks";
1
+ export { useWindowSize, useDynamicPosition, useOutsideClick } from "./hooks";
2
+ export { formatTime, formatDate, DATE_FORMATS } from "./formatting";
package/jest.config.js CHANGED
@@ -10,6 +10,9 @@ module.exports = {
10
10
  moduleNameMapper:{
11
11
  '^.+\\.(css|scss)$' :'<rootDir>/tests/staticStub.js',
12
12
  '^.+\\.(mdx)$' :'<rootDir>/tests/staticStub.js',
13
+ 'react-markdown' :'<rootDir>/tests/emptyMock.js',
14
+ 'remark-math' :'<rootDir>/tests/emptyMock.js',
15
+ 'rehype-mathjax' :'<rootDir>/tests/emptyMock.js',
13
16
  // https://jestjs.io/docs/webpack#mocking-css-modules
14
17
  '^@pareto-engineering/bem$' :'identity-obj-proxy',
15
18
  '^@pareto-engineering/bem/exports$':'identity-obj-proxy',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pareto-engineering/design-system",
3
- "version": "5.0.0",
3
+ "version": "5.0.1",
4
4
  "description": "",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/es/index.js",
@@ -63,6 +63,7 @@
63
63
  "@pareto-engineering/bem": "^5.0.0",
64
64
  "@pareto-engineering/styles": "^5.0.0",
65
65
  "@pareto-engineering/utils": "^5.0.0",
66
+ "better-react-mathjax": "^2.0.3",
66
67
  "codemirror": "^6.0.1",
67
68
  "date-fns": "^2.29.3",
68
69
  "downshift": "^6.1.12",
@@ -77,11 +78,14 @@
77
78
  "react-day-picker": "^8.10.0",
78
79
  "react-dom": "^18.2.0",
79
80
  "react-helmet-async": "^1.3.0",
81
+ "react-markdown": "^9.0.1",
80
82
  "react-relay": "^15.0.0",
81
83
  "react-router-dom": "^5.3.4",
82
84
  "recharts": "^2.13.3",
83
- "relay-test-utils": "^15.0.0"
85
+ "rehype-mathjax": "^6.0.0",
86
+ "relay-test-utils": "^15.0.0",
87
+ "remark-math": "^6.0.0"
84
88
  },
85
89
  "browserslist": "> 2%",
86
- "gitHead": "6892e855aadac7d1c0e4a8f00570e644ba9cfb55"
90
+ "gitHead": "874a3dc9198810523c6fe0edbaf72f43ddd6612d"
87
91
  }
@@ -0,0 +1,89 @@
1
+ // front/packages/design-system/src/ui/a/BarChart/BarChart.stories.jsx
2
+
3
+ import React from 'react'
4
+ import { BarChart } from 'ui'
5
+
6
+ export default {
7
+ title :'a/BarChart',
8
+ component:BarChart,
9
+ }
10
+
11
+ const data = [
12
+ {
13
+ date:'Jan', pendingReview:200, accepted:150, rejected:100, toRevise:250, revised:50,
14
+ },
15
+ {
16
+ date:'Feb', pendingReview:180, accepted:160, rejected:120, toRevise:240, revised:60,
17
+ },
18
+ {
19
+ date:'Mar', pendingReview:220, accepted:140, rejected:110, toRevise:230, revised:70,
20
+ },
21
+ {
22
+ date:'Apr', pendingReview:210, accepted:130, rejected:130, toRevise:220, revised:80,
23
+ },
24
+ {
25
+ date:'May', pendingReview:230, accepted:120, rejected:140, toRevise:210, revised:90,
26
+ },
27
+ {
28
+ date:'Jun', pendingReview:240, accepted:110, rejected:150, toRevise:200, revised:100,
29
+ },
30
+ {
31
+ date:'Jul', pendingReview:250, accepted:100, rejected:160, toRevise:190, revised:110,
32
+ },
33
+ {
34
+ date:'Aug', pendingReview:260, accepted:90, rejected:170, toRevise:180, revised:120,
35
+ },
36
+ {
37
+ date:'Sep', pendingReview:270, accepted:80, rejected:180, toRevise:170, revised:130,
38
+ },
39
+ {
40
+ date:'Oct', pendingReview:280, accepted:70, rejected:190, toRevise:160, revised:140,
41
+ },
42
+ {
43
+ date:'Nov', pendingReview:290, accepted:60, rejected:200, toRevise:150, revised:150,
44
+ },
45
+ {
46
+ date:'Dec', pendingReview:300, accepted:50, rejected:210, toRevise:140, revised:160,
47
+ },
48
+ ]
49
+
50
+ const Template = (args) => (
51
+ <div style={{ height: '100%', width: '100%' }}>
52
+ <BarChart {...args} />
53
+ </div>
54
+ )
55
+
56
+ export const Default = Template.bind({})
57
+ Default.args = {
58
+ data,
59
+ title :'Throughput',
60
+ xKey :'date',
61
+ yKeys :['pendingReview', 'accepted', 'rejected', 'toRevise', 'revised'],
62
+ xLabel:'Date',
63
+ yLabel:'Submissions',
64
+ colors:['purple', 'green', 'orange', 'blue', 'red'],
65
+ height:400,
66
+ }
67
+
68
+ const TemplateSideBySide = (args) => (
69
+ <div style={{ display: 'flex', gap: '20px' }}>
70
+ <div style={{ flex: 1 }}>
71
+ {/* eslint-disable-next-line react/destructuring-assignment */}
72
+ <BarChart {...args[0]} />
73
+ </div>
74
+ <div style={{ flex: 1 }}>
75
+ {/* eslint-disable-next-line react/destructuring-assignment */}
76
+ <BarChart {...args[1]} />
77
+ </div>
78
+ </div>
79
+ )
80
+
81
+ export const SideBySide = TemplateSideBySide.bind({})
82
+ SideBySide.args = [
83
+ {
84
+ ...Default.args,
85
+ },
86
+ {
87
+ ...Default.args,
88
+ },
89
+ ]