Update call link edit/add name modals
This commit is contained in:
parent
ba77ef7563
commit
b691e24d5c
20 changed files with 526 additions and 232 deletions
28
ts/components/CallLinkAddNameModal.stories.tsx
Normal file
28
ts/components/CallLinkAddNameModal.stories.tsx
Normal file
|
@ -0,0 +1,28 @@
|
|||
// Copyright 2024 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React from 'react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
import type { CallLinkAddNameModalProps } from './CallLinkAddNameModal';
|
||||
import { CallLinkAddNameModal } from './CallLinkAddNameModal';
|
||||
import type { ComponentMeta } from '../storybook/types';
|
||||
import { FAKE_CALL_LINK_WITH_ADMIN_KEY } from '../test-both/helpers/fakeCallLink';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
export default {
|
||||
title: 'Components/CallLinkAddNameModal',
|
||||
component: CallLinkAddNameModal,
|
||||
args: {
|
||||
i18n,
|
||||
callLink: FAKE_CALL_LINK_WITH_ADMIN_KEY,
|
||||
onClose: action('onClose'),
|
||||
onUpdateCallLinkName: action('onUpdateCallLinkName'),
|
||||
},
|
||||
} satisfies ComponentMeta<CallLinkAddNameModalProps>;
|
||||
|
||||
export function Basic(args: CallLinkAddNameModalProps): JSX.Element {
|
||||
return <CallLinkAddNameModal {...args} />;
|
||||
}
|
98
ts/components/CallLinkAddNameModal.tsx
Normal file
98
ts/components/CallLinkAddNameModal.tsx
Normal file
|
@ -0,0 +1,98 @@
|
|||
// Copyright 2024 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { v4 as generateUuid } from 'uuid';
|
||||
import { Modal } from './Modal';
|
||||
import type { LocalizerType } from '../types/I18N';
|
||||
import { Button, ButtonVariant } from './Button';
|
||||
import { Avatar, AvatarSize } from './Avatar';
|
||||
import { Input } from './Input';
|
||||
import type { CallLinkType } from '../types/CallLink';
|
||||
|
||||
export type CallLinkAddNameModalProps = Readonly<{
|
||||
i18n: LocalizerType;
|
||||
callLink: CallLinkType;
|
||||
onClose: () => void;
|
||||
onUpdateCallLinkName: (name: string) => void;
|
||||
}>;
|
||||
|
||||
export function CallLinkAddNameModal({
|
||||
i18n,
|
||||
callLink,
|
||||
onClose,
|
||||
onUpdateCallLinkName,
|
||||
}: CallLinkAddNameModalProps): JSX.Element {
|
||||
const [formId] = useState(() => generateUuid());
|
||||
const [nameId] = useState(() => generateUuid());
|
||||
const [nameInput, setNameInput] = useState(callLink.name);
|
||||
|
||||
const handleNameInputChange = useCallback((nextNameInput: string) => {
|
||||
setNameInput(nextNameInput);
|
||||
}, []);
|
||||
|
||||
const handleSubmit = useCallback(() => {
|
||||
const nameValue = nameInput.trim();
|
||||
if (nameValue === callLink.name) {
|
||||
return;
|
||||
}
|
||||
onUpdateCallLinkName(nameValue);
|
||||
onClose();
|
||||
}, [nameInput, callLink, onUpdateCallLinkName, onClose]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
modalName="CallLinkAddNameModal"
|
||||
i18n={i18n}
|
||||
hasXButton
|
||||
noEscapeClose
|
||||
noMouseClose
|
||||
title={i18n('icu:CallLinkAddNameModal__Title')}
|
||||
onClose={onClose}
|
||||
moduleClassName="CallLinkAddNameModal"
|
||||
modalFooter={
|
||||
<>
|
||||
<Button onClick={onClose} variant={ButtonVariant.Secondary}>
|
||||
{i18n('icu:cancel')}
|
||||
</Button>
|
||||
<Button type="submit" form={formId} variant={ButtonVariant.Primary}>
|
||||
{i18n('icu:save')}
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<form
|
||||
id={formId}
|
||||
onSubmit={handleSubmit}
|
||||
className="CallLinkAddNameModal__Row"
|
||||
>
|
||||
<Avatar
|
||||
i18n={i18n}
|
||||
badge={undefined}
|
||||
conversationType="callLink"
|
||||
size={AvatarSize.SIXTY_FOUR}
|
||||
acceptedMessageRequest
|
||||
isMe={false}
|
||||
sharedGroupNames={[]}
|
||||
title={
|
||||
callLink.name === ''
|
||||
? i18n('icu:calling__call-link-default-title')
|
||||
: callLink.name
|
||||
}
|
||||
/>
|
||||
|
||||
<label htmlFor={nameId} className="CallLinkAddNameModal__SrOnly">
|
||||
{i18n('icu:CallLinkAddNameModal__NameLabel')}
|
||||
</label>
|
||||
<Input
|
||||
i18n={i18n}
|
||||
id={nameId}
|
||||
value={nameInput}
|
||||
placeholder={i18n('icu:CallLinkAddNameModal__NameLabel')}
|
||||
autoFocus
|
||||
onChange={handleNameInputChange}
|
||||
moduleClassName="CallLinkAddNameModal__Input"
|
||||
/>
|
||||
</form>
|
||||
</Modal>
|
||||
);
|
||||
}
|
|
@ -20,7 +20,7 @@ export default {
|
|||
callLink: FAKE_CALL_LINK_WITH_ADMIN_KEY,
|
||||
onClose: action('onClose'),
|
||||
onCopyCallLink: action('onCopyCallLink'),
|
||||
onUpdateCallLinkName: action('onUpdateCallLinkName'),
|
||||
onOpenCallLinkAddNameModal: action('onOpenCallLinkAddNameModal'),
|
||||
onUpdateCallLinkRestrictions: action('onUpdateCallLinkRestrictions'),
|
||||
onShareCallLinkViaSignal: action('onShareCallLinkViaSignal'),
|
||||
onStartCallLinkLobby: action('onStartCallLinkLobby'),
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// Copyright 2024 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import type { ReactNode } from 'react';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import { v4 as generateUuid } from 'uuid';
|
||||
import { Modal } from './Modal';
|
||||
import type { LocalizerType } from '../types/I18N';
|
||||
|
@ -10,19 +11,67 @@ import {
|
|||
toCallLinkRestrictions,
|
||||
type CallLinkType,
|
||||
} from '../types/CallLink';
|
||||
import { Input } from './Input';
|
||||
import { Select } from './Select';
|
||||
import { linkCallRoute } from '../util/signalRoutes';
|
||||
import { Button, ButtonSize, ButtonVariant } from './Button';
|
||||
import { Avatar, AvatarSize } from './Avatar';
|
||||
import { formatUrlWithoutProtocol } from '../util/url';
|
||||
|
||||
const CallLinkEditModalRowIconClasses = {
|
||||
Edit: 'CallLinkEditModal__RowIcon--Edit',
|
||||
Approve: 'CallLinkEditModal__RowIcon--Approve',
|
||||
Copy: 'CallLinkEditModal__RowIcon--Copy',
|
||||
Share: 'CallLinkEditModal__RowIcon--Share',
|
||||
} as const;
|
||||
|
||||
function RowIcon({
|
||||
icon,
|
||||
}: {
|
||||
icon: keyof typeof CallLinkEditModalRowIconClasses;
|
||||
}) {
|
||||
return (
|
||||
<i
|
||||
role="presentation"
|
||||
className={`CallLinkEditModal__RowIcon ${CallLinkEditModalRowIconClasses[icon]}`}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function RowText({ children }: { children: ReactNode }) {
|
||||
return <div className="CallLinkEditModal__RowLabel">{children}</div>;
|
||||
}
|
||||
|
||||
function Row({ children }: { children: ReactNode }) {
|
||||
return <div className="CallLinkEditModal__Row">{children}</div>;
|
||||
}
|
||||
|
||||
function RowButton({
|
||||
onClick,
|
||||
children,
|
||||
}: {
|
||||
onClick: () => void;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<button
|
||||
className="CallLinkEditModal__RowButton"
|
||||
type="button"
|
||||
onClick={onClick}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
function Hr() {
|
||||
return <hr className="CallLinkEditModal__Hr" />;
|
||||
}
|
||||
|
||||
export type CallLinkEditModalProps = {
|
||||
i18n: LocalizerType;
|
||||
callLink: CallLinkType;
|
||||
onClose: () => void;
|
||||
onCopyCallLink: () => void;
|
||||
onUpdateCallLinkName: (name: string) => void;
|
||||
onOpenCallLinkAddNameModal: () => void;
|
||||
onUpdateCallLinkRestrictions: (restrictions: CallLinkRestrictions) => void;
|
||||
onShareCallLinkViaSignal: () => void;
|
||||
onStartCallLinkLobby: () => void;
|
||||
|
@ -33,64 +82,32 @@ export function CallLinkEditModal({
|
|||
callLink,
|
||||
onClose,
|
||||
onCopyCallLink,
|
||||
onUpdateCallLinkName,
|
||||
onOpenCallLinkAddNameModal,
|
||||
onUpdateCallLinkRestrictions,
|
||||
onShareCallLinkViaSignal,
|
||||
onStartCallLinkLobby,
|
||||
}: CallLinkEditModalProps): JSX.Element {
|
||||
const { name: savedName, restrictions: savedRestrictions } = callLink;
|
||||
|
||||
const [nameId] = useState(() => generateUuid());
|
||||
const [restrictionsId] = useState(() => generateUuid());
|
||||
|
||||
const [nameInput, setNameInput] = useState(savedName);
|
||||
const [restrictionsInput, setRestrictionsInput] = useState(savedRestrictions);
|
||||
|
||||
// We only want to use the default name "Signal Call" as a value if the user
|
||||
// modified the input and then chose that name. Doesn't revert when saved.
|
||||
const [nameTouched, setNameTouched] = useState(false);
|
||||
|
||||
const callLinkWebUrl = useMemo(() => {
|
||||
return formatUrlWithoutProtocol(
|
||||
linkCallRoute.toWebUrl({ key: callLink.rootKey })
|
||||
);
|
||||
return linkCallRoute.toWebUrl({ key: callLink.rootKey }).toString();
|
||||
}, [callLink.rootKey]);
|
||||
|
||||
const onSaveName = useCallback(
|
||||
(newName: string) => {
|
||||
if (!nameTouched) {
|
||||
return;
|
||||
}
|
||||
if (newName === savedName) {
|
||||
return;
|
||||
}
|
||||
onUpdateCallLinkName(newName);
|
||||
},
|
||||
[nameTouched, savedName, onUpdateCallLinkName]
|
||||
);
|
||||
|
||||
const onSaveRestrictions = useCallback(
|
||||
(newRestrictions: CallLinkRestrictions) => {
|
||||
if (newRestrictions === savedRestrictions) {
|
||||
return;
|
||||
}
|
||||
onUpdateCallLinkRestrictions(newRestrictions);
|
||||
},
|
||||
[savedRestrictions, onUpdateCallLinkRestrictions]
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
i18n={i18n}
|
||||
modalName="CallLinkEditModal"
|
||||
moduleClassName="CallLinkEditModal"
|
||||
title={i18n('icu:CallLinkEditModal__Title')}
|
||||
hasXButton
|
||||
onClose={() => {
|
||||
// Save the modal in case the user hits escape
|
||||
onSaveName(nameInput);
|
||||
onClose();
|
||||
}}
|
||||
noEscapeClose
|
||||
noMouseClose
|
||||
padded={false}
|
||||
modalFooter={
|
||||
<Button type="submit" variant={ButtonVariant.Primary} onClick={onClose}>
|
||||
{i18n('icu:done')}
|
||||
</Button>
|
||||
}
|
||||
onClose={onClose}
|
||||
>
|
||||
<div className="CallLinkEditModal__Header">
|
||||
<Avatar
|
||||
|
@ -101,114 +118,96 @@ export function CallLinkEditModal({
|
|||
acceptedMessageRequest
|
||||
isMe={false}
|
||||
sharedGroupNames={[]}
|
||||
title={callLink.name ?? i18n('icu:calling__call-link-default-title')}
|
||||
title={
|
||||
callLink.name === ''
|
||||
? i18n('icu:calling__call-link-default-title')
|
||||
: callLink.name
|
||||
}
|
||||
/>
|
||||
<div className="CallLinkEditModal__Header__Details">
|
||||
<label htmlFor={nameId} className="CallLinkEditModal__SrOnly">
|
||||
{i18n('icu:CallLinkEditModal__InputLabel--Name--SrOnly')}
|
||||
</label>
|
||||
<Input
|
||||
moduleClassName="CallLinkEditModal__Input--Name"
|
||||
i18n={i18n}
|
||||
value={
|
||||
nameInput === '' && !nameTouched
|
||||
? i18n('icu:calling__call-link-default-title')
|
||||
: nameInput
|
||||
}
|
||||
maxByteCount={120}
|
||||
onChange={value => {
|
||||
setNameTouched(true);
|
||||
setNameInput(value);
|
||||
}}
|
||||
onBlur={() => {
|
||||
onSaveName(nameInput);
|
||||
}}
|
||||
onEnter={() => {
|
||||
onSaveName(nameInput);
|
||||
}}
|
||||
placeholder={i18n('icu:calling__call-link-default-title')}
|
||||
/>
|
||||
|
||||
<div className="CallLinkEditModal__CallLinkAndJoinButton">
|
||||
<button
|
||||
className="CallLinkEditModal__CopyUrlTextButton"
|
||||
type="button"
|
||||
onClick={onCopyCallLink}
|
||||
aria-label={i18n('icu:CallLinkDetails__CopyLink')}
|
||||
>
|
||||
{callLinkWebUrl}
|
||||
</button>
|
||||
<Button
|
||||
onClick={onStartCallLinkLobby}
|
||||
size={ButtonSize.Small}
|
||||
variant={ButtonVariant.SecondaryAffirmative}
|
||||
className="CallLinkEditModal__JoinButton"
|
||||
>
|
||||
{i18n('icu:CallLinkEditModal__JoinButtonLabel')}
|
||||
</Button>
|
||||
<div className="CallLinkEditModal__Header__Title">
|
||||
{callLink.name === ''
|
||||
? i18n('icu:calling__call-link-default-title')
|
||||
: callLink.name}
|
||||
</div>
|
||||
<button
|
||||
className="CallLinkEditModal__Header__CallLinkButton"
|
||||
type="button"
|
||||
onClick={onCopyCallLink}
|
||||
aria-label={i18n('icu:CallLinkDetails__CopyLink')}
|
||||
>
|
||||
<div className="CallLinkEditModal__Header__CallLinkButton__Text">
|
||||
{callLinkWebUrl}
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div className="CallLinkEditModal__Header__Actions">
|
||||
<Button
|
||||
onClick={onStartCallLinkLobby}
|
||||
size={ButtonSize.Small}
|
||||
variant={ButtonVariant.SecondaryAffirmative}
|
||||
className="CallLinkEditModal__JoinButton"
|
||||
>
|
||||
{i18n('icu:CallLinkEditModal__JoinButtonLabel')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="CallLinkEditModal__ApproveAllMembers__Row"
|
||||
// For testing, to easily check the restrictions saved
|
||||
data-restrictions={savedRestrictions}
|
||||
>
|
||||
<label
|
||||
htmlFor={restrictionsId}
|
||||
className="CallLinkEditModal__ApproveAllMembers__Label"
|
||||
>
|
||||
{i18n('icu:CallLinkEditModal__InputLabel--ApproveAllMembers')}
|
||||
</label>
|
||||
<Hr />
|
||||
|
||||
<RowButton onClick={onOpenCallLinkAddNameModal}>
|
||||
<Row>
|
||||
<RowIcon icon="Edit" />
|
||||
<RowText>{i18n('icu:CallLinkEditModal__AddCallNameLabel')}</RowText>
|
||||
</Row>
|
||||
</RowButton>
|
||||
|
||||
<Row>
|
||||
<RowIcon icon="Approve" />
|
||||
<RowText>
|
||||
<label htmlFor={restrictionsId}>
|
||||
{i18n('icu:CallLinkEditModal__InputLabel--ApproveAllMembers')}
|
||||
</label>
|
||||
</RowText>
|
||||
<Select
|
||||
id={restrictionsId}
|
||||
value={restrictionsInput}
|
||||
value={String(callLink.restrictions)}
|
||||
moduleClassName="CallLinkEditModal__RowSelect"
|
||||
options={[
|
||||
{
|
||||
value: CallLinkRestrictions.None,
|
||||
value: String(CallLinkRestrictions.None),
|
||||
text: i18n(
|
||||
'icu:CallLinkEditModal__ApproveAllMembers__Option--Off'
|
||||
),
|
||||
},
|
||||
{
|
||||
value: CallLinkRestrictions.AdminApproval,
|
||||
value: String(CallLinkRestrictions.AdminApproval),
|
||||
text: i18n(
|
||||
'icu:CallLinkEditModal__ApproveAllMembers__Option--On'
|
||||
),
|
||||
},
|
||||
]}
|
||||
onChange={value => {
|
||||
const newRestrictions = toCallLinkRestrictions(value);
|
||||
setRestrictionsInput(newRestrictions);
|
||||
onSaveRestrictions(newRestrictions);
|
||||
onUpdateCallLinkRestrictions(toCallLinkRestrictions(value));
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Row>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="CallLinkEditModal__ActionButton"
|
||||
onClick={onCopyCallLink}
|
||||
>
|
||||
<i
|
||||
role="presentation"
|
||||
className="CallLinkEditModal__ActionButton__Icon CallLinkEditModal__ActionButton__Icon--Copy"
|
||||
/>
|
||||
{i18n('icu:CallLinkDetails__CopyLink')}
|
||||
</button>
|
||||
<Hr />
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="CallLinkEditModal__ActionButton"
|
||||
onClick={onShareCallLinkViaSignal}
|
||||
>
|
||||
<i
|
||||
role="presentation"
|
||||
className="CallLinkEditModal__ActionButton__Icon CallLinkEditModal__ActionButton__Icon--Share"
|
||||
/>
|
||||
{i18n('icu:CallLinkDetails__ShareLinkViaSignal')}
|
||||
</button>
|
||||
<RowButton onClick={onCopyCallLink}>
|
||||
<Row>
|
||||
<RowIcon icon="Copy" />
|
||||
<RowText>{i18n('icu:CallLinkDetails__CopyLink')}</RowText>
|
||||
</Row>
|
||||
</RowButton>
|
||||
|
||||
<RowButton onClick={onShareCallLinkViaSignal}>
|
||||
<Row>
|
||||
<RowIcon icon="Share" />
|
||||
<RowText>{i18n('icu:CallLinkDetails__ShareLinkViaSignal')}</RowText>
|
||||
</Row>
|
||||
</RowButton>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ export function EditNicknameAndNoteModal({
|
|||
}, [givenName, familyName, note]);
|
||||
|
||||
const handleSubmit = useCallback(
|
||||
(event: MouseEvent | FormEvent) => {
|
||||
(event: FormEvent) => {
|
||||
event.preventDefault();
|
||||
if (formResult.success) {
|
||||
onSave(formResult.data);
|
||||
|
@ -104,7 +104,6 @@ export function EditNicknameAndNoteModal({
|
|||
type="submit"
|
||||
form={formId}
|
||||
aria-disabled={!formResult.success}
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
{i18n('icu:save')}
|
||||
</Button>
|
||||
|
@ -124,7 +123,7 @@ export function EditNicknameAndNoteModal({
|
|||
theme={undefined}
|
||||
/>
|
||||
</div>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<form id={formId} onSubmit={handleSubmit}>
|
||||
<label
|
||||
htmlFor={givenNameId}
|
||||
className="EditNicknameAndNoteModal__Label"
|
||||
|
|
|
@ -29,6 +29,9 @@ export type PropsType = {
|
|||
// AddUserToAnotherGroupModal
|
||||
addUserToAnotherGroupModalContactId: string | undefined;
|
||||
renderAddUserToAnotherGroup: () => JSX.Element;
|
||||
// CallLinkAddNameModal
|
||||
callLinkAddNameModalRoomId: string | null;
|
||||
renderCallLinkAddNameModal: () => JSX.Element;
|
||||
// CallLinkEditModal
|
||||
callLinkEditModalRoomId: string | null;
|
||||
renderCallLinkEditModal: () => JSX.Element;
|
||||
|
@ -105,6 +108,9 @@ export function GlobalModalContainer({
|
|||
// AddUserToAnotherGroupModal
|
||||
addUserToAnotherGroupModalContactId,
|
||||
renderAddUserToAnotherGroup,
|
||||
// CallLinkAddNameModal
|
||||
callLinkAddNameModalRoomId,
|
||||
renderCallLinkAddNameModal,
|
||||
// CallLinkEditModal
|
||||
callLinkEditModalRoomId,
|
||||
renderCallLinkEditModal,
|
||||
|
@ -194,6 +200,10 @@ export function GlobalModalContainer({
|
|||
return renderAddUserToAnotherGroup();
|
||||
}
|
||||
|
||||
if (callLinkAddNameModalRoomId) {
|
||||
return renderCallLinkAddNameModal();
|
||||
}
|
||||
|
||||
if (callLinkEditModalRoomId) {
|
||||
return renderCallLinkEditModal();
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import { useRefMerger } from '../hooks/useRefMerger';
|
|||
import { byteLength } from '../Bytes';
|
||||
|
||||
export type PropsType = {
|
||||
autoFocus?: boolean;
|
||||
countBytes?: (value: string) => number;
|
||||
countLength?: (value: string) => number;
|
||||
disabled?: boolean;
|
||||
|
@ -63,6 +64,7 @@ export const Input = forwardRef<
|
|||
PropsType
|
||||
>(function InputInner(
|
||||
{
|
||||
autoFocus,
|
||||
countBytes = byteLength,
|
||||
countLength = grapheme.count,
|
||||
disabled,
|
||||
|
@ -206,6 +208,7 @@ export const Input = forwardRef<
|
|||
const isTextarea = expandable || forceTextarea;
|
||||
|
||||
const inputProps = {
|
||||
autoFocus,
|
||||
className: classNames(
|
||||
getClassName('__input'),
|
||||
icon && getClassName('__input--with-icon'),
|
||||
|
|
|
@ -43,6 +43,7 @@ type PropsType = {
|
|||
|
||||
export type ModalPropsType = PropsType & {
|
||||
noTransform?: boolean;
|
||||
noEscapeClose?: boolean;
|
||||
noMouseClose?: boolean;
|
||||
theme?: Theme;
|
||||
};
|
||||
|
@ -57,6 +58,7 @@ export function Modal({
|
|||
modalFooter,
|
||||
modalHeaderChildren,
|
||||
moduleClassName,
|
||||
noEscapeClose,
|
||||
noMouseClose,
|
||||
onBackButtonClick,
|
||||
onClose = noop,
|
||||
|
@ -114,6 +116,7 @@ export function Modal({
|
|||
<ModalHost
|
||||
modalName={modalName}
|
||||
moduleClassName={moduleClassName}
|
||||
noEscapeClose={noEscapeClose}
|
||||
noMouseClose={noMouseClose}
|
||||
onClose={close}
|
||||
onEscape={onBackButtonClick}
|
||||
|
|
|
@ -27,6 +27,7 @@ export type PropsType = Readonly<{
|
|||
children: React.ReactElement;
|
||||
modalName: string;
|
||||
moduleClassName?: string;
|
||||
noEscapeClose?: boolean;
|
||||
noMouseClose?: boolean;
|
||||
onClose: () => unknown;
|
||||
onEscape?: () => unknown;
|
||||
|
@ -40,6 +41,7 @@ export const ModalHost = React.memo(function ModalHostInner({
|
|||
children,
|
||||
modalName,
|
||||
moduleClassName,
|
||||
noEscapeClose,
|
||||
noMouseClose,
|
||||
onClose,
|
||||
onEscape,
|
||||
|
@ -72,7 +74,7 @@ export const ModalHost = React.memo(function ModalHostInner({
|
|||
};
|
||||
}, [modalContainer]);
|
||||
|
||||
useEscapeHandling(onEscape || onClose);
|
||||
useEscapeHandling(noEscapeClose ? noop : onEscape || onClose);
|
||||
useEffect(() => {
|
||||
if (noMouseClose) {
|
||||
return noop;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue