feat: Version 2

Closes #627, closes #1047
This commit is contained in:
Maksim Eltyshev
2025-05-10 02:09:06 +02:00
parent ad7fb51cfa
commit 2ee1166747
1557 changed files with 76832 additions and 47042 deletions

View File

@@ -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,
};

View File

@@ -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];
};

View 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,
];
};

View 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];
};

View 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];
};

View File

@@ -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) => {

View File

@@ -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,
}));
}, []);

View File

@@ -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);

View File

@@ -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') => {

View 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,
});
};

View File

@@ -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 = {}) => {