pixel-react 1.4.1 → 1.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. package/.yarn/install-state.gz +0 -0
  2. package/lib/components/MiniModal/types.d.ts +1 -1
  3. package/lib/components/Select/types.d.ts +1 -0
  4. package/lib/index.d.ts +5 -2
  5. package/lib/index.esm.js +123 -61
  6. package/lib/index.esm.js.map +1 -1
  7. package/lib/index.js +123 -60
  8. package/lib/index.js.map +1 -1
  9. package/lib/tsconfig.tsbuildinfo +1 -1
  10. package/lib/utils/downloadFile/saveFileFromBlob.d.ts +1 -0
  11. package/package.json +1 -1
  12. package/src/assets/icons/add_label_icon.svg +3 -0
  13. package/src/assets/icons/label_icon.svg +8 -0
  14. package/src/assets/icons/sample_template_first.svg +29 -0
  15. package/src/assets/icons/sample_template_second.svg +47 -0
  16. package/src/assets/styles/_fonts.scss +32 -2
  17. package/src/components/AllProjectsDropdown/AllProjectsDropdown.scss +2 -3
  18. package/src/components/AllProjectsDropdown/AllProjectsDropdown.tsx +1 -0
  19. package/src/components/AppHeader/AppHeader.scss +0 -1
  20. package/src/components/Icon/Icon.tsx +1 -0
  21. package/src/components/Icon/iconList.ts +10 -2
  22. package/src/components/MiniModal/MiniModal.stories.tsx +7 -5
  23. package/src/components/MiniModal/MiniModal.tsx +29 -23
  24. package/src/components/MiniModal/types.ts +1 -1
  25. package/src/components/Modal/Modal.tsx +2 -2
  26. package/src/components/Select/Select.tsx +2 -0
  27. package/src/components/Select/types.ts +5 -0
  28. package/src/components/StateDropdown/StateDropdown.tsx +18 -6
  29. package/src/components/Typography/Typography.scss +32 -2
  30. package/src/index.ts +2 -0
  31. package/src/utils/downloadFile/saveFileFromBlob.stories.tsx +62 -0
  32. package/src/utils/downloadFile/saveFileFromBlob.ts +40 -0
  33. /package/src/assets/icons/{fireflink_standard_template.svg → standard_template.svg} +0 -0
@@ -159,7 +159,9 @@ import DrawerMaximizeIcon from '../../assets/icons/drawer_maximize.svg?react';
159
159
  import SaveAsStepIcon from '../../assets/icons/save_as_step.svg?react';
160
160
  import SendToStepsIcon from '../../assets/icons/send_step.svg?react';
161
161
  import NoLicenseFound from '../../assets/icons/no_license_found.svg?react';
162
- import FireFlinkStandardTemplate from '../../assets/icons/fireflink_standard_template.svg?react';
162
+ import StandardTemplate from '../../assets/icons/standard_template.svg?react';
163
+ import SampleTemplateFirst from '../../assets/icons/sample_template_first.svg?react';
164
+ import SampleTemplateSecond from '../../assets/icons/sample_template_second.svg?react';
163
165
  import DataProvider from '../../assets/icons/data_provider.svg?react';
164
166
  import LinkExpired from '../../assets/icons/link_expired.svg?react';
165
167
  import LinkReset from '../../assets/icons/reset-link.svg?react';
@@ -176,6 +178,8 @@ import dashboardSalesforceIcon from '../../assets/icons/salesforce_icon.svg?reac
176
178
  import dashboardMsDynamicIcon from '../../assets/icons/ms_dynamic_icon.svg?react';
177
179
  import MinimizeScript from '../../assets/icons/minimize_script.svg?react';
178
180
  import MaximizeTree from '../../assets/icons/maximize_tree.svg?react';
181
+ import LabelIcon from '../../assets/icons/label_icon.svg?react';
182
+ import AddLabelIcon from '../../assets/icons/add_label_icon.svg?react';
179
183
 
180
184
  Components['delete_info'] = DeleteInfoIcon;
181
185
  Components['success'] = ToastSuccessIcon;
@@ -338,7 +342,9 @@ Components['flaky_status_icon'] = FlakyStatusIcon;
338
342
  Components['drawer_maximize'] = DrawerMaximizeIcon;
339
343
  Components['save_as_step'] = SaveAsStepIcon;
340
344
  Components['send_to_steps'] = SendToStepsIcon;
341
- Components['fireflink_standard_template'] = FireFlinkStandardTemplate;
345
+ Components['standard_template'] = StandardTemplate;
346
+ Components['sample_template_first'] = SampleTemplateFirst;
347
+ Components['sample_template_second'] = SampleTemplateSecond;
342
348
  Components['no_license_found'] = NoLicenseFound;
343
349
  Components['data_provider'] = DataProvider;
344
350
  Components['link_expired'] = LinkExpired;
@@ -349,5 +355,7 @@ Components['user_warning'] = UserWarning;
349
355
  Components['user_with_system'] = UserWithSystem;
350
356
  Components['minimize_script'] = MinimizeScript;
351
357
  Components['maximize_tree'] = MaximizeTree;
358
+ Components['label_icon'] = LabelIcon;
359
+ Components['add_label_icon'] = AddLabelIcon;
352
360
 
353
361
  export default Components;
@@ -5,6 +5,7 @@ import Button from '../Button/Button';
5
5
  import './MiniModal.scss';
6
6
  import Typography from '../Typography';
7
7
  import Icon from '../Icon';
8
+ import React from 'react';
8
9
 
9
10
  const meta: Meta<typeof MiniModal> = {
10
11
  title: 'Components/MiniModal',
@@ -41,14 +42,15 @@ const BasicModalComponent = () => {
41
42
  <div className="ff-mini-modal-buttons-flex ff-mini-modal-gap-10">
42
43
  <Button
43
44
  onClick={() => openModal(1)}
45
+ id='112233'
44
46
  ref={btnRef1}
45
- label="1"
47
+ label="122"
46
48
  variant={currentModal === 1 ? 'primary' : 'secondary'}
47
49
  />
48
50
 
49
51
  {currentModal === 1 && (
50
52
  <MiniModal
51
- anchorRef={btnRef1}
53
+ anchorRef="112233"
52
54
  modalProperties={{ width: 300, height: 180 }}
53
55
  headerProps={
54
56
  <>
@@ -254,14 +256,14 @@ export const CustomModalWithArrow = () => {
254
256
  <div className="ff-mini-modal-buttons-flex ff-mini-modal-gap-10">
255
257
  <Button
256
258
  onClick={() => openModal(1)}
257
- ref={btnRef1}
258
- label="1"
259
+ label="12"
260
+ id="1a2b"
259
261
  variant={currentModal === 1 ? 'primary' : 'secondary'}
260
262
  />
261
263
 
262
264
  {currentModal === 1 && (
263
265
  <MiniModal
264
- anchorRef={btnRef1}
266
+ anchorRef='1a2b'
265
267
  modalProperties={{ width: 300, height: 250 }}
266
268
  headerProps={
267
269
  <>
@@ -40,6 +40,7 @@ const MiniModal = forwardRef<HTMLDivElement, MiniEditModalProps>(
40
40
  });
41
41
  const [isVisible, setIsVisible] = useState(false);
42
42
  const modalRef = useRef<HTMLDivElement>(null);
43
+
43
44
  // Function to calculate available space
44
45
  const getAvailableSpace = (rect: Rect): AvailableSpace => {
45
46
  const { top, left, bottom, right } = rect;
@@ -53,7 +54,18 @@ const MiniModal = forwardRef<HTMLDivElement, MiniEditModalProps>(
53
54
  spaceBottom: viewportHeight - bottom,
54
55
  };
55
56
  };
56
- const anchorRect = anchorRef.current?.getBoundingClientRect();
57
+
58
+ // Helper function to get the anchor element
59
+ const getAnchorElement = () => {
60
+ if (typeof anchorRef === 'string') {
61
+ return document.getElementById(anchorRef);
62
+ }
63
+ return anchorRef?.current || null;
64
+ };
65
+
66
+ const anchorElement = getAnchorElement();
67
+ const anchorRect = anchorElement?.getBoundingClientRect();
68
+
57
69
  if (!isWrapped && anchorRect) {
58
70
  const availableSpace = getAvailableSpace(anchorRect);
59
71
  switch (modalPosition) {
@@ -82,7 +94,7 @@ const MiniModal = forwardRef<HTMLDivElement, MiniEditModalProps>(
82
94
  }
83
95
  }
84
96
 
85
- //specify for the wrapper div left position
97
+ // Specify for the wrapper div left position
86
98
  const calculateAnchorRefLeft = (anchorRefLeftNum?: number) => {
87
99
  if (anchorRefLeftNum) {
88
100
  return anchorRefLeftNum;
@@ -90,7 +102,7 @@ const MiniModal = forwardRef<HTMLDivElement, MiniEditModalProps>(
90
102
  return 0;
91
103
  };
92
104
 
93
- //specify for the arrow position in left or top
105
+ // Specify for the arrow position in left or top
94
106
  const getArrowClassName = () => {
95
107
  if (leftTopArrow && modalPosition === 'right') {
96
108
  return 'left-top-arrow';
@@ -99,13 +111,13 @@ const MiniModal = forwardRef<HTMLDivElement, MiniEditModalProps>(
99
111
  };
100
112
  const calculatedAnchorRefLeft = calculateAnchorRefLeft(anchorRefLeftNum);
101
113
 
102
- //specifying for specific wrapper modal position
114
+ // Specify specific wrapper modal position
103
115
  const firstAnchor =
104
116
  firstAnchorRef?.current &&
105
117
  firstAnchorRef?.current?.getBoundingClientRect().left -
106
118
  anchorLeftDistanceForWrapper;
107
119
 
108
- //specifying the modal top
120
+ // Specifying the modal top
109
121
  const calculateModalTop = () => {
110
122
  const safeHeight = modalProperties?.height ?? 0;
111
123
  if (modalPosition === 'bottom') {
@@ -115,24 +127,18 @@ const MiniModal = forwardRef<HTMLDivElement, MiniEditModalProps>(
115
127
  } else if (modalPosition === 'right') {
116
128
  return leftTopArrow
117
129
  ? modalPositionState.top - (extraRightSpace?.leftTopArrow ?? 30)
118
- : modalPositionState?.top -
119
- safeHeight / (extraRightSpace?.middleLeftArrow ?? 3.5);
130
+ : modalPositionState?.top - safeHeight / (extraRightSpace?.middleLeftArrow ?? 3.5);
120
131
  } else if (modalPosition === 'top') {
121
- return (
122
- modalPositionState.top -
123
- (safeHeight + (extraTopSpace?.normalModal ?? 10))
124
- );
132
+ return modalPositionState.top - (safeHeight + (extraTopSpace?.normalModal ?? 10));
125
133
  }
126
134
  return modalPositionState.top - safeHeight / 1.5;
127
135
  };
128
136
  const calculatedModalTop = calculateModalTop();
129
137
 
130
- //specifying the modal left
138
+ // Specifying the modal left
131
139
  const calculateModalLeft = () => {
132
140
  if (modalPosition === 'right') {
133
- return (
134
- modalPositionState.left + (extraLeftSpace?.rightAlignModal ?? 40)
135
- );
141
+ return modalPositionState.left + (extraLeftSpace?.rightAlignModal ?? 40);
136
142
  } else if (firstAnchorRef) {
137
143
  return firstAnchor;
138
144
  } else if (modalPosition === 'left') {
@@ -143,16 +149,16 @@ const MiniModal = forwardRef<HTMLDivElement, MiniEditModalProps>(
143
149
  };
144
150
  const calculatedModalLeft = calculateModalLeft();
145
151
 
146
- //specifying the modal's escape and enter functionality
152
+ // Handle escape and enter functionality
147
153
  const handleEsc = useEscapeKey('Escape');
148
154
  const handleEnter = useEscapeKey('Enter');
149
155
  handleEsc(cancelButtonProps?.onClick);
150
156
  handleEnter(proceedButtonProps?.onClick);
151
157
  useClickOutside(modalRef, cancelButtonProps.onClick);
152
158
 
153
- //calculate the modal position
159
+ // Calculate the modal position
154
160
  const calculatePosition = useCallback(() => {
155
- const anchorRect = anchorRef.current?.getBoundingClientRect();
161
+ const anchorRect = anchorElement?.getBoundingClientRect();
156
162
  if (anchorRect) {
157
163
  const { bottom, left } = anchorRect;
158
164
  const { scrollX, scrollY } = window;
@@ -164,7 +170,7 @@ const MiniModal = forwardRef<HTMLDivElement, MiniEditModalProps>(
164
170
  left: leftPosition,
165
171
  });
166
172
  }
167
- }, [anchorRef, modalProperties]);
173
+ }, [anchorElement]);
168
174
 
169
175
  useEffect(() => {
170
176
  const timeoutId = setTimeout(() => {
@@ -213,10 +219,10 @@ const MiniModal = forwardRef<HTMLDivElement, MiniEditModalProps>(
213
219
  modalPosition === 'right'
214
220
  ? 'left'
215
221
  : modalPosition === 'top'
216
- ? 'bottom'
217
- : modalPosition === 'left'
218
- ? 'right'
219
- : 'top'
222
+ ? 'bottom'
223
+ : modalPosition === 'left'
224
+ ? 'right'
225
+ : 'top'
220
226
  } ${getArrowClassName()}`}
221
227
  />
222
228
  )}
@@ -9,7 +9,7 @@ export interface MiniEditModalProps {
9
9
  /**
10
10
  * A reference to the button element that triggers the modal.
11
11
  */
12
- anchorRef: RefObject<HTMLButtonElement>;
12
+ anchorRef: RefObject<HTMLButtonElement> | string;
13
13
  /**
14
14
  * Optional properties for configuring the modal header.
15
15
  */
@@ -58,9 +58,9 @@ const Modal: React.FC<ModalProps> = ({
58
58
  <div
59
59
  style={{
60
60
  boxShadow: boxShadow,
61
- borderRadius: isHeaderDisplayed || isFooterDisplayed ? '12px' : '0px', // Apply based on conditions
61
+ borderRadius: '12px' ,
62
62
  }}
63
- className="ff-modal-container" // New container class for consistency
63
+ className="ff-modal-container"
64
64
  >
65
65
  <div
66
66
  className={classNames(
@@ -29,6 +29,7 @@ const Select: FC<SelectProps> = ({
29
29
  height = 32,
30
30
  width = '100%',
31
31
  onBlur = () => {},
32
+ disableInput = false
32
33
  }) => {
33
34
  const selectWidth = typeof width === 'number' ? `${width}px` : width;
34
35
 
@@ -176,6 +177,7 @@ const Select: FC<SelectProps> = ({
176
177
  style={{ zIndex: optionZIndex, color: selectedOptionColor }}
177
178
  disabled={disabled}
178
179
  onChange={handleChange}
180
+ readOnly={disableInput}
179
181
  />
180
182
  {optionsRequired && (
181
183
  <div
@@ -93,6 +93,11 @@ export interface SelectProps {
93
93
  * Provide the onBlur functionality for the select
94
94
  */
95
95
  onBlur?: () => void;
96
+
97
+ /*
98
+ * Disable the select component input
99
+ */
100
+ disableInput?: boolean;
96
101
  }
97
102
 
98
103
  export interface DrowdownPosition {
@@ -129,7 +129,9 @@ const StateDropdown = ({
129
129
  optionsList={options}
130
130
  selectedOption={selectedOption}
131
131
  showLabel={false}
132
- showBorder={true}
132
+ showBorder={false}
133
+ disableInput={true}
134
+ height={24}
133
135
  />
134
136
  ) : (
135
137
  <Select
@@ -139,7 +141,9 @@ const StateDropdown = ({
139
141
  optionsList={options}
140
142
  selectedOption={selectedOption}
141
143
  showLabel={false}
142
- showBorder={true}
144
+ showBorder={false}
145
+ disableInput={true}
146
+ height={24}
143
147
  />
144
148
  );
145
149
  } else if (
@@ -154,7 +158,9 @@ const StateDropdown = ({
154
158
  optionsList={options}
155
159
  selectedOption={selectedOption}
156
160
  showLabel={false}
157
- showBorder={true}
161
+ showBorder={false}
162
+ disableInput={true}
163
+ height={24}
158
164
  />
159
165
  );
160
166
  } else if (currentState === 'APPROVED') {
@@ -166,7 +172,9 @@ const StateDropdown = ({
166
172
  optionsList={options}
167
173
  selectedOption={selectedOption}
168
174
  showLabel={false}
169
- showBorder={true}
175
+ showBorder={false}
176
+ disableInput={true}
177
+ height={24}
170
178
  />
171
179
  );
172
180
  } else if (currentState === 'REJECTED' && userHasOnlyViewAccess) {
@@ -178,7 +186,9 @@ const StateDropdown = ({
178
186
  optionsList={options}
179
187
  selectedOption={selectedOption}
180
188
  showLabel={false}
181
- showBorder={true}
189
+ showBorder={false}
190
+ disableInput={true}
191
+ height={24}
182
192
  />
183
193
  );
184
194
  } else if (currentState === 'NEW' && userHasOnlyViewAccess) {
@@ -190,7 +200,9 @@ const StateDropdown = ({
190
200
  optionsList={options}
191
201
  selectedOption={selectedOption}
192
202
  showLabel={false}
193
- showBorder={true}
203
+ showBorder={false}
204
+ disableInput={true}
205
+ height={24}
194
206
  />
195
207
  );
196
208
  } else {
@@ -1,10 +1,40 @@
1
- @import url('https://fonts.cdnfonts.com/css/poppins');
2
-
3
1
  @mixin fontPoppins($size: 16px) {
4
2
  font-family: 'Poppins';
5
3
  font-size: $size;
6
4
  }
7
5
 
6
+ @font-face {
7
+ font-family: 'Poppins';
8
+ font-weight: 400;
9
+ src:
10
+ local('Poppins-Regular'),
11
+ url(../../fonts/Poppins/Poppins-Regular.ttf) format('truetype');
12
+ }
13
+
14
+ @font-face {
15
+ font-family: 'Poppins';
16
+ font-weight: 500;
17
+ src:
18
+ local('Poppins-Medium'),
19
+ url(../../fonts/Poppins/Poppins-Medium.ttf) format('truetype');
20
+ }
21
+
22
+ @font-face {
23
+ font-family: 'Poppins';
24
+ font-weight: 600;
25
+ src:
26
+ local('Poppins-SemiBold'),
27
+ url(../../fonts/Poppins/Poppins-SemiBold.ttf) format('truetype');
28
+ }
29
+
30
+ @font-face {
31
+ font-family: 'Poppins';
32
+ font-weight: 700;
33
+ src:
34
+ local('Poppins-Bold'),
35
+ url(../../fonts/Poppins/Poppins-Bold.ttf) format('truetype');
36
+ }
37
+
8
38
  .ff-text {
9
39
  @include fontPoppins();
10
40
 
package/src/index.ts CHANGED
@@ -80,6 +80,7 @@ import MultiRadialChart from './components/Charts/MultiRadialChart';
80
80
  import Editor from './components/Editor/Editor';
81
81
  import { getSequentialPayload } from './utils/getSequentialPayload/getSequentialPayload';
82
82
  import ConnectingBranch from './components/ConnectingBranch/ConnectingBranch';
83
+ import { saveFileFromBlob } from './utils/downloadFile/saveFileFromBlob'
83
84
 
84
85
  export {
85
86
  Button,
@@ -163,4 +164,5 @@ export {
163
164
  getEncryptedData,
164
165
  truncateText,
165
166
  getSequentialPayload,
167
+ saveFileFromBlob,
166
168
  };
@@ -0,0 +1,62 @@
1
+ import { saveFileFromBlob } from './saveFileFromBlob';
2
+ import { Toastify, toast } from '../../components/Toastify/Toastify';
3
+
4
+ export default {
5
+ title: 'Utils/saveFileFromBlob',
6
+ component: saveFileFromBlob,
7
+ };
8
+
9
+ export const Default = () => {
10
+ const testCases = [
11
+ {
12
+ blob: new Blob(['Hello, world!'], { type: 'text/plain' }),
13
+ filename: 'hello.txt',
14
+ },
15
+ {
16
+ blob: new Blob(['{ "key": "value" }'], { type: 'application/json' }),
17
+ filename: 'data.json',
18
+ },
19
+ {
20
+ blob: null,
21
+ filename: 'invalid.txt',
22
+ expectedError: 'Invalid Blob object',
23
+ },
24
+ ];
25
+
26
+ const handleDownload = (blob: Blob | null, filename: string) => {
27
+ try {
28
+ if (blob instanceof Blob) {
29
+ saveFileFromBlob(blob, filename);
30
+ toast.success(`File "${filename}" downloaded successfully!`);
31
+ } else {
32
+ throw new Error('Invalid Blob object');
33
+ }
34
+ } catch (error: any) {
35
+ toast.error(error.message);
36
+ }
37
+ };
38
+
39
+ return (
40
+ <>
41
+ <div>
42
+ <h1>saveFileFromBlob - Test Cases</h1>
43
+ {testCases.map(({ blob, filename, expectedError }, index) => (
44
+ <div key={index} style={{ marginBottom: '1rem' }}>
45
+ <button
46
+ onClick={() => handleDownload(blob as Blob, filename)}
47
+ style={{ marginRight: '1rem' }}
48
+ >
49
+ Download {filename}
50
+ </button>
51
+ {expectedError && (
52
+ <span style={{ color: 'red' }}>
53
+ Expected Error: {expectedError}
54
+ </span>
55
+ )}
56
+ </div>
57
+ ))}
58
+ </div>
59
+ <Toastify />
60
+ </>
61
+ );
62
+ };
@@ -0,0 +1,40 @@
1
+ // saveFileFromBlob.ts
2
+
3
+ /**
4
+ * Save a file from a Blob object.
5
+ * This utility handles downloading files in browsers, including IE support.
6
+ *
7
+ * @param blob - The Blob object representing the file.
8
+ * @param filename - The name of the file to save.
9
+ */
10
+ interface NavigatorWithMsSaveBlob extends Navigator {
11
+ msSaveOrOpenBlob?: (_blob: Blob, _filename: string) => void;
12
+ }
13
+
14
+ export const saveFileFromBlob = (blob: Blob, filename: string): void => {
15
+ if (!blob || !(blob instanceof Blob)) {
16
+ console.error('Invalid Blob object');
17
+ throw new Error('Invalid Blob object');
18
+ }
19
+
20
+ const navigatorWithMsSaveBlob = window.navigator as NavigatorWithMsSaveBlob;
21
+
22
+ if (navigatorWithMsSaveBlob.msSaveOrOpenBlob) {
23
+ const saveBlob = navigatorWithMsSaveBlob.msSaveOrOpenBlob;
24
+ if (saveBlob) {
25
+ saveBlob(blob, filename);
26
+ }
27
+ } else {
28
+ // For modern browsers
29
+ const anchorElement = document.createElement('a');
30
+ document.body.appendChild(anchorElement);
31
+ const objectURL = window.URL.createObjectURL(blob);
32
+ anchorElement.href = objectURL;
33
+ anchorElement.download = filename;
34
+ anchorElement.click();
35
+ setTimeout(() => {
36
+ window.URL.revokeObjectURL(objectURL);
37
+ document.body.removeChild(anchorElement);
38
+ }, 0);
39
+ }
40
+ };