Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add-on components #1336

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions ts/addons/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
load("@npm//@bazel/typescript:index.bzl", "ts_library")
load("//ts/svelte:svelte.bzl", "compile_svelte", "svelte_check")
load("//ts:prettier.bzl", "prettier_test")
load("//ts:eslint.bzl", "eslint_test")
load("//ts:esbuild.bzl", "esbuild")

svelte_files = glob(["*.svelte"])

svelte_names = [f.replace(".svelte", "") for f in svelte_files]

filegroup(
name = "svelte_components",
srcs = svelte_names,
visibility = ["//visibility:public"],
)

compile_svelte(
name = "svelte",
srcs = svelte_files,
visibility = ["//visibility:public"],
deps = [
"//ts/sass:button_mixins_lib",
"//ts/sass/bootstrap",
],
)

ts_library(
name = "addons",
srcs = glob(
["*.ts"],
exclude = ["*.test.ts"],
),
module_name = "addons",
tsconfig = "//ts:tsconfig.json",
visibility = ["//visibility:public"],
deps = [
"//ts/components",
"//ts/lib",
"//ts/sveltelib",
"@npm//@popperjs/core",
"@npm//@types/bootstrap",
"@npm//bootstrap",
"@npm//svelte",
] + svelte_names,
)

# Tests
################

prettier_test(
name = "format_check",
srcs = glob([
"*.ts",
"*.svelte",
]),
)

eslint_test(
name = "eslint",
srcs = glob(
[
"*.ts",
],
),
)

svelte_check(
name = "svelte_check",
srcs = glob([
"*.ts",
"*.svelte",
]) + [
"//ts/sass:button_mixins_lib",
"//ts/sass/bootstrap",
"@npm//@types/bootstrap",
],
)
36 changes: 36 additions & 0 deletions ts/addons/IconButton.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<!--
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="typescript">
import IconButton from "components/IconButton.svelte";

export let id: string;
export let className: string;

export let tooltip: string;
export let active: boolean;
export let disabled: boolean;
export let tabbable: boolean;

export let iconSize: number;
export let widthMultiplier: number;

export let onClick: (event: MouseEvent) => void;
export let onMount: (event: CustomEvent) => void;
</script>

<IconButton
{id}
class={className}
{tooltip}
{active}
{disabled}
{tabbable}
{iconSize}
{widthMultiplier}
on:click={onClick}
on:mount={onMount}
>
<slot />
</IconButton>
12 changes: 12 additions & 0 deletions ts/addons/Slotted.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!--
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script>
export let component;
export let slotted;
</script>

<svelte:component this={component.component} {...component.props}>
{slotted}
</svelte:component>
12 changes: 12 additions & 0 deletions ts/addons/SlottedHTML.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!--
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script>
export let component;
export let slotted;
</script>

<svelte:component this={component.component} {...component.props}>
{@html slotted}
</svelte:component>
17 changes: 17 additions & 0 deletions ts/addons/WithContext.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!--
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="typescript">
import type { SvelteComponentTyped } from "svelte/internal";
import WithContext from "components/WithContext.svelte";

export let key: string;
export let getComponent: ({ context }) => SvelteComponentTyped;
</script>

<WithContext {key} let:context>
{#each [getComponent({ context })] as data}
<svelte:component this={data.component} {...data.props} />
{/each}
</WithContext>
20 changes: 20 additions & 0 deletions ts/addons/WithShortcut.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!--
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="typescript">
import type { SvelteComponentTyped } from "svelte/internal";
import WithShortcut from "components/WithShortcut.svelte";

export let shortcut: string;
export let getComponent: ({
createShortcut,
shortcutLabel,
}) => SvelteComponentTyped;
</script>

<WithShortcut {shortcut} let:createShortcut let:shortcutLabel>
{#each [getComponent({ createShortcut, shortcutLabel })] as data}
<svelte:component this={data.component} {...data.props} />
{/each}
</WithShortcut>
19 changes: 19 additions & 0 deletions ts/addons/WithState.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!--
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="typescript">
import type { SvelteComponentTyped } from "svelte/internal";
import WithState from "components/WithState.svelte";

export let key: string;
export let update: (event: Event) => boolean;

export let getComponent: ({ state, updateState }) => SvelteComponentTyped;
</script>

<WithState {key} {update} let:state let:updateState>
{#each [getComponent({ state, updateState })] as data}
<svelte:component this={data.component} {...data.props} />
{/each}
</WithState>
25 changes: 25 additions & 0 deletions ts/addons/dynamic-components.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html

import { dynamicComponent } from "sveltelib/dynamicComponent";

/* components */
import IconButton from "./IconButton.svelte";
export const iconButton = dynamicComponent(IconButton);

/* decorators */
import WithContext from "./WithContext.svelte";
export const withContext = dynamicComponent(WithContext);

import WithState from "./WithState.svelte";
export const withState = dynamicComponent(WithState);

import WithShortcut from "./WithShortcut.svelte";
export const withShortcut = dynamicComponent(WithShortcut);

/* slots */
import Slotted from "./Slotted.svelte";
export const slotted = dynamicComponent(Slotted);

import SlottedHTML from "./SlottedHTML.svelte";
export const slottedHtml = dynamicComponent(SlottedHTML);
4 changes: 2 additions & 2 deletions ts/components/IconButton.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<button
bind:this={buttonRef}
{id}
class={`btn ${className}`}
class="btn {className}"
class:active
class:dropdown-toggle={dropdownProps.dropdown}
class:btn-day={!nightMode}
class:btn-night={nightMode}
style={`--icon-size: ${iconSize}%`}
style="--icon-size: {iconSize}%"
title={tooltip}
{...dropdownProps}
{disabled}
Expand Down
2 changes: 1 addition & 1 deletion ts/deck-options/DeckOptionsPage.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
component: HtmlAddon,
html,
mounted,
},
} as unknown as DynamicSvelteComponent,
];
}

Expand Down
5 changes: 5 additions & 0 deletions ts/editor/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ compile_svelte(
visibility = ["//visibility:public"],
deps = [
"//ts/components",
"//ts/addons",
],
)

Expand Down Expand Up @@ -71,6 +72,7 @@ ts_library(
"//ts/lib",
"//ts/sveltelib",
"//ts/components",
"//ts/addons",
"//ts/html-filter",
"//ts:image_module_support",
"@npm//svelte",
Expand Down Expand Up @@ -141,6 +143,8 @@ esbuild(
"svelte_components",
"//ts/components",
"//ts/components:svelte_components",
"//ts/addons",
"//ts/addons:svelte_components",
"@npm//protobufjs",
],
)
Expand Down Expand Up @@ -175,5 +179,6 @@ svelte_check(
"//ts/sass/bootstrap",
"@npm//@types/bootstrap",
"//ts/components",
"//ts/addons",
],
)
20 changes: 12 additions & 8 deletions ts/editor/Components.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,23 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script context="module" lang="typescript">
import IconButton from "components/IconButton.svelte";
import LabelButton from "components/LabelButton.svelte";
import WithContext from "components/WithContext.svelte";
import WithState from "components/WithState.svelte";
import {
iconButton,
withContext,
withState,
withShortcut,
slottedHtml,
} from "addons/dynamic-components";

import * as contextKeys from "components/context-keys";
import * as editorContextKeys from "./context-keys";

export const components = {
IconButton,
LabelButton,
WithContext,
WithState,
iconButton,
withContext,
withState,
withShortcut,
slottedHtml,
contextKeys: { ...contextKeys, ...editorContextKeys },
};
</script>
21 changes: 6 additions & 15 deletions ts/sveltelib/dynamicComponent.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,12 @@
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import type { SvelteComponentDev } from "svelte/internal";

export interface DynamicSvelteComponent<
T extends typeof SvelteComponentDev = typeof SvelteComponentDev
> {
component: T;
[k: string]: unknown;
export interface DynamicSvelteComponent {
component: unknown;
props: Record<string, unknown>;
}

export const dynamicComponent =
<
Comp extends typeof SvelteComponentDev,
DefaultProps = NonNullable<ConstructorParameters<Comp>[0]["props"]>
>(
component: Comp
) =>
<Props = DefaultProps>(props: Props): DynamicSvelteComponent<Comp> & Props => {
return { component, ...props };
<T>(component: T) =>
(props: Record<string, unknown>): DynamicSvelteComponent => {
return { component, props };
};