mirror of
https://github.com/LukeHagar/sveltesociety.dev.git
synced 2025-12-09 20:57:44 +00:00
Add component snippet generator (#108)
This commit is contained in:
@@ -12,7 +12,7 @@ import prettier from 'prettier';
|
||||
const files = [
|
||||
'src/routes/components/components.json',
|
||||
'src/routes/templates/templates.json',
|
||||
'src/routes/tooling/tools.json'
|
||||
'src/routes/tools/tools.json'
|
||||
];
|
||||
|
||||
if (!process.env.GH_TOKEN) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
const linksLeft = [
|
||||
['/templates', 'templates'],
|
||||
['/components', 'components'],
|
||||
['/tooling', 'tooling']
|
||||
['/tools', 'tools']
|
||||
];
|
||||
const linksRight = [
|
||||
['/recipes', 'recipes'],
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<a href="/help/components" class="submit">Submit a component</a>
|
||||
<a href="/help/submitting?type=component" class="submit">Submit a component</a>
|
||||
<input
|
||||
class="searchbar"
|
||||
type="text"
|
||||
|
||||
271
src/routes/help/submitting.svelte
Normal file
271
src/routes/help/submitting.svelte
Normal file
@@ -0,0 +1,271 @@
|
||||
<script>
|
||||
import SvelteSelect from 'svelte-select';
|
||||
import components from '../components/components.json';
|
||||
import templates from '../templates/templates.json';
|
||||
import tools from '../tools/tools.json';
|
||||
import { tick } from 'svelte';
|
||||
import { page } from '$app/stores';
|
||||
import { copyToClipboard } from '$lib/utils/clipboard';
|
||||
import { extractUnique } from '$lib/utils/extractUnique';
|
||||
|
||||
const repoURL = 'https://github.com/svelte-society/sveltesociety.dev';
|
||||
const typeQuery = $page.query.get('type');
|
||||
const types = ['Component', 'Template', 'Tool'].map((t) => ({
|
||||
label: t,
|
||||
value: t.toLowerCase()
|
||||
}));
|
||||
|
||||
const data = {
|
||||
component: {
|
||||
tags: extractUnique(components, 'tags'),
|
||||
categories: [...extractUnique(components, 'category').filter((cat) => cat.label !== '')]
|
||||
},
|
||||
template: {
|
||||
tags: extractUnique(templates, 'tags'),
|
||||
categories: extractUnique(templates, 'category')
|
||||
},
|
||||
tool: {
|
||||
tags: extractUnique(tools, 'tags'),
|
||||
categories: extractUnique(tools, 'category')
|
||||
}
|
||||
};
|
||||
|
||||
let clipboardCopy = false;
|
||||
const copy = () => {
|
||||
copyToClipboard(JSON.stringify(jsonSnippet, null, 4)).then(() => (clipboardCopy = false));
|
||||
clipboardCopy = true;
|
||||
};
|
||||
|
||||
let type = types.find((t) => t.value == typeQuery) || types[0];
|
||||
let title = 'svelte-lorem-ipsum';
|
||||
let url = 'https://github.com/sveltejs/svelte-lorem-ipsum';
|
||||
let description = 'A dummy text generator that does not exist';
|
||||
let npm = 'svelte-lorem-ipsum';
|
||||
let addedOn = todaysDate();
|
||||
let category;
|
||||
let tags;
|
||||
|
||||
$: pathName = `${type.value}s`;
|
||||
$: jsonSnippet = {
|
||||
title,
|
||||
url,
|
||||
description,
|
||||
npm,
|
||||
addedOn,
|
||||
category: category?.value,
|
||||
tags: tags?.map((tag) => tag.value)
|
||||
};
|
||||
|
||||
$: currentTags = data[type.value].tags;
|
||||
$: currentCategories = data[type.value].categories;
|
||||
|
||||
function padWithZero(date) {
|
||||
return date.toString().padStart(2, '0');
|
||||
}
|
||||
|
||||
function todaysDate() {
|
||||
const date = new Date();
|
||||
const day = padWithZero(date.getDate());
|
||||
const month = padWithZero(date.getMonth() + 1);
|
||||
const year = date.getFullYear();
|
||||
const sep = '-';
|
||||
return [year, month, day].join(sep);
|
||||
}
|
||||
|
||||
async function clearCategoryAndTags() {
|
||||
await tick();
|
||||
category = null;
|
||||
tags = null;
|
||||
}
|
||||
</script>
|
||||
|
||||
<h1>Submitting a new component</h1>
|
||||
<p>
|
||||
To add a new component on the website, the process is rather simple. You have to add a snippet in
|
||||
the appropriate file.
|
||||
</p>
|
||||
|
||||
<h2>Generating file contents snippet</h2>
|
||||
<p>
|
||||
Each component is represented by a JSON Object. Use the generator below to generate the Object.
|
||||
</p>
|
||||
|
||||
<p><code>*</code> marked fields are required</p>
|
||||
<div class="json-generator">
|
||||
<div class="input-wrapper">
|
||||
<label for="type">Type:</label>
|
||||
<div>
|
||||
<SvelteSelect
|
||||
id="type"
|
||||
items={types}
|
||||
isClearable={false}
|
||||
showIndicator
|
||||
bind:value={type}
|
||||
on:select={clearCategoryAndTags}
|
||||
/>
|
||||
<span class="input-helper">The type of snippet to generate</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-wrapper">
|
||||
<label for="title" class="required">Title:</label>
|
||||
<div>
|
||||
<input id="title" type="text" required bind:value={title} />
|
||||
<span class="input-helper">Name of the component</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-wrapper">
|
||||
<label for="url">URL:</label>
|
||||
<div>
|
||||
<input id="url" type="url" bind:value={url} />
|
||||
<span class="input-helper">The URL where to find it</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-wrapper">
|
||||
<label for="desc">Description:</label>
|
||||
<div>
|
||||
<input id="desc" type="text" bind:value={description} />
|
||||
<span class="input-helper">A short description of the component</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-wrapper">
|
||||
<label for="npm">NPM:</label>
|
||||
<div>
|
||||
<input id="npm" type="text" bind:value={npm} />
|
||||
<span class="input-helper">The npm name of the component</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-wrapper">
|
||||
<label for="adden-on" class="required">Added On:</label>
|
||||
<div>
|
||||
<input id="adden-on" type="date" required bind:value={addedOn} />
|
||||
<span class="input-helper">
|
||||
The date when the component have been added on the website (generally it’s today)
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-wrapper">
|
||||
<label for="category">Category:</label>
|
||||
<div>
|
||||
<SvelteSelect
|
||||
id="category"
|
||||
items={currentCategories}
|
||||
isClearable={false}
|
||||
showIndicator
|
||||
bind:value={category}
|
||||
/>
|
||||
<span class="input-helper">The category of the component</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-wrapper">
|
||||
<label for="tags" class="required">Tags:</label>
|
||||
<div>
|
||||
<SvelteSelect id="category" items={currentTags} showIndicator isMulti bind:value={tags} />
|
||||
<span class="input-helper">A list of tags</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>JSON Snippet</h2>
|
||||
<pre>
|
||||
{JSON.stringify(jsonSnippet,null,4)}<button on:click={copy}>{clipboardCopy ? 'Copied' : 'Copy'}</button>
|
||||
</pre>
|
||||
<br />
|
||||
Copy this snippet and add it to
|
||||
<a href="{repoURL}/blob/staging/src/routes/{pathName}/{pathName}.json">{pathName}.json</a>. You can
|
||||
propose your changes
|
||||
<a href="{repoURL}/edit/staging/src/routes/{pathName}/{pathName}.json">directly in GitHub</a>.
|
||||
|
||||
<style>
|
||||
.json-generator,
|
||||
pre {
|
||||
max-width: var(--s-max);
|
||||
padding: var(--s-4);
|
||||
border-radius: 14px;
|
||||
background-color: #f3f6f9;
|
||||
}
|
||||
|
||||
.json-generator {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: var(--s-4) var(--s-20);
|
||||
padding-block: var(--s-5);
|
||||
}
|
||||
|
||||
.input-wrapper {
|
||||
--borderRadius: 5px;
|
||||
--border: 2px solid var(--dark-gray);
|
||||
--borderFocusColor: var(--secondary);
|
||||
--borderHoverColor: var(--secondary);
|
||||
--itemIsActiveBG: var(--secondary);
|
||||
--multiItemActiveBG: var(--secondary);
|
||||
--indicatorColor: var(--dark-gray);
|
||||
--indicatorTop: calc(50% - 13px);
|
||||
|
||||
display: flex;
|
||||
gap: var(--s-4);
|
||||
}
|
||||
|
||||
.input-wrapper label {
|
||||
min-width: 10ch;
|
||||
}
|
||||
|
||||
.input-wrapper > div {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
gap: var(--s-1);
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
padding: var(--s-2) 16px;
|
||||
border: var(--border);
|
||||
border-radius: var(--borderRadius);
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
input:hover,
|
||||
input:focus {
|
||||
outline: none;
|
||||
border-color: var(--borderFocusColor);
|
||||
}
|
||||
|
||||
.input-helper {
|
||||
color: var(--dark-gray);
|
||||
font-size: var(--font-100);
|
||||
}
|
||||
|
||||
.required::after {
|
||||
content: '*';
|
||||
color: var(--error);
|
||||
}
|
||||
|
||||
pre {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
pre button {
|
||||
position: absolute;
|
||||
top: var(--s-4);
|
||||
right: var(--s-4);
|
||||
padding: var(--s-1);
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
color: var(--white);
|
||||
background-color: var(--primary-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 700px) {
|
||||
.json-generator {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 450px) {
|
||||
.input-wrapper {
|
||||
flex-direction: column;
|
||||
gap: var(--s-1);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -13,7 +13,7 @@
|
||||
let filterTag = [];
|
||||
let selectedTags = null;
|
||||
|
||||
const categoryItems = [{ label: 'all', value: null }, ...extractUnique(components, 'category')];
|
||||
const categoryItems = [{ label: 'All', value: null }, ...extractUnique(components, 'category')];
|
||||
let selectedCategory = null;
|
||||
let filterCategory = null;
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
isClearable={false}
|
||||
/>
|
||||
|
||||
<a href="/help/components" class="submit">Submit a template</a>
|
||||
<a href="/help/submitting?type=template" class="submit">Submit a template</a>
|
||||
</div>
|
||||
|
||||
<input
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
let filterTag = [];
|
||||
let selectedTags = null;
|
||||
|
||||
const categoryItems = [{ label: 'all', value: null }, ...extractUnique(components, 'category')];
|
||||
const categoryItems = [{ label: 'All', value: null }, ...extractUnique(components, 'category')];
|
||||
let selectedCategory = null;
|
||||
let filterCategory = null;
|
||||
|
||||
@@ -50,10 +50,10 @@
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Tooling - Svelte Society</title>
|
||||
<title>Tools - Svelte Society</title>
|
||||
</svelte:head>
|
||||
|
||||
<SearchLayout title="Tooling">
|
||||
<SearchLayout title="Tools">
|
||||
<section slot="controls" class="controls">
|
||||
<div class="inputs">
|
||||
<Select bind:value={selectedTags} items={tagItems} isMulti label="Tags" />
|
||||
@@ -72,7 +72,7 @@
|
||||
showIndicator
|
||||
isClearable={false}
|
||||
/>
|
||||
<a href="/help/components" class="submit">Submit a tool</a>
|
||||
<a href="/help/submitting?type=tool" class="submit">Submit a tool</a>
|
||||
</div>
|
||||
|
||||
<input
|
||||
Reference in New Issue
Block a user