og-image/public/script.js

165 lines
5.4 KiB
JavaScript
Raw Normal View History

2019-01-23 13:02:11 -08:00
import { toClipboard } from 'https://cdn.jsdelivr.net/npm/[email protected]/dist/copee.mjs';
2019-01-23 07:16:53 -08:00
2019-01-24 09:18:22 -08:00
const ImagePreview = ({ src, onclick, onload, loading }) => {
const style = {
filter: loading ? 'blur(5px)' : '',
opacity: loading ? 0.1 : 1,
};
2019-01-23 12:00:45 -08:00
return H('a',
2019-01-23 12:44:49 -08:00
{ className: 'image-wrapper', href: src, onclick },
2019-01-23 12:00:45 -08:00
H('img',
2019-01-24 09:18:22 -08:00
{ src, onload, style }
2019-01-23 12:00:45 -08:00
)
);
2019-01-23 07:16:53 -08:00
}
const Dropdown = ({ options, value, onchange }) => {
2019-01-23 10:59:32 -08:00
return H('div',
{ className: 'select-wrapper'},
H('select',
{ onchange: e => onchange(e.target.value) },
options.map(o =>
H('option',
{ value: o.value, selected: value === o.value },
o.text
)
2019-01-23 07:16:53 -08:00
)
2019-01-23 10:59:32 -08:00
),
H('div',
{ className: 'select-arrow' },
'▼'
2019-01-23 07:16:53 -08:00
)
);
}
2019-01-23 08:09:35 -08:00
const TextInput = ({ value, onchange }) => {
2019-01-23 10:59:32 -08:00
return H('div',
{ className: 'input-outer-wrapper' },
H('div',
{ className: 'input-inner-wrapper' },
H('input',
{ type: 'text', value, onchange: e => onchange(e.target.value) }
)
)
2019-01-23 08:09:35 -08:00
);
}
const Button = ({ label, onclick }) => {
return H('button', { onclick }, label);
2019-01-23 07:16:53 -08:00
}
const Field = ({ label, input }) => {
return H('div',
2019-01-23 10:59:32 -08:00
{ className: 'field' },
H('label', { className: 'field-label' }, label),
H('div', { className: 'field-value' }, input),
2019-01-23 07:16:53 -08:00
);
}
2019-01-23 12:00:45 -08:00
const Toast = ({ show, message }) => {
const style = { transform: show ? 'translate3d(0,-0px,-0px) scale(1)' : '' };
return H('div',
{ className: 'toast-area' },
H('div',
{ className: 'toast-outer', style },
H('div',
{ className: 'toast-inner' },
H('div',
{ className: 'toast-message'},
message
)
)
),
);
}
2019-01-23 07:16:53 -08:00
const fileTypeOptions = [
{ text: 'PNG', value: 'png' },
{ text: 'JPEG', value: 'jpeg' },
];
const fontSizeOptions = Array
.from({ length: 10 })
.map((_, i) => i * 25)
.filter(n => n > 0)
.map(n => ({ text: n + 'px', value: n + 'px' }));
const markdownOptions = [
{ text: 'Plain Text', value: '0' },
{ text: 'Markdown', value: '1' },
];
const App = (props, state, setState) => {
2019-01-24 09:18:22 -08:00
const { fileType = 'png', fontSize = '75px', md = '1', text = '**Hello** World', images=['https://assets.zeit.co/image/upload/front/assets/design/now-black.svg'], showToast = false, loading = true } = state;
const url = new URL(window.location.hostname === 'localhost' ? 'https://og-image.now.sh' : window.location.origin);
2019-01-23 08:09:35 -08:00
url.pathname = `${text}.${fileType}`;
url.searchParams.append('md', md);
url.searchParams.append('fontSize', fontSize);
2019-01-23 13:08:01 -08:00
for (let image of images) {
url.searchParams.append('images', image);
2019-01-23 08:09:35 -08:00
}
2019-01-24 09:18:22 -08:00
const setLoadingState = (newState) => {
setState({ ...newState, loading: true });
};
2019-01-23 07:16:53 -08:00
return H('div',
2019-01-23 12:22:51 -08:00
{ className: 'split' },
H('div',
2019-01-24 08:09:26 -08:00
{ className: 'pull-left' },
H('div',
H(Field, {
label: 'File Type',
2019-01-24 09:18:22 -08:00
input: H(Dropdown, { options: fileTypeOptions, value: fileType, onchange: val => setLoadingState({fileType: val}) })
2019-01-24 08:09:26 -08:00
}),
H(Field, {
label: 'Font Size',
2019-01-24 09:18:22 -08:00
input: H(Dropdown, { options: fontSizeOptions, value: fontSize, onchange: val => setLoadingState({fontSize: val}) })
2019-01-24 08:09:26 -08:00
}),
H(Field, {
label: 'Text Type',
2019-01-24 09:18:22 -08:00
input: H(Dropdown, { options: markdownOptions, value: md, onchange: val => setLoadingState({ md: val }) })
2019-01-24 08:09:26 -08:00
}),
H(Field, {
label: 'Text Input',
2019-01-24 09:18:22 -08:00
input: H(TextInput, { value: text, onchange: val => setLoadingState({ text: val }) })
2019-01-23 12:22:51 -08:00
}),
2019-01-24 08:09:26 -08:00
...images.map((image, i) => H(Field, {
label: `Image ${i + 1}`,
2019-01-24 09:18:22 -08:00
input: H(TextInput, { value: image, onchange: val => { let clone = [...images]; clone[i] = val; setLoadingState({ images: clone }) } })
2019-01-24 08:09:26 -08:00
})),
H(Field, {
label: `Image ${images.length + 1}`,
input: H(Button, {
label: `Add Image ${images.length + 1}`,
2019-01-24 09:18:22 -08:00
onclick: () => { setLoadingState({ images: [...images, ''] }) }
2019-01-24 08:09:26 -08:00
}),
}),
)
2019-01-23 12:22:51 -08:00
),
H('div',
2019-01-24 08:09:26 -08:00
{ clasName: 'pull-right' },
2019-01-23 12:22:51 -08:00
H(ImagePreview, {
src: url.href,
2019-01-24 09:18:22 -08:00
loading: loading,
onload: e => setState({ loading: false }),
2019-01-23 12:22:51 -08:00
onclick: e => {
e.preventDefault();
2019-01-23 13:02:11 -08:00
const success = toClipboard(url.href);
2019-01-23 12:22:51 -08:00
if (success) {
setState({ showToast: true });
setTimeout(() => setState({ showToast: false }), 3000);
} else {
window.open(url.href, '_blank');
}
return false;
2019-01-23 12:00:45 -08:00
}
2019-01-23 12:22:51 -08:00
})
2019-01-24 08:09:26 -08:00
),
H(Toast, {
message: 'Copied image URL to clipboard',
show: showToast,
})
2019-01-23 12:22:51 -08:00
);
2019-01-23 07:16:53 -08:00
};
2019-01-23 08:09:35 -08:00
2019-01-23 12:00:45 -08:00
R(H(App), document.getElementById('generated'));