1
0
mirror of https://github.com/garraflavatra/rolens.git synced 2025-07-18 22:04:05 +00:00

Initial commit

This commit is contained in:
2023-01-10 17:28:27 +01:00
commit 101d892139
45 changed files with 7976 additions and 0 deletions

View File

@ -0,0 +1,28 @@
<script>
export let code = '';
</script>
<div class="examplecode">
<strong>CLI command</strong>
<code>{code}</code>
</div>
<style>
.examplecode {
border: 1px solid #ccc;
border-radius: 10px;
padding: 0.5rem;
opacity: 0.6;
margin-bottom: 0.5rem;
}
strong {
display: inline-block;
margin-right: 1rem;
font-weight: 700;
}
code {
user-select: all;
}
</style>

View File

@ -0,0 +1,167 @@
<script>
import { createEventDispatcher } from 'svelte';
import Icon from './icon.svelte';
export let columns = [];
export let items = [];
export let key = 'id';
export let activeKey = '';
export let activeChildKey = '';
export let showHeaders = true;
export let level = 0;
export let contained = false;
const dispatch = createEventDispatcher();
const childrenOpen = {};
$: _items = objectToArray(items).map(item => {
item.children = objectToArray(item.children);
return item;
});
function objectToArray(obj) {
if (Array.isArray(obj)) {
return obj;
}
else if (typeof obj === 'object') {
return Object.entries(obj).map(([ k, item ]) => ({ ...item, [key]: k }));
}
else {
return obj;
}
}
function select(itemKey) {
activeKey = itemKey;
activeChildKey = '';
dispatch('select', itemKey);
}
function selectChild(itemKey, childKey) {
select(itemKey);
activeChildKey = childKey;
dispatch('selectChild', childKey);
}
function toggleChildren(itemKey) {
childrenOpen[itemKey] = !childrenOpen[itemKey];
}
</script>
<div class:grid={level === 0} class:subgrid={level > 0} class:contained>
<table>
{#if showHeaders && columns.some(col => col.title)}
<thead>
<tr>
<th class="has-toggle"></th>
{#each columns as column}
<th scope="col">{column.title || ''}</th>
{/each}
</tr>
</thead>
{/if}
<tbody>
{#each _items as item (item[key])}
<tr on:click={() => select(item[key])} class:selected={activeKey === item[key] && !activeChildKey}>
<td class="has-toggle">
{#if item.children}
<button class="toggle" on:click={() => toggleChildren(item[key])}>
<Icon name={childrenOpen[item[key]] ? 'chev-d' : 'chev-r'} />
</button>
{/if}
</td>
{#each columns as column}
{@const value = item[column.key]}
<td class:right={column.right}>
{#if typeof value !== 'object'}
{value || ''}
{/if}
</td>
{/each}
</tr>
{#if item.children && childrenOpen[item[key]]}
<tr>
<td></td>
<td colspan={columns.length + 1} class="subgrid-parent">
<svelte:self
{columns}
{key}
bind:activeKey={activeChildKey}
showHeaders={false}
items={item.children}
level={level + 1}
on:select={e => selectChild(item[key], e.detail)}
/>
</td>
</tr>
{/if}
{/each}
</tbody>
</table>
</div>
<style>
.grid {
background-color: #fff;
height: 100%;
width: 100%;
overflow: scroll;
}
.grid.contained {
border: 1px solid #ccc;
}
.subgrid {
width: 100%;
}
table {
border-collapse: collapse;
width: 100%;
}
table thead {
border-bottom: 2px solid #ccc;
}
table th {
font-weight: 600;
text-align: left;
}
tr {
cursor: pointer;
}
td, th {
padding: 0.3rem;
height: 100%;
}
td.has-toggle {
width: calc(20px + 0.3rem);
}
td.subgrid-parent {
padding: 0;
}
table tbody tr.selected td {
background-color: #00008b;
color: #fff;
}
button.toggle {
color: inherit;
padding: 0;
}
button.toggle :global(svg) {
width: 15px;
height: 15px;
vertical-align: top;
}
.right {
text-align: right;
}
</style>

View File

@ -0,0 +1,15 @@
<script>
export let name;
</script>
{#if name === 'radio'}
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-radio"><circle cx="12" cy="12" r="2"></circle><path d="M16.24 7.76a6 6 0 0 1 0 8.49m-8.48-.01a6 6 0 0 1 0-8.49m11.31-2.82a10 10 0 0 1 0 14.14m-14.14 0a10 10 0 0 1 0-14.14"></path></svg>
{:else if name === 'chev-r'}
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"><polyline points="9 18 15 12 9 6"></polyline></svg>
{:else if name === 'chev-d'}
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-down"><polyline points="6 9 12 15 18 9"></polyline></svg>
{:else if name === 'db'}
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-database"><ellipse cx="12" cy="5" rx="9" ry="3"></ellipse><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"></path><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"></path></svg>
{:else if name === 'x'}
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-x"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
{/if}

View File

@ -0,0 +1,105 @@
<script>
import { fade, fly } from 'svelte/transition';
import Icon from './icon.svelte';
export let show = false;
export let title = undefined;
export let contentPadding = true;
</script>
{#if show}
<div class="modal outer" on:mousedown|self={close} transition:fade>
<div class="inner" transition:fly={{ y: 100 }}>
<header>
{#if title}
<div class="title">{title}</div>
{/if}
<button class="btn close" on:click={() => show = false} title="close">
<Icon name="x" />
</button>
</header>
<div class="slot content" class:p-0={!contentPadding}> <slot /> </div>
{#if $$slots.footerLeft || $$slots.footerRight}
<footer>
<slot name="footer" />
</footer>
{/if}
</div>
</div>
{/if}
<style>
.outer {
position: fixed;
display: flex;
z-index: 100;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.5);
margin: 0;
padding-top: 1rem;
cursor: pointer;
}
.inner {
max-width: 80vw;
max-height: 80vh;
background-color: #fff;
margin-left: auto;
margin-right: auto;
margin-bottom: auto;
width: 100%;
border-radius: 10px;
display: flex;
flex-direction: column;
cursor: auto;
}
.inner > :global(*:first-child) {
margin-top: 0;
}
.inner > :global(*:last-child) {
margin-bottom: 0;
}
header {
border-bottom: 1px solid #ccc;
display: flex;
align-items: center;
padding: 1rem;
}
header .title {
font-size: 1.5rem;
}
.close {
margin-left: auto;
}
.content {
padding: 1rem;
overflow-y: auto;
max-height: 100%;
}
footer {
padding: 1rem;
border-top: 1px solid #ccc;
}
@media (max-width: 600px) {
.outer {
padding: 0;
}
.inner {
max-width: 100%;
max-height: 100%;
width: 100%;
margin-top: auto;
margin-bottom: 0;
}
}
</style>

View File

@ -0,0 +1,64 @@
<script>
import Grid from './grid.svelte';
export let data = [];
export let key = '_id';
export let showHeaders = false;
export let contained = true;
console.log(data);
let items = [];
$: if (data) {
items = [];
if (Array.isArray(data)) {
for (const item of data) {
const _item = {};
_item.key = item[key];
_item.children = dissectObject(item);
items = [ ...items, _item ];
}
}
else {
items = dissectObject(data);
console.log(items);
}
}
function getType(value) {
if (Array.isArray(value)) {
return `array (${value.length} item${value.length === 1 ? '' : 's'})`;
}
else if (new Date(value).toString() !== 'Invalid Date') {
return 'date';
}
else if (typeof value === 'object') {
const keys = Object.keys(value);
return `object (${keys.length} item${keys.length === 1 ? '' : 's'})`;
}
else {
return typeof value;
}
}
function dissectObject(object) {
return Object.entries(object).map(([ key, value ]) => {
const type = getType(value);
const child = { key, value, type };
if (type.startsWith('object')) {
child.children = dissectObject(value);
}
return child;
});
}
</script>
<Grid columns={[
{ key: 'key', label: 'Key' },
{ key: 'value', label: 'Value' },
{ key: 'type', label: 'Type' },
]} {items} {showHeaders} {contained} key="key" />

View File

@ -0,0 +1,54 @@
<script>
import { createEventDispatcher } from 'svelte';
export let tabs = [];
export let selectedKey = {};
const dispatch = createEventDispatcher();
function select(tabKey) {
selectedKey = tabKey;
dispatch('select', tabKey);
}
</script>
<nav class="tabs">
<ul>
{#each tabs as tab (tab.key)}
<li class="tab" class:active={tab.key === selectedKey}>
<button on:click={() => select(tab.key)}>{tab.title}</button>
</li>
{/each}
</ul>
</nav>
<style>
.tabs {
border-bottom: 1px solid #ccc;
padding: 0 0.5rem;
}
.tabs ul {
overflow-x: scroll;
display: flex;
gap: 0.5rem;
list-style: none;
}
.tabs li {
display: inline-block;
flex-grow: 1;
}
.tabs li button {
width: 100%;
padding: 0.7rem 1rem;
border: 1px solid #ccc;
border-bottom: none;
border-radius: 5px 5px 0 0;
cursor: pointer;
}
.tabs li.active button {
color: #fff;
background-color: #00008b;
border-color: #00008b;
cursor: not-allowed;
}
</style>