PageSourceSearch

https://occm-og.vercel.app/dist/web/index.js

js occm-og.vercel.app collected 2026-10-03 07:25:12 UTC 9,946 bytes, 236 lines download raw bytes

1const { H, R, copee } = window;
2let timeout = -1;
3const ImagePreview = ({ src, onclick, onload, onerror, loading }) => {
4    const style = {
5        filter: loading ? 'blur(5px)' : '',
6        opacity: loading ? 0.1 : 1,
7    };
8    const title = 'Click to copy image URL to clipboard';
9    return H('a', { className: 'image-wrapper', href: src, onclick }, H('img', { src, onload, onerror, style, title }));
10};
11const Dropdown = ({ options, value, onchange, small }) => {
12    const wrapper = small ? 'select-wrapper small' : 'select-wrapper';
13    const arrow = small ? 'select-arrow small' : 'select-arrow';
14    return H('div', { className: wrapper }, H('select', { onchange: (e) => onchange(e.target.value) }, options.map(o => H('option', { value: o.value, selected: value === o.value }, o.text))), H('div', { className: arrow }, '▼'));
15};
16const TextInput = ({ value, oninput, small, type = 'text', placeholder = '' }) => {
17    return H('div', { className: 'input-outer-wrapper' + (small ? ' small' : '') }, H('div', { className: 'input-inner-wrapper' }, H('input', { type, value, placeholder, oninput: (e) => oninput(e.target.value) })));
18};
19const Button = ({ label, onclick }) => {
20    return H('button', { onclick }, label);
21};
22const Field = ({ label, input }) => {
23    return H('div', { className: 'field' }, H('label', H('div', { className: 'field-label' }, label), H('div', { className: 'field-value' }, input)));
24};
25const Toast = ({ show, message }) => {
26    const style = { transform: show ? 'translate3d(0,-0px,-0px) scale(1)' : '' };
27    return H('div', { className: 'toast-area' }, H('div', { className: 'toast-outer', style }, H('div', { className: 'toast-inner' }, H('div', { className: 'toast-message' }, message))));
28};
29const themeOptions = [
30    { text: 'Light', value: 'light' },
31    { text: 'Dark', value: 'dark' },
32];
33const fileTypeOptions = [
34    { text: 'PNG', value: 'png' },
35    { text: 'JPEG', value: 'jpeg' },
36];
37const fontSizeOptions = Array
38    .from({ length: 10 })
39    .map((_, i) => i * 25)
40    .filter(n => n > 0)
41    .map(n => ({ text: n + 'px', value: n + 'px' }));
42const markdownOptions = [
43    { text: 'Plain Text', value: '0' },
44    { text: 'Markdown', value: '1' },
45];
46const imageLightOptions = [
47    { text: 'Vercel', value: 'https://assets.vercel.com/image/upload/front/assets/design/vercel-triangle-black.svg' },
48    { text: 'Next.js', value: 'https://assets.vercel.com/image/upload/front/assets/design/nextjs-black-logo.svg' },
49    { text: 'Hyper', value: 'https://assets.vercel.com/image/upload/front/assets/design/hyper-color-logo.svg' },
50];
51const imageDarkOptions = [
52    { text: 'Vercel', value: 'https://assets.vercel.com/image/upload/front/assets/design/vercel-triangle-white.svg' },
53    { text: 'Next.js', value: 'https://assets.vercel.com/image/upload/front/assets/design/nextjs-white-logo.svg' },
54    { text: 'Hyper', value: 'https://assets.vercel.com/image/upload/front/assets/design/hyper-bw-logo.svg' },
55];
56const App = (_, state, setState) => {
57    const setLoadingState = (newState) => {
58        window.clearTimeout(timeout);
59        if (state.overrideUrl && state.overrideUrl !== newState.overrideUrl) {
60            newState.overrideUrl = state.overrideUrl;
61        }
62        if (newState.overrideUrl) {
63            timeout = window.setTimeout(() => setState({ overrideUrl: null }), 200);
64        }
65        setState({ ...newState, loading: true });
66    };
67    const { fileType = 'png', fontSize = '100px', theme = 'light', md = true, text = '**Hello** World', images = [imageLightOptions[0].value], widths = [], heights = [], showToast = false, messageToast = '', loading = true, selectedImageIndex = 0, overrideUrl = null, } = state;
68    const mdValue = md ? '1' : '0';
69    const imageOptions = theme === 'light' ? imageLightOptions : imageDarkOptions;
70    const url = new URL(window.location.origin);
71    url.pathname = `${encodeURIComponent(text)}.${fileType}`;
72    url.searchParams.append('theme', theme);
73    url.searchParams.append('md', mdValue);
74    url.searchParams.append('fontSize', fontSize);
75    for (let image of images) {
76        url.searchParams.append('images', image);
77    }
78    for (let width of widths) {
79        url.searchParams.append('widths', width);
80    }
81    for (let height of heights) {
82        url.searchParams.append('heights', height);
83    }
84    return H('div', { className: 'split' }, H('div', { className: 'pull-left' }, H('div', H(Field, {
85        label: 'Theme',
86        input: H(Dropdown, {
87            options: themeOptions,
88            value: theme,
89            onchange: (val) => {
90                const options = val === 'light' ? imageLightOptions : imageDarkOptions;
91                let clone = [...images];
92                clone[0] = options[selectedImageIndex].value;
93                setLoadingState({ theme: val, images: clone });
94            }
95        })
96    }), H(Field, {
97        label: 'File Type',
98        input: H(Dropdown, {
99            options: fileTypeOptions,
100            value: fileType,
101            onchange: (val) => setLoadingState({ fileType: val })
102        })
103    }), H(Field, {
104        label: 'Font Size',
105        input: H(Dropdown, {
106            options: fontSizeOptions,
107            value: fontSize,
108            onchange: (val) => setLoadingState({ fontSize: val })
109        })
110    }), H(Field, {
111        label: 'Text Type',
112        input: H(Dropdown, {
113            options: markdownOptions,
114            value: mdValue,
115            onchange: (val) => setLoadingState({ md: val === '1' })
116        })
117    }), H(Field, {
118        label: 'Text Input',
119        input: H(TextInput, {
120            value: text,
121            oninput: (val) => {
122                console.log('oninput ' + val);
123                setLoadingState({ text: val, overrideUrl: url });
124            }
125        })
126    }), H(Field, {
127        label: 'Image 1',
128        input: H('div', H(Dropdown, {
129            options: imageOptions,
130            value: imageOptions[selectedImageIndex].value,
131            onchange: (val) => {
132                let clone = [...images];
133                clone[0] = val;
134                const selected = imageOptions.map(o => o.value).indexOf(val);
135                setLoadingState({ images: clone, selectedImageIndex: selected });
136            }
137        }), H('div', { className: 'field-flex' }, H(TextInput, {
138            value: widths[0],
139            type: 'number',
140            placeholder: 'width',
141            small: true,
142            oninput: (val) => {
143                let clone = [...widths];
144                clone[0] = val;
145                setLoadingState({ widths: clone });
146            }
147        }), H(TextInput, {
148            value: heights[0],
149            type: 'number',
150            placeholder: 'height',
151            small: true,
152            oninput: (val) => {
153                let clone = [...heights];
154                clone[0] = val;
155                setLoadingState({ heights: clone });
156            }
157        }))),
158    }), ...images.slice(1).map((image, i) => H(Field, {
159        label: `Image ${i + 2}`,
160        input: H('div', H(TextInput, {
161            value: image,
162            oninput: (val) => {
163                let clone = [...images];
164                clone[i + 1] = val;
165                setLoadingState({ images: clone, overrideUrl: url });
166            }
167        }), H('div', { className: 'field-flex' }, H(TextInput, {
168            value: widths[i + 1],
169            type: 'number',
170            placeholder: 'width',
171            small: true,
172            oninput: (val) => {
173                let clone = [...widths];
174                clone[i + 1] = val;
175                setLoadingState({ widths: clone });
176            }
177        }), H(TextInput, {
178            value: heights[i + 1],
179            type: 'number',
180            placeholder: 'height',
181            small: true,
182            oninput: (val) => {
183                let clone = [...heights];
184                clone[i + 1] = val;
185                setLoadingState({ heights: clone });
186            }
187        })), H('div', { className: 'field-flex' }, H(Button, {
188            label: `Remove Image ${i + 2}`,
189            onclick: (e) => {
190                e.preventDefault();
191                const filter = (arr) => [...arr].filter((_, n) => n !== i + 1);
192                const imagesClone = filter(images);
193                const widthsClone = filter(widths);
194                const heightsClone = filter(heights);
195                setLoadingState({ images: imagesClone, widths: widthsClone, heights: heightsClone });
196            }
197        })))
198    })), H(Field, {
199        label: `Image ${images.length + 1}`,
200        input: H(Button, {
201            label: `Add Image ${images.length + 1}`,
202            onclick: () => {
203                const nextImage = images.length === 1
204                    ? 'https://cdn.jsdelivr.net/gh/remojansen/logo.ts@master/ts.svg'
205                    : '';
206                setLoadingState({ images: [...images, nextImage] });
207            }
208        }),
209    }))), H('div', { className: 'pull-right' }, H(ImagePreview, {
210        src: overrideUrl ? overrideUrl.href : url.href,
211        loading: loading,
212        onload: () => setState({ loading: false }),
213        onerror: () => {
214            setState({ showToast: true, messageToast: 'Oops, an error occurred' });
215            setTimeout(() => setState({ showToast: false }), 2000);
216        },
217        onclick: (e) => {
218            e.preventDefault();
219            const success = copee.toClipboard(url.href);
220            if (success) {
221                setState({ showToast: true, messageToast: 'Copied image URL to clipboard' });
222                setTimeout(() => setState({ showToast: false }), 3000);
223            }
224            else {
225                window.open(url.href, '_blank');
226            }
227            return false;
228        }
229    })), H(Toast, {
230        message: messageToast,
231        show: showToast,
232    }));
233};
234R(H(App), document.getElementById('app'));
235export {};
236//# sourceMappingURL=index.js.map

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.