pixel-react 1.4.1 → 1.4.3

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 (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
+ };