Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | 14x 14x | import { ThemeProvider } from '@automattic/jetpack-components';
import { useDispatch, useSelect } from '@wordpress/data';
import { useCallback } from '@wordpress/element';
import { __, isRTL, sprintf } from '@wordpress/i18n';
import { chevronLeft, chevronRight } from '@wordpress/icons';
import { Dialog, IconButton, Text, Tooltip } from '@wordpress/ui';
import { store as socialStore } from '../../social-store';
import { PlatformInput } from './platform-input';
import { SelectPlatform } from './select-platform';
import type { ConnectionFlowStep } from '../../social-store/types';
/**
* Placeholder body shown until a step's own component lands. Each of M2-01…04
* replaces its branch in `renderStep` with the real step UI.
*
* @param props - Props.
* @param props.step - The step being rendered.
* @return The placeholder body.
*/
const StepPlaceholder = ( { step }: { step: ConnectionFlowStep } ) => (
<Text variant="body-sm" render={ <p /> }>
{ step }
</Text>
);
/**
* Step router: maps the current connection-flow step to its content.
*
* @param step - The current flow step.
* @return The step content.
*/
function renderStep( step: ConnectionFlowStep ): JSX.Element {
switch ( step ) {
case 'select-platform':
return <SelectPlatform />;
case 'platform-input':
return <PlatformInput />;
case 'authorizing':
case 'confirm':
case 'creating':
return <StepPlaceholder step={ step } />;
}
}
/**
* The dialog title for the current step. `platform-input` names the chosen
* platform; the other steps use a static title.
*
* @param step - The current flow step.
* @param serviceLabel - Label of the selected service, for `platform-input`.
* @return The dialog title.
*/
function getStepTitle( step: ConnectionFlowStep, serviceLabel: string ): string {
switch ( step ) {
case 'select-platform':
return __( 'Select your account platform', 'jetpack-publicize-pkg' );
case 'platform-input':
return sprintf(
// translators: %s is the platform name, e.g. "Mastodon".
__( 'Connect %s account', 'jetpack-publicize-pkg' ),
serviceLabel
);
default:
return __( 'Add an account', 'jetpack-publicize-pkg' );
}
}
/**
* The open connection-flow dialog. Only rendered while the flow is active, so
* the controlled `open` prop stays `true` and any close intent (Esc, backdrop,
* close button) routes through `onOpenChange` to reset the flow.
*
* @return The dialog.
*/
const ConnectionFlowDialog = () => {
const { step, canGoBack, serviceLabel } = useSelect( select => {
const {
getConnectionFlowStep,
canGoToPreviousConnectionFlowStep,
getConnectionFlowSelectedServiceId,
getService,
} = select( socialStore );
const serviceId = getConnectionFlowSelectedServiceId();
return {
step: getConnectionFlowStep(),
canGoBack: canGoToPreviousConnectionFlowStep(),
serviceLabel: serviceId ? getService( serviceId )?.label ?? '' : '',
};
}, [] );
const { cancelConnectionFlow, goToPreviousStep } = useDispatch( socialStore );
const onOpenChange = useCallback(
( open: boolean ) => {
if ( ! open ) {
cancelConnectionFlow();
}
},
[ cancelConnectionFlow ]
);
if ( ! step ) {
return null;
}
return (
<Tooltip.Provider delay={ 0 }>
<Dialog.Root open onOpenChange={ onOpenChange }>
<Dialog.Popup size="medium">
<Dialog.Header>
{ canGoBack && (
<IconButton
variant="minimal"
tone="neutral"
size="small"
icon={ isRTL() ? chevronRight : chevronLeft }
label={ __( 'Back', 'jetpack-publicize-pkg' ) }
onClick={ goToPreviousStep }
/>
) }
<Dialog.Title>{ getStepTitle( step, serviceLabel ) }</Dialog.Title>
<Dialog.CloseIcon />
</Dialog.Header>
<Dialog.Content>{ renderStep( step ) }</Dialog.Content>
</Dialog.Popup>
</Dialog.Root>
</Tooltip.Provider>
);
};
/**
* Container for the redesigned add-account flow. Mirrors `ThemedConnectionsModal`:
* it self-gates on the store's flow state and portals into `document.body` under
* its own theme, so mount sites can render it unconditionally. Callers open it by
* dispatching `startConnectionFlow`.
*
* @return The themed connection-flow modal.
*/
export function ConnectionFlowModal() {
const isActive = useSelect( select => select( socialStore ).isConnectionFlowActive(), [] );
return (
<ThemeProvider targetDom={ document.body }>
{ isActive ? <ConnectionFlowDialog /> : null }
</ThemeProvider>
);
}
|