@fixefy/fixefy-ui-components 0.0.5 → 0.0.7
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.
- package/dist-cjs/ActionsTray/{actions_tray.jsx → ActionsTray.jsx} +46 -46
- package/dist-cjs/ActionsTray/index.js +4 -0
- package/dist-cjs/ActionsTray/styles/{actionsTray.styles.jsx → actions_tray.styles.jsx} +1 -1
- package/dist-cjs/AggregationsBar/Aggregations.jsx +27 -0
- package/dist-cjs/AggregationsBar/helpers/structureReader.jsx +41 -0
- package/dist-cjs/AggregationsBar/index.js +5 -0
- package/dist-cjs/AggregationsBar/operations/query.js +66 -0
- package/dist-cjs/AsyncDropdown/AsyncDropdown.jsx +209 -0
- package/dist-cjs/AsyncDropdown/helpers/helpers.js +81 -0
- package/dist-cjs/AsyncDropdown/index.js +5 -0
- package/dist-cjs/AsyncDropdown/styles/dropdown.styles.jsx +130 -0
- package/dist-cjs/FxAvatar/FxAvatar.jsx +34 -0
- package/dist-cjs/FxAvatar/helpers/stringToColor.js +17 -0
- package/dist-cjs/FxAvatar/index.js +5 -0
- package/dist-cjs/FxAvatar/styles/avatar.styles.jsx +75 -0
- package/dist-cjs/FxButton/{button.jsx → FxButton.jsx} +3 -3
- package/dist-cjs/FxButton/index.js +3 -3
- package/dist-cjs/FxChip/FxChip.jsx +14 -0
- package/dist-cjs/FxChip/index.js +5 -0
- package/dist-cjs/FxChip/styles/chip.styles.jsx +48 -0
- package/dist-cjs/FxIcon/FxIcon.jsx +29 -0
- package/dist-cjs/FxIcon/content/dynamic_icon.jsx +7 -0
- package/dist-cjs/FxIcon/content/index.js +7 -0
- package/dist-cjs/FxIcon/content/lazy_icon.jsx +22 -0
- package/dist-cjs/FxIcon/index.js +5 -0
- package/dist-cjs/FxModal/FxModal.jsx +36 -0
- package/dist-cjs/FxModal/index.js +5 -0
- package/dist-cjs/FxModal/styles/modal.style.jsx +34 -0
- package/dist-cjs/FxNotes/FxNotes.jsx +101 -0
- package/dist-cjs/FxNotes/helpers/stringToColor.js +20 -0
- package/dist-cjs/FxNotes/index.js +5 -0
- package/dist-cjs/FxNotes/operations/queries.js +24 -0
- package/dist-cjs/FxNotes/styles/notes.styles.jsx +120 -0
- package/dist-cjs/FxNumberField/FxNumberField.jsx +30 -0
- package/dist-cjs/FxNumberField/index.js +5 -0
- package/dist-cjs/FxNumberField/styles/number_field.styles.js +87 -0
- package/dist-cjs/FxProgressCircle/FxProgressCircle.jsx +28 -0
- package/dist-cjs/FxProgressCircle/index.js +5 -0
- package/dist-cjs/FxProgressCircle/styles/progress_circle.styles.jsx +27 -0
- package/dist-cjs/FxProgressCounter/ProgressCounter.jsx +45 -0
- package/dist-cjs/FxProgressCounter/index.js +5 -0
- package/dist-cjs/FxProgressCounter/styles/progress_counter.styles.js +36 -0
- package/dist-cjs/FxShowMore/FxShowMore.jsx +47 -0
- package/dist-cjs/FxShowMore/index.js +5 -0
- package/dist-cjs/FxShowMore/styles/show_more.styles.js +43 -0
- package/dist-cjs/FxSlider/FxSlider.jsx +10 -0
- package/dist-cjs/FxSlider/index.js +5 -0
- package/dist-cjs/FxStatusBar/FxStatusBar.jsx +64 -0
- package/dist-cjs/FxStatusBar/helpers/constants.js +15 -0
- package/dist-cjs/FxStatusBar/index.js +5 -0
- package/dist-cjs/FxStatusBar/styles/statusBar.styles.jsx +39 -0
- package/dist-cjs/FxTextField/FxTextField.jsx +62 -0
- package/dist-cjs/FxTextField/index.js +5 -0
- package/dist-cjs/FxTodo/FxTodo.jsx +46 -0
- package/dist-cjs/FxTodo/index.js +5 -0
- package/dist-cjs/FxTodo/styles/todo.styles.jsx +75 -0
- package/dist-cjs/FxWizard/FxWizard.jsx +49 -0
- package/dist-cjs/FxWizard/WizardContext.jsx +86 -0
- package/dist-cjs/FxWizard/index.js +8 -0
- package/dist-cjs/FxWizard/styles/wizard.styles.jsx +17 -0
- package/dist-cjs/Score/Score.jsx +57 -0
- package/dist-cjs/Score/index.js +5 -0
- package/dist-cjs/Score/styles/score.styles.js +33 -0
- package/dist-cjs/StatisticsBar/StatisticsBar.jsx +95 -0
- package/dist-cjs/StatisticsBar/index.js +5 -0
- package/dist-cjs/StatisticsBar/styles/statistics.styles.js +33 -0
- package/dist-cjs/Tag/Tag.jsx +6 -6
- package/dist-cjs/index.js +15 -3
- package/dist-es/ActionsTray/{actions_tray.jsx → ActionsTray.jsx} +1 -1
- package/dist-es/ActionsTray/index.js +1 -1
- package/dist-es/ActionsTray/styles/{actionsTray.styles.jsx → actions_tray.styles.jsx} +2 -2
- package/dist-es/AggregationsBar/Aggregations.jsx +22 -0
- package/dist-es/AggregationsBar/helpers/structureReader.jsx +32 -0
- package/dist-es/AggregationsBar/index.js +1 -0
- package/dist-es/AggregationsBar/operations/query.js +63 -0
- package/dist-es/AsyncDropdown/AsyncDropdown.jsx +228 -0
- package/dist-es/AsyncDropdown/helpers/helpers.js +77 -0
- package/dist-es/AsyncDropdown/index.js +1 -0
- package/dist-es/AsyncDropdown/styles/dropdown.styles.jsx +143 -0
- package/dist-es/FxAvatar/FxAvatar.jsx +32 -0
- package/dist-es/FxAvatar/helpers/stringToColor.js +13 -0
- package/dist-es/FxAvatar/index.js +1 -0
- package/dist-es/FxAvatar/styles/avatar.styles.jsx +68 -0
- package/dist-es/FxButton/{button.jsx → FxButton.jsx} +1 -1
- package/dist-es/FxButton/index.js +1 -1
- package/dist-es/FxChip/FxChip.jsx +9 -0
- package/dist-es/FxChip/index.js +1 -0
- package/dist-es/FxChip/styles/chip.styles.jsx +45 -0
- package/dist-es/FxIcon/FxIcon.jsx +24 -0
- package/dist-es/FxIcon/content/dynamic_icon.jsx +2 -0
- package/dist-es/FxIcon/content/index.js +2 -0
- package/dist-es/FxIcon/content/lazy_icon.jsx +17 -0
- package/dist-es/FxIcon/index.js +1 -0
- package/dist-es/FxModal/FxModal.jsx +30 -0
- package/dist-es/FxModal/index.js +1 -0
- package/dist-es/FxModal/styles/modal.style.jsx +31 -0
- package/dist-es/FxNotes/FxNotes.jsx +102 -0
- package/dist-es/FxNotes/helpers/stringToColor.js +16 -0
- package/dist-es/FxNotes/index.js +1 -0
- package/dist-es/FxNotes/operations/queries.js +20 -0
- package/dist-es/FxNotes/styles/notes.styles.jsx +116 -0
- package/dist-es/FxNumberField/FxNumberField.jsx +25 -0
- package/dist-es/FxNumberField/index.js +1 -0
- package/dist-es/FxNumberField/styles/number_field.styles.js +84 -0
- package/dist-es/FxProgressCircle/FxProgressCircle.jsx +23 -0
- package/dist-es/FxProgressCircle/index.js +1 -0
- package/dist-es/FxProgressCircle/styles/progress_circle.styles.jsx +28 -0
- package/dist-es/FxProgressCounter/ProgressCounter.jsx +38 -0
- package/dist-es/FxProgressCounter/index.js +1 -0
- package/dist-es/FxProgressCounter/styles/progress_counter.styles.js +33 -0
- package/dist-es/FxShowMore/FxShowMore.jsx +42 -0
- package/dist-es/FxShowMore/index.js +1 -0
- package/dist-es/FxShowMore/styles/show_more.styles.js +53 -0
- package/dist-es/FxSlider/FxSlider.jsx +5 -0
- package/dist-es/FxSlider/index.js +1 -0
- package/dist-es/FxStatusBar/FxStatusBar.jsx +59 -0
- package/dist-es/FxStatusBar/helpers/constants.js +12 -0
- package/dist-es/FxStatusBar/index.js +1 -0
- package/dist-es/FxStatusBar/styles/statusBar.styles.jsx +39 -0
- package/dist-es/FxTextField/FxTextField.jsx +63 -0
- package/dist-es/FxTextField/index.js +1 -0
- package/dist-es/FxTodo/FxTodo.jsx +41 -0
- package/dist-es/FxTodo/index.js +1 -0
- package/dist-es/FxTodo/styles/todo.styles.jsx +97 -0
- package/dist-es/FxWizard/FxWizard.jsx +46 -0
- package/dist-es/FxWizard/WizardContext.jsx +84 -0
- package/dist-es/FxWizard/index.js +2 -0
- package/dist-es/FxWizard/styles/wizard.styles.jsx +18 -0
- package/dist-es/Score/Score.jsx +57 -0
- package/dist-es/Score/index.js +1 -0
- package/dist-es/Score/styles/score.styles.js +35 -0
- package/dist-es/StatisticsBar/StatisticsBar.jsx +91 -0
- package/dist-es/StatisticsBar/index.js +1 -0
- package/dist-es/StatisticsBar/styles/statistics.styles.js +38 -0
- package/dist-es/Tag/Tag.jsx +6 -6
- package/dist-es/index.js +7 -1
- package/dist-types/ActionsTray/{actions_tray.d.ts → ActionsTray.d.ts} +2 -2
- package/dist-types/ActionsTray/index.d.ts +2 -0
- package/dist-types/AggregationsBar/Aggregations.d.ts +3 -0
- package/dist-types/AggregationsBar/helpers/structureReader.d.ts +1 -0
- package/dist-types/AggregationsBar/index.d.ts +2 -0
- package/dist-types/AggregationsBar/operations/query.d.ts +1 -0
- package/dist-types/AsyncDropdown/AsyncDropdown.d.ts +3 -0
- package/dist-types/AsyncDropdown/helpers/helpers.d.ts +4 -0
- package/dist-types/AsyncDropdown/index.d.ts +2 -0
- package/dist-types/AsyncDropdown/styles/dropdown.styles.d.ts +7 -0
- package/dist-types/FxAvatar/FxAvatar.d.ts +3 -0
- package/dist-types/FxAvatar/helpers/stringToColor.d.ts +1 -0
- package/dist-types/FxAvatar/index.d.ts +2 -0
- package/dist-types/FxAvatar/styles/avatar.styles.d.ts +7 -0
- package/dist-types/FxButton/FxButton.d.ts +6 -0
- package/dist-types/FxButton/index.d.ts +2 -2
- package/dist-types/FxChip/FxChip.d.ts +3 -0
- package/dist-types/FxChip/index.d.ts +2 -0
- package/dist-types/FxChip/styles/chip.styles.d.ts +3 -0
- package/dist-types/FxIcon/FxIcon.d.ts +3 -0
- package/dist-types/FxIcon/content/dynamic_icon.d.ts +5 -0
- package/dist-types/FxIcon/content/index.d.ts +2 -0
- package/dist-types/FxIcon/content/lazy_icon.d.ts +9 -0
- package/dist-types/FxIcon/index.d.ts +1 -0
- package/dist-types/FxModal/FxModal.d.ts +3 -0
- package/dist-types/FxModal/index.d.ts +2 -0
- package/dist-types/FxModal/styles/modal.style.d.ts +4 -0
- package/dist-types/FxNotes/FxNotes.d.ts +3 -0
- package/dist-types/FxNotes/helpers/stringToColor.d.ts +1 -0
- package/dist-types/FxNotes/index.d.ts +2 -0
- package/dist-types/FxNotes/operations/queries.d.ts +1 -0
- package/dist-types/FxNotes/styles/notes.styles.d.ts +13 -0
- package/dist-types/FxNumberField/FxNumberField.d.ts +3 -0
- package/dist-types/FxNumberField/index.d.ts +2 -0
- package/dist-types/FxNumberField/styles/number_field.styles.d.ts +1 -0
- package/dist-types/FxProgressCircle/FxProgressCircle.d.ts +3 -0
- package/dist-types/FxProgressCircle/index.d.ts +2 -0
- package/dist-types/FxProgressCircle/styles/progress_circle.styles.d.ts +5 -0
- package/dist-types/FxProgressCounter/ProgressCounter.d.ts +3 -0
- package/dist-types/FxProgressCounter/index.d.ts +2 -0
- package/dist-types/FxProgressCounter/styles/progress_counter.styles.d.ts +5 -0
- package/dist-types/FxShowMore/FxShowMore.d.ts +3 -0
- package/dist-types/FxShowMore/index.d.ts +2 -0
- package/dist-types/FxShowMore/styles/show_more.styles.d.ts +6 -0
- package/dist-types/FxSlider/FxSlider.d.ts +3 -0
- package/dist-types/FxSlider/index.d.ts +2 -0
- package/dist-types/FxStatusBar/FxStatusBar.d.ts +3 -0
- package/dist-types/FxStatusBar/helpers/constants.d.ts +12 -0
- package/dist-types/FxStatusBar/index.d.ts +1 -0
- package/dist-types/FxStatusBar/styles/statusBar.styles.d.ts +3 -0
- package/dist-types/FxTextField/FxTextField.d.ts +4 -0
- package/dist-types/FxTextField/index.d.ts +2 -0
- package/dist-types/FxTodo/FxTodo.d.ts +3 -0
- package/dist-types/FxTodo/index.d.ts +2 -0
- package/dist-types/FxTodo/styles/todo.styles.d.ts +8 -0
- package/dist-types/FxWizard/FxWizard.d.ts +3 -0
- package/dist-types/FxWizard/WizardContext.d.ts +6 -0
- package/dist-types/FxWizard/index.d.ts +3 -0
- package/dist-types/FxWizard/styles/wizard.styles.d.ts +2 -0
- package/dist-types/Score/Score.d.ts +3 -0
- package/dist-types/Score/index.d.ts +2 -0
- package/dist-types/Score/styles/score.styles.d.ts +7 -0
- package/dist-types/StatisticsBar/StatisticsBar.d.ts +3 -0
- package/dist-types/StatisticsBar/index.d.ts +2 -0
- package/dist-types/StatisticsBar/styles/statistics.styles.d.ts +2 -0
- package/dist-types/Tag/Tag.d.ts +2 -2
- package/dist-types/Tag/index.d.ts +1 -1
- package/dist-types/index.d.ts +9 -4
- package/package.json +6 -2
- package/dist-types/FxButton/button.d.ts +0 -6
- /package/dist-types/ActionsTray/styles/{actionsTray.styles.d.ts → actions_tray.styles.d.ts} +0 -0
package/dist-cjs/index.js
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Tag = exports.
|
|
4
|
-
var
|
|
5
|
-
Object.defineProperty(exports, "
|
|
3
|
+
exports.Tag = exports.FxProgressCounter = exports.FxModal = exports.FxChip = exports.FxButton = exports.FxAvatar = exports.AsyncDropdown = exports.AggregationsBar = void 0;
|
|
4
|
+
var AggregationsBar_1 = require("./AggregationsBar");
|
|
5
|
+
Object.defineProperty(exports, "AggregationsBar", { enumerable: true, get: function () { return AggregationsBar_1.AggregationsBar; } });
|
|
6
|
+
var AsyncDropdown_1 = require("./AsyncDropdown");
|
|
7
|
+
Object.defineProperty(exports, "AsyncDropdown", { enumerable: true, get: function () { return AsyncDropdown_1.AsyncDropdown; } });
|
|
8
|
+
var FxAvatar_1 = require("./FxAvatar");
|
|
9
|
+
Object.defineProperty(exports, "FxAvatar", { enumerable: true, get: function () { return FxAvatar_1.FxAvatar; } });
|
|
10
|
+
var FxButton_1 = require("./FxButton");
|
|
11
|
+
Object.defineProperty(exports, "FxButton", { enumerable: true, get: function () { return FxButton_1.FxButton; } });
|
|
12
|
+
var FxChip_1 = require("./FxChip");
|
|
13
|
+
Object.defineProperty(exports, "FxChip", { enumerable: true, get: function () { return FxChip_1.FxChip; } });
|
|
14
|
+
var FxModal_1 = require("./FxModal");
|
|
15
|
+
Object.defineProperty(exports, "FxModal", { enumerable: true, get: function () { return FxModal_1.FxModal; } });
|
|
16
|
+
var FxProgressCounter_1 = require("./FxProgressCounter");
|
|
17
|
+
Object.defineProperty(exports, "FxProgressCounter", { enumerable: true, get: function () { return FxProgressCounter_1.FxProgressCounter; } });
|
|
6
18
|
var Tag_1 = require("./Tag/");
|
|
7
19
|
Object.defineProperty(exports, "Tag", { enumerable: true, get: function () { return Tag_1.Tag; } });
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import Image from 'next/image';
|
|
3
3
|
import { Slide } from '@mui/material';
|
|
4
4
|
import { imageLoader } from '@fixefy/fixefy-ui-utils';
|
|
5
|
-
import { ActionBtn, ActionTitle, ChargesCount, ChargesTitle, Close, Container, Divider, TitleWrapper } from './styles/
|
|
5
|
+
import { ActionBtn, ActionTitle, ChargesCount, ChargesTitle, Close, Container, Divider, TitleWrapper } from './styles/actions_tray.styles';
|
|
6
6
|
export function ActionsTray({ type, onApprove, onChallenge, onClick, show, onClose, chargesCount, container, direction = 'up' }) {
|
|
7
7
|
const renderActions = () => {
|
|
8
8
|
switch (type) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
export { ActionsTray } from './ActionsTray';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FxButton } from '../../FxButton';
|
|
2
2
|
import { Typography } from '@mui/material';
|
|
3
3
|
import { styled } from '@mui/material/styles';
|
|
4
4
|
const filterWhite = 'invert(99%) sepia(74%) saturate(0%) hue-rotate(253deg) brightness(108%) contrast(100%)';
|
|
@@ -46,7 +46,7 @@ export const Divider = styled('div')(({ theme }) => ({
|
|
|
46
46
|
marginRight: 24,
|
|
47
47
|
marginLeft: 24,
|
|
48
48
|
}));
|
|
49
|
-
export const ActionBtn = styled(
|
|
49
|
+
export const ActionBtn = styled(FxButton)(({ theme, type }) => ({
|
|
50
50
|
height: 40,
|
|
51
51
|
maxHeight: 40,
|
|
52
52
|
borderRadius: 100,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Stack from '@mui/material/Stack';
|
|
3
|
+
import { structureReader } from './helpers/structureReader';
|
|
4
|
+
export const AggregationsBar = (props) => {
|
|
5
|
+
const { structure, minWidth, mb, filter, initialValues } = props;
|
|
6
|
+
const { children, extended } = structure;
|
|
7
|
+
const { variables } = extended;
|
|
8
|
+
const { collapsed } = variables;
|
|
9
|
+
return (<Stack direction="row" spacing={1.5} sx={{
|
|
10
|
+
mb: mb ? mb : 0,
|
|
11
|
+
['& div']: {
|
|
12
|
+
minWidth: minWidth,
|
|
13
|
+
},
|
|
14
|
+
['& > span']: {
|
|
15
|
+
minWidth: minWidth,
|
|
16
|
+
},
|
|
17
|
+
}}>
|
|
18
|
+
{children.map((child, index) => {
|
|
19
|
+
return structureReader(child, filter, collapsed, initialValues);
|
|
20
|
+
})}
|
|
21
|
+
</Stack>);
|
|
22
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Box, Stack, Divider } from '@mui/material';
|
|
3
|
+
import { Score } from '../../Score';
|
|
4
|
+
import { StatisticsBar } from '../../StatisticsBar';
|
|
5
|
+
import { FxProgressCounter } from '../../FxProgressCounter';
|
|
6
|
+
export const structureReader = (structure, filter, collapsed, initialValues) => {
|
|
7
|
+
const { extended, type } = structure;
|
|
8
|
+
switch (type) {
|
|
9
|
+
case 'aggregations_primary_container':
|
|
10
|
+
return structure.children.map((child, index) => child.input_type?.value === 'percentage' ? (<Score structure={child} key={index} filter={filter} value={initialValues?.score}/>) : child.input_type?.value === 'progress' ? (<FxProgressCounter structure={child} filter={filter} key={index} values={initialValues}/>) : (<Box sx={{
|
|
11
|
+
display: 'flex',
|
|
12
|
+
justifyContent: 'center',
|
|
13
|
+
alignItems: 'center',
|
|
14
|
+
width: 'fit-content',
|
|
15
|
+
padding: 2,
|
|
16
|
+
borderRadius: 2,
|
|
17
|
+
backgroundColor: extended?.variables?.bg || '#FFFFFF',
|
|
18
|
+
}}>
|
|
19
|
+
<StatisticsBar structure={child} key={index} filter={filter} collapsed={collapsed} value={initialValues ? initialValues[child.extended.object_path] : null}/>
|
|
20
|
+
</Box>));
|
|
21
|
+
case 'aggregations_secondary_container':
|
|
22
|
+
return (<Stack direction="row" divider={<Divider orientation="vertical" flexItem/>} spacing={2} sx={{
|
|
23
|
+
backgroundColor: extended?.variables?.bg || '#FFFFFF',
|
|
24
|
+
borderRadius: '8px',
|
|
25
|
+
padding: '24px 16px',
|
|
26
|
+
}}>
|
|
27
|
+
{structure.children.map((child, index) => {
|
|
28
|
+
return <StatisticsBar structure={child} key={index} filter={filter} collapsed={collapsed} value={initialValues ? initialValues[child.extended.object_path] : null}/>;
|
|
29
|
+
})}
|
|
30
|
+
</Stack>);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { AggregationsBar } from './Aggregations';
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { gql } from 'graphql-tag';
|
|
2
|
+
export const STRUCTURES = gql `
|
|
3
|
+
query STRUCTURES {
|
|
4
|
+
structure(where: { name: "aggregations_invoice" }) {
|
|
5
|
+
_id
|
|
6
|
+
bundle_name
|
|
7
|
+
name
|
|
8
|
+
title
|
|
9
|
+
type
|
|
10
|
+
input_type {
|
|
11
|
+
name
|
|
12
|
+
value
|
|
13
|
+
}
|
|
14
|
+
readable_id
|
|
15
|
+
extended {
|
|
16
|
+
format
|
|
17
|
+
gql_operation
|
|
18
|
+
title_path
|
|
19
|
+
object_path
|
|
20
|
+
filter
|
|
21
|
+
variables
|
|
22
|
+
}
|
|
23
|
+
children(sort: { index: 1 }) {
|
|
24
|
+
_id
|
|
25
|
+
name
|
|
26
|
+
title
|
|
27
|
+
type
|
|
28
|
+
input_type {
|
|
29
|
+
name
|
|
30
|
+
value
|
|
31
|
+
}
|
|
32
|
+
readable_id
|
|
33
|
+
extended {
|
|
34
|
+
format
|
|
35
|
+
gql_operation
|
|
36
|
+
title_path
|
|
37
|
+
object_path
|
|
38
|
+
filter
|
|
39
|
+
variables
|
|
40
|
+
}
|
|
41
|
+
children(sort: { index: 1 }) {
|
|
42
|
+
_id
|
|
43
|
+
name
|
|
44
|
+
title
|
|
45
|
+
type
|
|
46
|
+
input_type {
|
|
47
|
+
name
|
|
48
|
+
value
|
|
49
|
+
}
|
|
50
|
+
readable_id
|
|
51
|
+
extended {
|
|
52
|
+
format
|
|
53
|
+
gql_operation
|
|
54
|
+
title_path
|
|
55
|
+
object_path
|
|
56
|
+
filter
|
|
57
|
+
variables
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
`;
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
import { Close as CloseIcon, CheckBox as CheckBoxIcon, CheckBoxOutlineBlank as CheckBoxOutlineBlankIcon, KeyboardArrowDown as ArrowIcon } from '@mui/icons-material';
|
|
3
|
+
import { gql } from 'graphql-tag';
|
|
4
|
+
import { useLazyQuery } from '@apollo/client';
|
|
5
|
+
import { titleCase } from '@fixefy/fixefy-ui-utils';
|
|
6
|
+
import React, { useEffect, useState, useRef, useImperativeHandle } from 'react';
|
|
7
|
+
import { Button, Checkbox, CircularProgress, useAutocomplete, useTheme, Typography } from '@mui/material';
|
|
8
|
+
import { Root, InputWrapper, Listbox, StyledClose, StyledListBox, Loading } from './styles/dropdown.styles';
|
|
9
|
+
const icon = <CheckBoxOutlineBlankIcon fontSize="small"/>;
|
|
10
|
+
const checkedIcon = <CheckBoxIcon fontSize="small"/>;
|
|
11
|
+
export const AsyncDropdown = React.forwardRef((props, parentRef) => {
|
|
12
|
+
const ref = useRef(null);
|
|
13
|
+
const theme = useTheme();
|
|
14
|
+
const [options, setOptions] = useState([]);
|
|
15
|
+
const [loadingData, setLoadingData] = useState(false);
|
|
16
|
+
const [isLastPage, setIsLastPage] = useState(false);
|
|
17
|
+
const [searchValue, setSearchValue] = useState(null);
|
|
18
|
+
const [hasClearBtn, setHasClearBtn] = useState(false);
|
|
19
|
+
const [page, setPage] = useState(1);
|
|
20
|
+
const [prevPage, setPrevPage] = useState(0);
|
|
21
|
+
const [pageSize, setPageSize] = useState(20);
|
|
22
|
+
const { debug, structure, onChange, onClear, renderOptions, fetcher, initialValue = {}, multiple, disabled, type = 'text', showSelectedValue, ...rest } = props;
|
|
23
|
+
const { name, extended, children } = structure;
|
|
24
|
+
const { search_path, variables } = extended;
|
|
25
|
+
const { method_name } = variables;
|
|
26
|
+
const [fetch, { data, error, loading }] = useLazyQuery(gql(fetcher.query), {
|
|
27
|
+
...fetcher.queryOptions,
|
|
28
|
+
variables: {
|
|
29
|
+
...fetcher.queryOptions.variables,
|
|
30
|
+
where: searchValue
|
|
31
|
+
? {
|
|
32
|
+
...fetcher.queryOptions.variables.where,
|
|
33
|
+
[search_path]: searchValue,
|
|
34
|
+
}
|
|
35
|
+
: {
|
|
36
|
+
...fetcher.queryOptions.variables.where,
|
|
37
|
+
},
|
|
38
|
+
skip: page * pageSize - pageSize,
|
|
39
|
+
limit: pageSize,
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
const labelOption = structure?.extended?.title_path ?? 'title';
|
|
43
|
+
const { getRootProps, getInputProps, getClearProps, getListboxProps, getOptionProps, groupedOptions, value, popupOpen, focused, setAnchorEl } = useAutocomplete({
|
|
44
|
+
...rest,
|
|
45
|
+
defaultValue: initialValue,
|
|
46
|
+
options: options,
|
|
47
|
+
disableCloseOnSelect: !!multiple,
|
|
48
|
+
multiple,
|
|
49
|
+
disabled: disabled,
|
|
50
|
+
isOptionEqualToValue: (option, value) => {
|
|
51
|
+
return option._id === value._id;
|
|
52
|
+
},
|
|
53
|
+
getOptionLabel: (option) => titleCase(option[labelOption] ?? option.title),
|
|
54
|
+
});
|
|
55
|
+
const onPopupScroll = _.debounce(() => {
|
|
56
|
+
if (ref && ref.current) {
|
|
57
|
+
const threshHold = ref.current.scrollHeight / 2;
|
|
58
|
+
if (ref.current.scrollTop > threshHold && !loadingData && !isLastPage) {
|
|
59
|
+
setLoadingData(true);
|
|
60
|
+
setPage((prevPage) => prevPage + 1);
|
|
61
|
+
setPrevPage((prevPage) => prevPage + 1);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}, 800);
|
|
65
|
+
const createTitle = () => {
|
|
66
|
+
if (Array.isArray(value)) {
|
|
67
|
+
if (value && value.length) {
|
|
68
|
+
return `${titleCase(name)} (${value.length})`;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return titleCase(name);
|
|
72
|
+
};
|
|
73
|
+
const handleSearch = _.debounce((e) => {
|
|
74
|
+
setSearchValue(e.target.value);
|
|
75
|
+
setPage(1);
|
|
76
|
+
}, 300);
|
|
77
|
+
const handleChildrens = ({ structure, ...rest }) => {
|
|
78
|
+
const { type, children } = structure;
|
|
79
|
+
debug === true && console.log('handleChildrens', structure);
|
|
80
|
+
switch (type) {
|
|
81
|
+
case 'dropdownOptions':
|
|
82
|
+
case 'dropdown_options': {
|
|
83
|
+
children.map((child) => {
|
|
84
|
+
return handleChildrens({
|
|
85
|
+
structure: child,
|
|
86
|
+
...rest,
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
case 'clear': {
|
|
92
|
+
if (!hasClearBtn) {
|
|
93
|
+
setHasClearBtn(true);
|
|
94
|
+
}
|
|
95
|
+
return <Button {...rest}>{structure.title}</Button>;
|
|
96
|
+
}
|
|
97
|
+
default: {
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
const handleRenderOptions = () => {
|
|
103
|
+
debug === true && console.log('renderOptions: ', renderOptions);
|
|
104
|
+
if (renderOptions) {
|
|
105
|
+
return groupedOptions.map((option, index) => {
|
|
106
|
+
const CustomeComponent = renderOptions(option, index);
|
|
107
|
+
return React.cloneElement(CustomeComponent, {
|
|
108
|
+
...getOptionProps({ option, index }),
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
switch (type) {
|
|
114
|
+
case 'checkbox': {
|
|
115
|
+
return groupedOptions.map((option, index) => {
|
|
116
|
+
const isSelected = getOptionProps({
|
|
117
|
+
option,
|
|
118
|
+
index,
|
|
119
|
+
})['aria-selected'];
|
|
120
|
+
return (<li {...getOptionProps({ option, index })}>
|
|
121
|
+
<Checkbox icon={icon} checked={Boolean(isSelected)} checkedIcon={checkedIcon} sx={{
|
|
122
|
+
mr: 1,
|
|
123
|
+
minWidth: 24,
|
|
124
|
+
minHeight: 24,
|
|
125
|
+
p: 0,
|
|
126
|
+
['& svg']: { fill: theme.palette.primary.light },
|
|
127
|
+
}}/>
|
|
128
|
+
<Typography variant="table" color={theme.palette.typography.title}>
|
|
129
|
+
{titleCase(option?.title)}
|
|
130
|
+
</Typography>
|
|
131
|
+
</li>);
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
case 'text': {
|
|
135
|
+
return groupedOptions.map((option, index) => {
|
|
136
|
+
debug === true && console.log('renderOptions: ', structure?.extended?.title_path, option[structure?.extended?.title_path], options);
|
|
137
|
+
return (<li {...getOptionProps({ option, index })}>
|
|
138
|
+
<Typography variant="table" color={theme.palette.typography.title}>
|
|
139
|
+
{titleCase(option[structure?.extended?.title_path] ?? option.title)}
|
|
140
|
+
</Typography>
|
|
141
|
+
</li>);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
default: {
|
|
145
|
+
return groupedOptions.map((option, index) => {
|
|
146
|
+
debug === true && console.log('renderOptions: ', structure?.extended?.title_path, option[structure?.extended?.title_path], options);
|
|
147
|
+
return (<li {...getOptionProps({ option, index })}>
|
|
148
|
+
<Typography variant="table" color={theme.palette.typography.title}>
|
|
149
|
+
{titleCase(option[structure?.extended?.title_path] ?? option.title)}
|
|
150
|
+
</Typography>
|
|
151
|
+
</li>);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
useImperativeHandle(parentRef, () => ({
|
|
158
|
+
clearDDL: () => {
|
|
159
|
+
getClearProps()?.onClick(null);
|
|
160
|
+
},
|
|
161
|
+
}));
|
|
162
|
+
useEffect(() => {
|
|
163
|
+
if (ref && ref.current) {
|
|
164
|
+
ref.current.addEventListener('scroll', () => onPopupScroll());
|
|
165
|
+
}
|
|
166
|
+
return () => {
|
|
167
|
+
if (ref && ref.current) {
|
|
168
|
+
ref.current.removeEventListener('scroll', () => onPopupScroll());
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
}, [groupedOptions]);
|
|
172
|
+
useEffect(() => {
|
|
173
|
+
onChange && onChange(value, name);
|
|
174
|
+
}, [value]);
|
|
175
|
+
useEffect(() => {
|
|
176
|
+
if (popupOpen && !isLastPage && prevPage < page && !disabled) {
|
|
177
|
+
fetch();
|
|
178
|
+
}
|
|
179
|
+
}, [popupOpen]);
|
|
180
|
+
useEffect(() => {
|
|
181
|
+
if (!disabled) {
|
|
182
|
+
fetch();
|
|
183
|
+
}
|
|
184
|
+
}, []);
|
|
185
|
+
useEffect(() => {
|
|
186
|
+
if (data && !isLastPage && prevPage < page) {
|
|
187
|
+
const newOptions = data[method_name];
|
|
188
|
+
if (newOptions.length === 0 || newOptions.length < pageSize) {
|
|
189
|
+
setIsLastPage(true);
|
|
190
|
+
}
|
|
191
|
+
setOptions([...newOptions, ...options]);
|
|
192
|
+
setLoadingData(false);
|
|
193
|
+
}
|
|
194
|
+
}, [data]);
|
|
195
|
+
return (<Root>
|
|
196
|
+
<InputWrapper hasValue={!!(value && Object.keys(value).length)} disabled={disabled} sx={{
|
|
197
|
+
width: props.styles?.width ?? 180,
|
|
198
|
+
maxWidth: props.styles?.maxWidth ?? 300,
|
|
199
|
+
}} {...getRootProps()} ref={setAnchorEl} className={focused ? 'focused' : ''}>
|
|
200
|
+
<input {...getInputProps()} readOnly onChange={(e) => {
|
|
201
|
+
getInputProps()?.onChange(e);
|
|
202
|
+
handleSearch(e);
|
|
203
|
+
}} placeholder={createTitle()} value={showSelectedValue ? titleCase(value.title) : undefined}/>
|
|
204
|
+
{loading ? (<Loading>
|
|
205
|
+
<CircularProgress />
|
|
206
|
+
</Loading>) : (<ArrowIcon />)}
|
|
207
|
+
</InputWrapper>
|
|
208
|
+
|
|
209
|
+
{groupedOptions.length > 0 && !disabled ? (<Listbox {...getListboxProps()}>
|
|
210
|
+
<StyledListBox sx={{
|
|
211
|
+
...props.styles?.menuSx,
|
|
212
|
+
}} hasClearBtn={children?.length} ref={ref}>
|
|
213
|
+
{handleRenderOptions()}
|
|
214
|
+
</StyledListBox>
|
|
215
|
+
|
|
216
|
+
{children && children.length ? (<StyledClose>
|
|
217
|
+
{handleChildrens({
|
|
218
|
+
structure: children[0],
|
|
219
|
+
onClick: (e) => {
|
|
220
|
+
onClear && onClear();
|
|
221
|
+
getClearProps()?.onClick(e);
|
|
222
|
+
},
|
|
223
|
+
startIcon: <CloseIcon />,
|
|
224
|
+
})}
|
|
225
|
+
</StyledClose>) : null}
|
|
226
|
+
</Listbox>) : null}
|
|
227
|
+
</Root>);
|
|
228
|
+
});
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
export const getJPart = (j, jsonPath, defaultValue) => {
|
|
2
|
+
if (isObjectValid(j) === false)
|
|
3
|
+
return defaultValue;
|
|
4
|
+
jsonPath = jsonPath.replace(/\[(\w+)\]/g, '.$1');
|
|
5
|
+
jsonPath = jsonPath.replace(/^\./, '');
|
|
6
|
+
let _isArrayValid = false;
|
|
7
|
+
let _isStringValid = false;
|
|
8
|
+
let currentPathPart;
|
|
9
|
+
let pathParts = jsonPath.split('.');
|
|
10
|
+
let isLoop = true;
|
|
11
|
+
for (let i = 0, n = pathParts.length; isLoop && i < n; ++i) {
|
|
12
|
+
currentPathPart = pathParts[i];
|
|
13
|
+
_isStringValid = isStringValid(j);
|
|
14
|
+
_isArrayValid = isArrayValid(j);
|
|
15
|
+
if (_isStringValid === true || _isArrayValid === true) {
|
|
16
|
+
if (_isStringValid === true) {
|
|
17
|
+
j = JSON.parse(j);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
j = j.reduce((acc, cur, idx, src) => {
|
|
21
|
+
const innerJ = getJPart(cur, pathParts.slice(i).join('.'), defaultValue);
|
|
22
|
+
if (isArrayValid(innerJ)) {
|
|
23
|
+
acc.push(...innerJ);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
acc.push({
|
|
27
|
+
...innerJ,
|
|
28
|
+
value: innerJ._id,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return acc;
|
|
32
|
+
}, []);
|
|
33
|
+
isLoop = false;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
if (currentPathPart in j) {
|
|
38
|
+
j = j[currentPathPart];
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
j = defaultValue;
|
|
42
|
+
isLoop = false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return j;
|
|
47
|
+
};
|
|
48
|
+
export const isArrayValid = (arr, minLength = 1, maxLength = 0) => {
|
|
49
|
+
let rv = isObjectValid(arr) &&
|
|
50
|
+
arr.length >= minLength &&
|
|
51
|
+
Object.prototype.toString.call(arr) == '[object Array]';
|
|
52
|
+
if (maxLength > 0) {
|
|
53
|
+
rv = rv && arr.length <= maxLength;
|
|
54
|
+
}
|
|
55
|
+
return rv;
|
|
56
|
+
};
|
|
57
|
+
export const isObjectValid = (obj, isCheckKeys = false) => {
|
|
58
|
+
let rv = typeof obj !== 'undefined' && obj !== null;
|
|
59
|
+
if (isCheckKeys) {
|
|
60
|
+
rv = rv && Object.keys(obj).length > 0;
|
|
61
|
+
}
|
|
62
|
+
return rv;
|
|
63
|
+
};
|
|
64
|
+
export const isStringValid = (str, minLength = null, maxLength = null, isValidateType = true) => {
|
|
65
|
+
let rv = isObjectValid(str) && str.toString().length > 0 && (isValidateType ? typeof str === 'string' : true);
|
|
66
|
+
if (rv === false)
|
|
67
|
+
return false;
|
|
68
|
+
if (minLength && isNaN(minLength) === false && minLength > 0) {
|
|
69
|
+
rv = rv && str.toString().length >= minLength;
|
|
70
|
+
}
|
|
71
|
+
if (rv === false)
|
|
72
|
+
return false;
|
|
73
|
+
if (maxLength && isNaN(maxLength) === false && maxLength > 0) {
|
|
74
|
+
rv = rv && str.toString().length <= maxLength;
|
|
75
|
+
}
|
|
76
|
+
return rv;
|
|
77
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { AsyncDropdown } from './AsyncDropdown';
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { styled } from '@mui/material/styles';
|
|
2
|
+
export const Root = styled('div')(() => ({
|
|
3
|
+
color: 'rgba(0,0,0,.85)',
|
|
4
|
+
fontSize: 14,
|
|
5
|
+
}));
|
|
6
|
+
export const Label = styled('label')(() => ({
|
|
7
|
+
padding: '0 0 4px',
|
|
8
|
+
lineHeight: '1.5',
|
|
9
|
+
display: 'block',
|
|
10
|
+
}));
|
|
11
|
+
export const Loading = styled('div')(() => ({
|
|
12
|
+
width: 30,
|
|
13
|
+
height: 30,
|
|
14
|
+
display: 'flex',
|
|
15
|
+
alignItems: 'center',
|
|
16
|
+
justifyContent: 'center',
|
|
17
|
+
['& span']: {
|
|
18
|
+
width: '20px !important',
|
|
19
|
+
height: '20px !important',
|
|
20
|
+
},
|
|
21
|
+
}));
|
|
22
|
+
export const InputWrapper = styled('div')(({ theme, hasValue, disabled }) => {
|
|
23
|
+
const defaultBorder = `1px solid ${theme.palette.greyscale[200]}`;
|
|
24
|
+
const hasValueBorder = `1px solid ${theme.palette.primary[500]}`;
|
|
25
|
+
const disabledBorder = `1px solid ${theme.palette.greyscale[200]}`;
|
|
26
|
+
const activeBorder = `1px solid ${theme.palette.primary[500]}`;
|
|
27
|
+
return {
|
|
28
|
+
border: disabled ? disabledBorder : hasValue ? hasValueBorder : defaultBorder,
|
|
29
|
+
backgroundColor: theme.palette.common.white,
|
|
30
|
+
borderRadius: 4,
|
|
31
|
+
padding: 1,
|
|
32
|
+
display: 'flex',
|
|
33
|
+
alignItems: 'center',
|
|
34
|
+
flexWrap: 'wrap',
|
|
35
|
+
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
36
|
+
['&:hover']: {
|
|
37
|
+
border: disabled ? disabledBorder : activeBorder,
|
|
38
|
+
borderRadius: 4,
|
|
39
|
+
},
|
|
40
|
+
['&:focus']: {
|
|
41
|
+
border: disabled ? disabledBorder : activeBorder,
|
|
42
|
+
borderRadius: 4,
|
|
43
|
+
},
|
|
44
|
+
['& > svg']: {
|
|
45
|
+
color: disabled ? theme.palette.greyscale[300] : theme.palette.primary['500'],
|
|
46
|
+
marginRight: 8,
|
|
47
|
+
},
|
|
48
|
+
['& input']: {
|
|
49
|
+
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
50
|
+
backgroundColor: theme.palette.common.white,
|
|
51
|
+
color: theme.palette.typography.title,
|
|
52
|
+
height: 36,
|
|
53
|
+
boxSizing: 'border-box',
|
|
54
|
+
padding: '4px 6px 4px 16px',
|
|
55
|
+
width: 0,
|
|
56
|
+
minWidth: 30,
|
|
57
|
+
flexGrow: 1,
|
|
58
|
+
border: 0,
|
|
59
|
+
margin: 0,
|
|
60
|
+
outline: 0,
|
|
61
|
+
...theme.typography.body1,
|
|
62
|
+
lineHeight: '20px',
|
|
63
|
+
['& ::placeholder']: {
|
|
64
|
+
color: hasValue ? theme.palette.typography.title : theme.palette.greyscale[400],
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
export const Listbox = styled('ul')(({ theme }) => ({
|
|
70
|
+
margin: 0,
|
|
71
|
+
padding: 0,
|
|
72
|
+
position: 'absolute',
|
|
73
|
+
listStyle: 'none',
|
|
74
|
+
backgroundColor: theme.palette.common.white,
|
|
75
|
+
overflow: 'auto',
|
|
76
|
+
maxHeight: 250,
|
|
77
|
+
minHeight: 250,
|
|
78
|
+
borderRadius: 4,
|
|
79
|
+
boxShadow: '0px 0px 10px rgba(86, 135, 147, 0.2)',
|
|
80
|
+
zIndex: 1,
|
|
81
|
+
maxWidth: 270,
|
|
82
|
+
minWidth: 270,
|
|
83
|
+
top: 48,
|
|
84
|
+
left: -42,
|
|
85
|
+
['& div']: {
|
|
86
|
+
textOverflow: 'ellipsis',
|
|
87
|
+
whiteSpace: 'nowrap',
|
|
88
|
+
overflow: 'hidden',
|
|
89
|
+
},
|
|
90
|
+
}));
|
|
91
|
+
export const StyledClose = styled('div')(() => ({
|
|
92
|
+
position: 'absolute',
|
|
93
|
+
bottom: 0,
|
|
94
|
+
}));
|
|
95
|
+
export const StyledListBox = styled('ul')(({ theme, hasClearBtn }) => ({
|
|
96
|
+
margin: 0,
|
|
97
|
+
padding: 0,
|
|
98
|
+
listStyle: 'none',
|
|
99
|
+
backgroundColor: theme.palette.common.white,
|
|
100
|
+
overflow: 'auto',
|
|
101
|
+
maxHeight: hasClearBtn ? 190 : 230,
|
|
102
|
+
zIndex: 1,
|
|
103
|
+
textOverflow: 'ellipsis',
|
|
104
|
+
whiteSpace: 'nowrap',
|
|
105
|
+
overflowX: 'hidden',
|
|
106
|
+
paddingTop: 8,
|
|
107
|
+
paddingBottom: 8,
|
|
108
|
+
maxWidth: 270,
|
|
109
|
+
minWidth: 270,
|
|
110
|
+
['& div']: {
|
|
111
|
+
textOverflow: 'ellipsis',
|
|
112
|
+
whiteSpace: 'nowrap',
|
|
113
|
+
overflow: 'hidden',
|
|
114
|
+
},
|
|
115
|
+
['& li']: {
|
|
116
|
+
paddingRight: 16,
|
|
117
|
+
paddingLeft: 16,
|
|
118
|
+
display: 'flex',
|
|
119
|
+
alignItems: 'center',
|
|
120
|
+
justifyContent: 'flex-start',
|
|
121
|
+
height: 40,
|
|
122
|
+
cursor: 'pointer',
|
|
123
|
+
textOverflow: 'ellipsis',
|
|
124
|
+
whiteSpace: 'nowrap',
|
|
125
|
+
overflow: 'hidden',
|
|
126
|
+
maxWidth: 270,
|
|
127
|
+
minWidth: 270,
|
|
128
|
+
},
|
|
129
|
+
['& li:hover']: {
|
|
130
|
+
backgroundColor: '#F6F9FA',
|
|
131
|
+
},
|
|
132
|
+
["& li[aria-selected='true']"]: {
|
|
133
|
+
fontWeight: 900,
|
|
134
|
+
backgroundColor: '#F6F9FA',
|
|
135
|
+
},
|
|
136
|
+
["& li[data-focus='true']"]: {
|
|
137
|
+
backgroundColor: '#F6F9FA',
|
|
138
|
+
cursor: 'pointer',
|
|
139
|
+
['& svg ']: {
|
|
140
|
+
color: 'currentColor',
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
}));
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { titleCase } from '@fixefy/fixefy-ui-utils';
|
|
3
|
+
import { stringToColor } from './helpers/stringToColor';
|
|
4
|
+
import { AvatarWrapper, StyledAvatar, StyledMoreAvatar, AvatarGroup, EditIcon, FxTooltip } from './styles/avatar.styles';
|
|
5
|
+
export function FxAvatar({ users, max = 5, isEditable = false, onEdit }) {
|
|
6
|
+
const [backgroundcolors, setBackgroundColors] = useState({});
|
|
7
|
+
const avatars = users.length > max ? users.slice(0, max - 1) : users;
|
|
8
|
+
const isMoreThanMax = users.length > max;
|
|
9
|
+
return (<AvatarWrapper>
|
|
10
|
+
<AvatarGroup>
|
|
11
|
+
{avatars.map((user, index) => {
|
|
12
|
+
const userName = user.first_name + ' ' + user.last_name;
|
|
13
|
+
return (<FxTooltip key={index} title={titleCase(userName)}>
|
|
14
|
+
<StyledAvatar sx={{
|
|
15
|
+
backgroundColor: backgroundcolors[userName]
|
|
16
|
+
? backgroundcolors[userName]
|
|
17
|
+
: stringToColor(userName, (color) => {
|
|
18
|
+
setBackgroundColors({
|
|
19
|
+
...backgroundcolors,
|
|
20
|
+
[userName]: color,
|
|
21
|
+
});
|
|
22
|
+
}),
|
|
23
|
+
}} src={user.image_url} alt={userName}>
|
|
24
|
+
{titleCase(userName.slice(0, 1))}
|
|
25
|
+
</StyledAvatar>
|
|
26
|
+
</FxTooltip>);
|
|
27
|
+
})}
|
|
28
|
+
{isMoreThanMax && <StyledMoreAvatar>{`+${users.length - max + 1}`}</StyledMoreAvatar>}
|
|
29
|
+
</AvatarGroup>
|
|
30
|
+
{isEditable && <EditIcon onClick={onEdit && onEdit}/>}
|
|
31
|
+
</AvatarWrapper>);
|
|
32
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const stringToColor = (string, callBack) => {
|
|
2
|
+
let hash = 0;
|
|
3
|
+
let color = '#';
|
|
4
|
+
for (let i = 0; i < string.length; i += 1) {
|
|
5
|
+
hash = string.charCodeAt(i) + ((hash << 5) - hash);
|
|
6
|
+
}
|
|
7
|
+
for (let i = 0; i < 3; i += 1) {
|
|
8
|
+
const value = (hash >> (i * 8)) & 0xff;
|
|
9
|
+
color += `00${value.toString(16)}`.substr(-2);
|
|
10
|
+
}
|
|
11
|
+
callBack && callBack(color);
|
|
12
|
+
return color;
|
|
13
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { FxAvatar } from './FxAvatar';
|