mirror of
https://github.com/plankanban/planka.git
synced 2025-12-25 17:25:01 +03:00
@@ -1,8 +1,26 @@
|
||||
/*!
|
||||
* Copyright (c) 2024 PLANKA Software GmbH
|
||||
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
import useNestedRef from './use-nested-ref';
|
||||
import useField from './use-field';
|
||||
import useForm from './use-form';
|
||||
import useClosable from './use-closable';
|
||||
import useEscapeInterceptor from './use-escape-interceptor';
|
||||
import useSteps from './use-steps';
|
||||
import useModal from './use-modal';
|
||||
import useClosableForm from './use-closable-form';
|
||||
import useClosableModal from './use-closable-modal';
|
||||
import usePopupInClosableContext from './use-popup-in-closable-context';
|
||||
|
||||
export { useNestedRef, useField, useForm, useSteps, useModal, useClosableForm };
|
||||
export {
|
||||
useNestedRef,
|
||||
useField,
|
||||
useForm,
|
||||
useClosable,
|
||||
useEscapeInterceptor,
|
||||
useSteps,
|
||||
useModal,
|
||||
useClosableModal,
|
||||
usePopupInClosableContext,
|
||||
};
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
import { useCallback, useEffect, useRef } from 'react';
|
||||
|
||||
export default (close, isOpened = true) => {
|
||||
const isClosable = useRef(null);
|
||||
|
||||
const handleFieldBlur = useCallback(() => {
|
||||
if (isClosable.current) {
|
||||
close();
|
||||
}
|
||||
}, [close]);
|
||||
|
||||
const handleControlMouseOver = useCallback(() => {
|
||||
isClosable.current = false;
|
||||
}, []);
|
||||
|
||||
const handleControlMouseOut = useCallback(() => {
|
||||
isClosable.current = true;
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpened) {
|
||||
isClosable.current = true;
|
||||
} else {
|
||||
isClosable.current = null;
|
||||
}
|
||||
}, [isOpened]);
|
||||
|
||||
return [handleFieldBlur, handleControlMouseOver, handleControlMouseOut];
|
||||
};
|
||||
75
client/src/hooks/use-closable-modal.jsx
Normal file
75
client/src/hooks/use-closable-modal.jsx
Normal file
@@ -0,0 +1,75 @@
|
||||
/*!
|
||||
* Copyright (c) 2024 PLANKA Software GmbH
|
||||
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Modal } from 'semantic-ui-react';
|
||||
|
||||
import useClosable from './use-closable';
|
||||
import { ClosableContext } from '../contexts';
|
||||
|
||||
export default (initialClosableValue) => {
|
||||
const [isClosableActiveRef, activateClosable, deactivateClosable, setIsClosableActive] =
|
||||
useClosable(initialClosableValue);
|
||||
|
||||
const closableContextValue = useMemo(
|
||||
() => [activateClosable, deactivateClosable, setIsClosableActive],
|
||||
[activateClosable, deactivateClosable, setIsClosableActive],
|
||||
);
|
||||
|
||||
const ClosableModal = useMemo(() => {
|
||||
// eslint-disable-next-line no-shadow
|
||||
const ClosableModal = React.memo(({ closeIcon, onClose, ...props }) => {
|
||||
const handleClose = useCallback(
|
||||
(event) => {
|
||||
if (isClosableActiveRef.current) {
|
||||
if (closeIcon && event.type === 'click') {
|
||||
if (!event.currentTarget.classList.contains('close')) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (onClose) {
|
||||
onClose();
|
||||
}
|
||||
},
|
||||
[closeIcon, onClose],
|
||||
);
|
||||
|
||||
return (
|
||||
<ClosableContext.Provider value={closableContextValue}>
|
||||
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
|
||||
<Modal open {...props} closeIcon={closeIcon} onClose={handleClose} />
|
||||
</ClosableContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
ClosableModal.propTypes = {
|
||||
closeIcon: PropTypes.bool,
|
||||
onClose: PropTypes.func,
|
||||
};
|
||||
|
||||
ClosableModal.defaultProps = {
|
||||
closeIcon: undefined,
|
||||
onClose: undefined,
|
||||
};
|
||||
|
||||
ClosableModal.Content = Modal.Content;
|
||||
ClosableModal.Actions = Modal.Actions;
|
||||
|
||||
return ClosableModal;
|
||||
}, [isClosableActiveRef, closableContextValue]);
|
||||
|
||||
return [
|
||||
ClosableModal,
|
||||
isClosableActiveRef,
|
||||
activateClosable,
|
||||
deactivateClosable,
|
||||
setIsClosableActive,
|
||||
];
|
||||
};
|
||||
26
client/src/hooks/use-closable.js
Normal file
26
client/src/hooks/use-closable.js
Normal file
@@ -0,0 +1,26 @@
|
||||
/*!
|
||||
* Copyright (c) 2024 PLANKA Software GmbH
|
||||
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
import { useCallback, useRef } from 'react';
|
||||
|
||||
export default (initialValue = false) => {
|
||||
const isActiveRef = useRef(initialValue);
|
||||
|
||||
const setIsActive = useCallback((isActive) => {
|
||||
setTimeout(() => {
|
||||
isActiveRef.current = isActive;
|
||||
});
|
||||
}, []);
|
||||
|
||||
const activate = useCallback(() => {
|
||||
setIsActive(true);
|
||||
}, [setIsActive]);
|
||||
|
||||
const deactivate = useCallback(() => {
|
||||
setIsActive(false);
|
||||
}, [setIsActive]);
|
||||
|
||||
return [isActiveRef, activate, deactivate, setIsActive];
|
||||
};
|
||||
32
client/src/hooks/use-escape-interceptor.js
Normal file
32
client/src/hooks/use-escape-interceptor.js
Normal file
@@ -0,0 +1,32 @@
|
||||
/*!
|
||||
* Copyright (c) 2024 PLANKA Software GmbH
|
||||
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
import { useCallback } from 'react';
|
||||
import { useEventCallback } from '../lib/hooks';
|
||||
|
||||
export default (onEscape) => {
|
||||
const handleWindowKeydown = useEventCallback(
|
||||
(event) => {
|
||||
if (event.key === 'Escape') {
|
||||
event.stopPropagation();
|
||||
|
||||
if (onEscape) {
|
||||
onEscape();
|
||||
}
|
||||
}
|
||||
},
|
||||
[onEscape],
|
||||
);
|
||||
|
||||
const activate = useCallback(() => {
|
||||
window.addEventListener('keydown', handleWindowKeydown, true);
|
||||
}, [handleWindowKeydown]);
|
||||
|
||||
const deactivate = useCallback(() => {
|
||||
window.removeEventListener('keydown', handleWindowKeydown, true);
|
||||
}, [handleWindowKeydown]);
|
||||
|
||||
return [activate, deactivate];
|
||||
};
|
||||
@@ -1,3 +1,8 @@
|
||||
/*!
|
||||
* Copyright (c) 2024 PLANKA Software GmbH
|
||||
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
export default (initialValue) => {
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
/*!
|
||||
* Copyright (c) 2024 PLANKA Software GmbH
|
||||
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
export default (initialData) => {
|
||||
const [data, setData] = useState(initialData);
|
||||
|
||||
const handleFieldChange = useCallback((_, { name: fieldName, value }) => {
|
||||
const handleFieldChange = useCallback((_, { type, name: fieldName, value, checked }) => {
|
||||
setData((prevData) => ({
|
||||
...prevData,
|
||||
[fieldName]: value,
|
||||
[fieldName]: type === 'radio' ? checked : value,
|
||||
}));
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
/*!
|
||||
* Copyright (c) 2024 PLANKA Software GmbH
|
||||
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
// TODO: rename?
|
||||
export default (initialParams) => {
|
||||
const [modal, setModal] = useState(() => initialParams);
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/*!
|
||||
* Copyright (c) 2024 PLANKA Software GmbH
|
||||
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
import { useCallback, useRef } from 'react';
|
||||
|
||||
export default (nestedRefName = 'ref') => {
|
||||
|
||||
35
client/src/hooks/use-popup-in-closable-context.js
Normal file
35
client/src/hooks/use-popup-in-closable-context.js
Normal file
@@ -0,0 +1,35 @@
|
||||
/*!
|
||||
* Copyright (c) 2024 PLANKA Software GmbH
|
||||
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
import { useCallback, useContext } from 'react';
|
||||
import { usePopup } from '../lib/popup';
|
||||
|
||||
import { ClosableContext } from '../contexts';
|
||||
|
||||
export default (Step, { onOpen, onClose, ...props } = {}) => {
|
||||
const [activateClosable, deactivateClosable] = useContext(ClosableContext);
|
||||
|
||||
const handleOpen = useCallback(() => {
|
||||
activateClosable();
|
||||
|
||||
if (onOpen) {
|
||||
onOpen();
|
||||
}
|
||||
}, [onOpen, activateClosable]);
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
deactivateClosable();
|
||||
|
||||
if (onClose) {
|
||||
onClose();
|
||||
}
|
||||
}, [onClose, deactivateClosable]);
|
||||
|
||||
return usePopup(Step, {
|
||||
...props,
|
||||
onOpen: handleOpen,
|
||||
onClose: handleClose,
|
||||
});
|
||||
};
|
||||
@@ -1,3 +1,8 @@
|
||||
/*!
|
||||
* Copyright (c) 2024 PLANKA Software GmbH
|
||||
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
const createStep = (type, params = {}) => {
|
||||
|
||||
Reference in New Issue
Block a user