PromptCommands.svelte 6.03 KB
Newer Older
Timothy J. Baek's avatar
Timothy J. Baek committed
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
<script lang="ts">
	import { findWordIndices } from '$lib/utils';
	import { tick } from 'svelte';

	export let prompt = '';

	let selectedCommandIdx = 0;

	let promptCommands = [
		{
			command: '/article',
			title: 'Article Generator',
			content: `Write an article about [topic]

include relevant statistics (add the links of the sources you use) and consider diverse perspectives. Write it in a [X_tone] and mention the source links in the end.`
		},
		{
			command: '/backlink',

			title: 'Backlink Outreach Email',
			content: `Write a link-exchange outreach email on behalf of [your name] from [your_company] to ask for a backlink from their [website_url] to [your website url].`
		},
		{
			command: '/faq',

			title: 'FAQ Generator',
			content: `Create a list of [10] frequently asked questions about [keyword] and provide answers for each one of them considering the SERP and rich result guidelines.`
		},
		{
			command: '/headline',

			title: 'Headline Generator',
			content: `Generate 10 attention-grabbing headlines for an article about [your topic]`
		},
		{
			command: '/product',

			title: 'Product Description',
			content: `Craft an irresistible product description that highlights the benefits of [your product]`
		},
		{
			command: '/seo',

			title: 'SEO Content Brief',
			content: `Create a SEO content brief for [keyword].`
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
149
		},
		{
			command: '/seo-ideas',

			title: 'SEO Keyword Ideas',
			content: `Generate a list of 20 keyword ideas on [topic].

Cluster this list of keywords according to funnel stages whether they are top of the funnel, middle of the funnel or bottom of the funnel keywords.`
		},
		{
			command: '/summary',

			title: 'Short Summary',
			content: `Write a summary in 50 words that summarizes [topic or keyword].`
		},
		{
			command: '/email-subject',

			title: 'Email Subject Line',
			content: `Develop [5] subject lines for a cold email offering your [product or service] to a potential client.`
		},
		{
			command: '/facebook-ads',

			title: 'Facebook Ads',
			content: `Create 3 variations of effective ad copy to promote [product] for [audience].

Make sure they are [persuasive/playful/emotional] and mention these benefits:

[Benefit 1]

[Benefit 2]

[Benefit 3]

Finish with a call to action saying [CTA].

Add 3 emojis to it.`
		},
		{
			command: '/google-ads',

			title: 'Google Ads',
			content: `Create 10 google ads (a headline and a description) for [product description] targeting the keyword [keyword].

The headline of the ad needs to be under 30 characters. The description needs to be under 90 characters. Format the output as a table.`
		},
		{
			command: '/insta-caption',

			title: 'Instagram Caption',
			content: `Write 5 variations of Instagram captions for [product].

Use friendly, human-like language that appeals to [target audience].

Emphasize the unique qualities of [product],

use ample emojis, and don't sound too promotional.`
		},
		{
			command: '/linkedin-post',

			title: 'LinkedIn Post',
			content: `Create a narrative Linkedin post using immersive writing about [topic].

Details:

[give details in bullet point format]

Use a mix of short and long sentences. Make it punchy and dramatic.`
		},
		{
			command: '/youtube-desc',

			title: 'YouTube Video',
			content: `Write a 100-word YouTube video description that compels [audience]

to watch a video on [topic]

and mentions the following keywords

[keyword 1]

[keyword 2]

[keyword 3].`
		},
		{
			command: '/seo-meta',

			title: 'SEO Meta',
			content: `Suggest a meta description for the content above, make it user-friendly and with a call to action, include the keyword [keyword].`
		},
		{
			command: '/eli5',

			title: 'ELI5',
			content: `You are an expert teacher with the ability to explain complex topics in simpler terms. Explain the concept of [topic] in simple terms, so that my [grade level/subject] class can understand [this concept/specific example]?`
		},
		{
			command: '/emoji-translate',

			title: 'Emoji Translation',
			content: `You are an emoji expert. Using only emojis, translate the following text to emojis. [insert numbered sentences].`
Timothy J. Baek's avatar
Timothy J. Baek committed
150
151
152
153
154
		}
	];

	let filteredPromptCommands = [];

155
156
157
	$: filteredPromptCommands = promptCommands
		.filter((p) => p.command.includes(prompt))
		.sort((a, b) => a.title.localeCompare(b.title));
Timothy J. Baek's avatar
Timothy J. Baek committed
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227

	$: if (prompt) {
		selectedCommandIdx = 0;
	}

	export const selectUp = () => {
		selectedCommandIdx = Math.max(0, selectedCommandIdx - 1);
	};

	export const selectDown = () => {
		selectedCommandIdx = Math.min(selectedCommandIdx + 1, filteredPromptCommands.length - 1);
	};

	const confirmCommand = async (command) => {
		prompt = command.content;

		const chatInputElement = document.getElementById('chat-textarea');

		await tick();

		chatInputElement.style.height = '';
		chatInputElement.style.height = Math.min(chatInputElement.scrollHeight, 200) + 'px';

		chatInputElement?.focus();

		await tick();

		const words = findWordIndices(prompt);

		if (words.length > 0) {
			const word = words.at(0);
			chatInputElement.setSelectionRange(word?.startIndex, word.endIndex + 1);
		}
	};
</script>

{#if filteredPromptCommands.length > 0}
	<div class="md:px-2 mb-3 text-left w-full">
		<div class="flex w-full rounded-lg border border-gray-100 dark:border-gray-700">
			<div class=" bg-gray-100 dark:bg-gray-700 w-10 rounded-l-lg text-center">
				<div class=" text-lg font-medium mt-2">/</div>
			</div>
			<div class=" max-h-60 overflow-y-auto bg-white w-full p-2 rounded-r-lg space-y-0.5">
				{#each filteredPromptCommands as command, commandIdx}
					<button
						class=" px-3 py-1.5 rounded-lg w-full text-left {commandIdx === selectedCommandIdx
							? ' bg-gray-100 selected-command-option-button'
							: ''}"
						type="button"
						on:click={() => {
							confirmCommand(command);
						}}
						on:mousemove={() => {
							selectedCommandIdx = commandIdx;
						}}
						on:focus={() => {}}
					>
						<div class=" font-medium text-black">
							{command.command}
						</div>

						<div class=" text-xs text-gray-600">
							{command.title}
						</div>
					</button>
				{/each}
			</div>
		</div>
	</div>
{/if}