2024-05-09 05:56:45 -05:00
|
|
|
import { Banner, Button, IconInfo32, LoadingIndicator } from '@create-figma-plugin/ui';
|
2024-05-03 06:43:07 -05:00
|
|
|
import { useEffect, useState } from 'react';
|
|
|
|
import { FormProvider, useForm } from 'react-hook-form';
|
|
|
|
|
2024-05-09 05:56:45 -05:00
|
|
|
import { Stack } from '@ui/components/Stack';
|
2024-05-03 06:43:07 -05:00
|
|
|
import { createPenpotFile } from '@ui/converters';
|
|
|
|
import { PenpotDocument } from '@ui/lib/types/penpotDocument';
|
|
|
|
|
|
|
|
import { MissingFontsSection } from './MissingFontsSection';
|
|
|
|
|
|
|
|
type FormValues = Record<string, string>;
|
|
|
|
|
|
|
|
export const PenpotExporter = () => {
|
|
|
|
const [missingFonts, setMissingFonts] = useState<string[]>();
|
2024-05-09 05:56:45 -05:00
|
|
|
const [needsReload, setNeedsReload] = useState(false);
|
|
|
|
const [loading, setLoading] = useState(true);
|
2024-05-03 06:43:07 -05:00
|
|
|
const [exporting, setExporting] = useState(false);
|
|
|
|
const methods = useForm<FormValues>();
|
|
|
|
|
|
|
|
methods.getValues();
|
|
|
|
|
|
|
|
const onMessage = (event: MessageEvent<{ pluginMessage: { type: string; data: unknown } }>) => {
|
|
|
|
if (event.data.pluginMessage?.type == 'PENPOT_DOCUMENT') {
|
|
|
|
const document = event.data.pluginMessage.data as PenpotDocument;
|
|
|
|
const file = createPenpotFile(document);
|
|
|
|
|
|
|
|
file.export();
|
|
|
|
|
|
|
|
setExporting(false);
|
|
|
|
} else if (event.data.pluginMessage?.type == 'CUSTOM_FONTS') {
|
|
|
|
setMissingFonts(event.data.pluginMessage.data as string[]);
|
2024-05-09 05:56:45 -05:00
|
|
|
setLoading(false);
|
|
|
|
setNeedsReload(false);
|
|
|
|
} else if (event.data.pluginMessage?.type == 'CHANGES_DETECTED') {
|
|
|
|
setNeedsReload(true);
|
2024-05-03 06:43:07 -05:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const exportPenpot = (data: FormValues) => {
|
|
|
|
setExporting(true);
|
|
|
|
|
|
|
|
parent.postMessage(
|
|
|
|
{
|
|
|
|
pluginMessage: {
|
|
|
|
type: 'export',
|
|
|
|
data
|
|
|
|
}
|
|
|
|
},
|
|
|
|
'*'
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const cancel = () => {
|
|
|
|
parent.postMessage({ pluginMessage: { type: 'cancel' } }, '*');
|
|
|
|
};
|
|
|
|
|
2024-05-09 05:56:45 -05:00
|
|
|
const reload = () => {
|
|
|
|
setLoading(true);
|
|
|
|
parent.postMessage({ pluginMessage: { type: 'reload' } }, '*');
|
|
|
|
};
|
|
|
|
|
2024-05-03 06:43:07 -05:00
|
|
|
useEffect(() => {
|
|
|
|
window.addEventListener('message', onMessage);
|
|
|
|
|
|
|
|
parent.postMessage({ pluginMessage: { type: 'ready' } }, '*');
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
window.removeEventListener('message', onMessage);
|
|
|
|
};
|
|
|
|
}, []);
|
|
|
|
|
2024-05-09 05:56:45 -05:00
|
|
|
if (loading) {
|
|
|
|
return <LoadingIndicator />;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (needsReload) {
|
|
|
|
return (
|
|
|
|
<Stack space="small">
|
|
|
|
<Banner icon={<IconInfo32 />}>
|
|
|
|
Changes detected. Please reload the plug-in to ensure all modifications are included in
|
|
|
|
the exported file.
|
|
|
|
</Banner>
|
|
|
|
<Stack space="xsmall" direction="row">
|
|
|
|
<Button onClick={reload} fullWidth>
|
|
|
|
Reload
|
|
|
|
</Button>
|
|
|
|
<Button secondary onClick={cancel} fullWidth>
|
|
|
|
Cancel
|
|
|
|
</Button>
|
|
|
|
</Stack>
|
|
|
|
</Stack>
|
|
|
|
);
|
|
|
|
}
|
2024-05-03 06:43:07 -05:00
|
|
|
|
|
|
|
return (
|
|
|
|
<FormProvider {...methods}>
|
2024-05-09 05:56:45 -05:00
|
|
|
<form onSubmit={methods.handleSubmit(exportPenpot)}>
|
|
|
|
<Stack space="medium">
|
2024-05-03 06:43:07 -05:00
|
|
|
<MissingFontsSection fonts={missingFonts} />
|
2024-05-09 05:56:45 -05:00
|
|
|
<Stack space="xsmall" direction="row">
|
|
|
|
<Button type="submit" loading={exporting} fullWidth>
|
|
|
|
Export to Penpot
|
|
|
|
</Button>
|
|
|
|
<Button secondary onClick={cancel} fullWidth>
|
|
|
|
Cancel
|
|
|
|
</Button>
|
|
|
|
</Stack>
|
|
|
|
</Stack>
|
2024-05-03 06:43:07 -05:00
|
|
|
</form>
|
|
|
|
</FormProvider>
|
|
|
|
);
|
|
|
|
};
|