mirror of
https://seed.radicle.dev/rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5.git
synced 2026-11-02 02:00:31 +08:00
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import Icon from "@app/components/Icon.svelte";
|
||||
import Toggle from "@app/components/Toggle.svelte";
|
||||
import ToggleSwitch from "@app/components/ToggleSwitch.svelte";
|
||||
import { theme, storeTheme } from "@app/lib/appearance";
|
||||
|
||||
$: document.documentElement.setAttribute("data-theme", $theme);
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
<div class="theme">
|
||||
<Icon name="sun" on:click={() => theme.set("light")} />
|
||||
<Toggle
|
||||
<ToggleSwitch
|
||||
checked={$theme === "dark"}
|
||||
on:change={() => {
|
||||
theme.set($theme === "dark" ? "light" : "dark");
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
import * as modal from "@app/lib/modal";
|
||||
|
||||
import ColorPalette from "./ColorPalette.svelte";
|
||||
import HelpModal from "./HelpModal.svelte";
|
||||
import ColorPaletteModal from "@app/App/ColorPaletteModal.svelte";
|
||||
import HotkeysModal from "@app/App/HotkeysModal.svelte";
|
||||
|
||||
const onKeydown = (event: KeyboardEvent) => {
|
||||
if (event.key === "Escape") {
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
switch (event.key) {
|
||||
case "?":
|
||||
modal.toggle({ component: HelpModal, props: {} });
|
||||
modal.toggle({ component: HotkeysModal, props: {} });
|
||||
break;
|
||||
case "/": {
|
||||
event.preventDefault();
|
||||
@@ -26,7 +26,7 @@
|
||||
if (import.meta.env.PROD) {
|
||||
return;
|
||||
}
|
||||
modal.toggle({ component: ColorPalette, props: {} });
|
||||
modal.toggle({ component: ColorPaletteModal, props: {} });
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
import type { Comment, Thread } from "@app/lib/issue";
|
||||
|
||||
import Authorship from "@app/components/Authorship.svelte";
|
||||
import Avatar from "@app/components/Avatar.svelte";
|
||||
import Avatar from "@app/components/Comment/Avatar.svelte";
|
||||
import Markdown from "@app/components/Markdown.svelte";
|
||||
import ReactionSelector from "./Comment/ReactionSelector.svelte";
|
||||
import Reactions from "./Comment/Reactions.svelte";
|
||||
import Reactions from "@app/components/Comment/Reactions.svelte";
|
||||
|
||||
export let comment: Comment | Thread;
|
||||
export let caption = "left a comment";
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
<script lang="ts">
|
||||
// Use this component if you need an emoji that is reactive. For static
|
||||
// emojis use the `twemoji` action from the utils module.
|
||||
|
||||
import twemoji from "twemoji";
|
||||
import { base } from "@app/lib/router";
|
||||
|
||||
export let emoji: string;
|
||||
</script>
|
||||
|
||||
{@html twemoji.parse(emoji, {
|
||||
base,
|
||||
folder: "twemoji",
|
||||
ext: ".svg",
|
||||
className: "txt-emoji",
|
||||
})}
|
||||
@@ -1,35 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { twemoji } from "@app/lib/utils";
|
||||
|
||||
export let emoji: string = "👻";
|
||||
export let title: string;
|
||||
export let message: string;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.error {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.emoji {
|
||||
font-size: var(--font-size-xx-large);
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: var(--color-negative);
|
||||
}
|
||||
|
||||
.message {
|
||||
color: var(--color-foreground-6);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="error">
|
||||
<div class="emoji" use:twemoji>{emoji}</div>
|
||||
<div class="title txt-medium txt-bold">{title}</div>
|
||||
<div class="message">{message}</div>
|
||||
</div>
|
||||
@@ -1,83 +0,0 @@
|
||||
<script lang="ts">
|
||||
import type {
|
||||
CloseAction,
|
||||
PrimaryAction,
|
||||
} from "@app/components/Modal.svelte";
|
||||
|
||||
import debounce from "lodash/debounce";
|
||||
import Modal from "@app/components/Modal.svelte";
|
||||
import Icon from "@app/components/Icon.svelte";
|
||||
|
||||
import { toClipboard } from "@app/lib/utils";
|
||||
|
||||
export let title: string;
|
||||
export let caption: string = "There was an error with your transaction.";
|
||||
export let error: string | undefined = undefined;
|
||||
|
||||
export let closeAction: CloseAction = undefined;
|
||||
export let primaryAction: PrimaryAction = undefined;
|
||||
|
||||
const emoji = "🚨";
|
||||
let clipboardIcon: "clipboard" | "checkmark" = "clipboard";
|
||||
|
||||
const resetIcon = debounce(() => {
|
||||
clipboardIcon = "clipboard";
|
||||
}, 800);
|
||||
|
||||
function copy() {
|
||||
if (error) {
|
||||
toClipboard(error);
|
||||
}
|
||||
clipboardIcon = "checkmark";
|
||||
resetIcon();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
overflow: hidden;
|
||||
border-radius: var(--border-radius);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.copy {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
padding: 2px;
|
||||
background-color: var(--color-foreground-2);
|
||||
border-radius: var(--border-radius-round);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.message {
|
||||
font-size: var(--font-size-tiny);
|
||||
word-wrap: break-word;
|
||||
max-height: 8rem;
|
||||
background-color: var(--color-foreground-2);
|
||||
overflow-y: auto;
|
||||
padding: 1rem;
|
||||
text-align: left;
|
||||
}
|
||||
</style>
|
||||
|
||||
{#if error}
|
||||
<Modal {title} {emoji} {closeAction} {primaryAction}>
|
||||
<div slot="subtitle">{caption}</div>
|
||||
<div slot="body">
|
||||
<div class="container">
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div class="copy" on:click={copy}>
|
||||
<Icon name={clipboardIcon} />
|
||||
</div>
|
||||
<div class="message txt-monospace txt-small">
|
||||
{error}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
{:else}
|
||||
<Modal {title} {emoji} {closeAction} {primaryAction}>
|
||||
<div slot="subtitle">{caption}</div>
|
||||
</Modal>
|
||||
{/if}
|
||||
@@ -26,10 +26,12 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import twemoji from "twemoji";
|
||||
|
||||
import * as modal from "@app/lib/modal";
|
||||
import { base } from "@app/lib/router";
|
||||
|
||||
import Button from "@app/components/Button.svelte";
|
||||
import Emoji from "@app/components/Emoji.svelte";
|
||||
|
||||
export let emoji: string | undefined = undefined;
|
||||
export let title: string | undefined = undefined;
|
||||
@@ -89,7 +91,12 @@
|
||||
<div class="modal">
|
||||
{#if emoji}
|
||||
<div style:font-size="var(--font-size-xx-large)">
|
||||
<Emoji {emoji} />
|
||||
{@html twemoji.parse(emoji, {
|
||||
base,
|
||||
folder: "twemoji",
|
||||
ext: ".svg",
|
||||
className: "txt-emoji",
|
||||
})}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { parseRadicleId, toClipboard, twemoji } from "@app/lib/utils";
|
||||
import Button from "@app/components/Button.svelte";
|
||||
|
||||
export let id: string;
|
||||
|
||||
let copied = false;
|
||||
|
||||
function copy() {
|
||||
toClipboard(id).then(() => {
|
||||
copied = true;
|
||||
setTimeout(() => {
|
||||
copied = false;
|
||||
}, 1000);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.id {
|
||||
display: inline-flex;
|
||||
font-size: var(--font-size-regular);
|
||||
line-height: 2rem;
|
||||
color: var(--color-foreground-6);
|
||||
vertical-align: middle;
|
||||
}
|
||||
.icon {
|
||||
width: 1rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
.id > * {
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="layout-desktop">
|
||||
<div class="id">
|
||||
<span class="icon" use:twemoji>🌱</span>
|
||||
<span class="txt-faded">rad:</span>
|
||||
<span>{parseRadicleId(id)}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Button variant="foreground" size="small" disabled={copied} on:click={copy}>
|
||||
{#if copied}
|
||||
Copy ✓
|
||||
{:else}
|
||||
Copy
|
||||
{/if}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts" context="module">
|
||||
export interface ToggleButtonOption<T> {
|
||||
export interface Tab<T> {
|
||||
title?: string;
|
||||
count?: number;
|
||||
value: T;
|
||||
@@ -12,12 +12,12 @@
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import { capitalize } from "@app/lib/utils";
|
||||
|
||||
export let options: ToggleButtonOption<T>[];
|
||||
export let options: Tab<T>[];
|
||||
export let active: T;
|
||||
|
||||
const dispatch = createEventDispatcher<{ select: T }>();
|
||||
|
||||
function onSelect(option: ToggleButtonOption<T>) {
|
||||
function onSelect(option: Tab<T>) {
|
||||
if (option.count !== 0) {
|
||||
dispatch("select", option.value);
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import type { Issue } from "@app/lib/issue";
|
||||
import type { ToggleButtonOption } from "@app/components/ToggleButton.svelte";
|
||||
import type { Tab } from "@app/components/TabBar.svelte";
|
||||
|
||||
import { capitalize } from "@app/lib/utils";
|
||||
import { groupIssues } from "@app/lib/issue";
|
||||
@@ -12,12 +12,12 @@
|
||||
|
||||
import IssueTeaser from "@app/views/projects/Issue/IssueTeaser.svelte";
|
||||
import Placeholder from "@app/components/Placeholder.svelte";
|
||||
import ToggleButton from "@app/components/ToggleButton.svelte";
|
||||
import TabBar from "@app/components/TabBar.svelte";
|
||||
|
||||
export let issues: Issue[];
|
||||
export let state: State;
|
||||
|
||||
let options: ToggleButtonOption<State>[];
|
||||
let options: Tab<State>[];
|
||||
const { open, closed } = groupIssues(issues);
|
||||
|
||||
$: filteredIssues = state === "open" ? open : closed;
|
||||
@@ -59,7 +59,7 @@
|
||||
|
||||
<div class="issues">
|
||||
<div style="margin-bottom: 1rem;">
|
||||
<ToggleButton
|
||||
<TabBar
|
||||
{options}
|
||||
on:select={e =>
|
||||
router.updateProjectRoute({
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script lang="ts" strictEvents>
|
||||
import type { ToggleButtonOption } from "@app/components/ToggleButton.svelte";
|
||||
import type { Tab } from "@app/components/TabBar.svelte";
|
||||
|
||||
import Dropdown from "@app/components/Dropdown.svelte";
|
||||
import Floating, { closeFocused } from "@app/components/Floating.svelte";
|
||||
import ToggleButton from "@app/components/ToggleButton.svelte";
|
||||
import TabBar from "@app/components/TabBar.svelte";
|
||||
|
||||
import type { Revision } from "@app/lib/patch";
|
||||
import { PatchTab } from "@app/lib/patch";
|
||||
@@ -37,7 +37,7 @@
|
||||
dispatch("revisionChanged", detail);
|
||||
};
|
||||
|
||||
let options: ToggleButtonOption<PatchTab>[];
|
||||
let options: Tab<PatchTab>[];
|
||||
$: options = [
|
||||
{
|
||||
title: "Patch",
|
||||
@@ -77,7 +77,7 @@
|
||||
</style>
|
||||
|
||||
<div class="bar txt-small">
|
||||
<ToggleButton
|
||||
<TabBar
|
||||
{options}
|
||||
on:select={e => {
|
||||
dispatch("switchTab", e.detail);
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
|
||||
<script lang="ts">
|
||||
import type { Patch } from "@app/lib/patch";
|
||||
import type { ToggleButtonOption } from "@app/components/ToggleButton.svelte";
|
||||
import type { Tab } from "@app/components/TabBar.svelte";
|
||||
|
||||
import PatchTeaser from "./Patch/PatchTeaser.svelte";
|
||||
import Placeholder from "@app/components/Placeholder.svelte";
|
||||
import ToggleButton from "@app/components/ToggleButton.svelte";
|
||||
import TabBar from "@app/components/TabBar.svelte";
|
||||
|
||||
import { capitalize } from "@app/lib/utils";
|
||||
import { groupPatches } from "@app/lib/patch";
|
||||
@@ -17,7 +17,7 @@
|
||||
export let state: State;
|
||||
export let patches: Patch[];
|
||||
|
||||
let options: ToggleButtonOption<State>[];
|
||||
let options: Tab<State>[];
|
||||
const sortedPatches = groupPatches(patches);
|
||||
|
||||
$: filteredPatches = sortedPatches[state];
|
||||
@@ -59,7 +59,7 @@
|
||||
|
||||
<div class="patches">
|
||||
<div style="margin-bottom: 1rem;">
|
||||
<ToggleButton
|
||||
<TabBar
|
||||
{options}
|
||||
on:select={e =>
|
||||
router.updateProjectRoute({
|
||||
|
||||
+11
-10
@@ -1,15 +1,16 @@
|
||||
<script lang="ts">
|
||||
import type { Stats } from "@app/lib/seed";
|
||||
import type { ProjectInfo } from "@app/lib/project";
|
||||
import { formatSeedId, formatSeedHost, twemoji } from "@app/lib/utils";
|
||||
import { Seed, defaultSeedPort } from "@app/lib/seed";
|
||||
import Loading from "@app/components/Loading.svelte";
|
||||
import SeedAddress from "@app/components/SeedAddress.svelte";
|
||||
import NotFound from "@app/components/NotFound.svelte";
|
||||
import Clipboard from "@app/components/Clipboard.svelte";
|
||||
import Projects from "@app/views/seeds/View/Projects.svelte";
|
||||
import { Project } from "@app/lib/project";
|
||||
import type { Host } from "@app/lib/api";
|
||||
import type { ProjectInfo } from "@app/lib/project";
|
||||
import type { Stats } from "@app/lib/seed";
|
||||
|
||||
import Clipboard from "@app/components/Clipboard.svelte";
|
||||
import Loading from "@app/components/Loading.svelte";
|
||||
import NotFound from "@app/components/NotFound.svelte";
|
||||
import Projects from "@app/views/seeds/View/Projects.svelte";
|
||||
import SeedAddress from "@app/views/seeds/View/SeedAddress.svelte";
|
||||
import { Project } from "@app/lib/project";
|
||||
import { Seed, defaultSeedPort } from "@app/lib/seed";
|
||||
import { formatSeedId, formatSeedHost, twemoji } from "@app/lib/utils";
|
||||
|
||||
export let hostAndPort: string;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user