Skip to content

Commit 774afad

Browse files
authored
Merge pull request #39 from webgme/issue/38-string-control-append
Add `append` and `'prepend` properties for string controls
2 parents 2d5a968 + 929291d commit 774afad

File tree

3 files changed

+50
-3
lines changed

3 files changed

+50
-3
lines changed

src/lib/Control.svelte

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
<script context="module" lang="ts">
2+
import { getContext, setContext } from "svelte";
3+
import * as controls from "./controls";
4+
5+
const controlNames = Object.keys(controls);
6+
const ControlPropsContextKey = Symbol("control-props");
7+
28
function useConst(schema: JSONSchema7 | undefined) {
39
return (schema != null) && !isBoolean(schema) && ("const" in schema);
410
}
@@ -13,20 +19,36 @@
1319
: schema?.type;
1420
return (Array.isArray(type) ? type[0] : type) ?? "object";
1521
}
22+
23+
export function setControlProps(props: Record<string, any>) {
24+
const context = Object.keys(props).reduce((controlsProps, name) => {
25+
const [controlName, propName] = name.split('$', 2);
26+
if ((controlNames.includes(controlName)) && (propName != null)) {
27+
(controlsProps[controlName] ??= {})[propName] = props[name];
28+
}
29+
return controlsProps;
30+
}, {} as { [control: string]: { [prop: string]: any } });
31+
return setContext(ControlPropsContextKey, context);
32+
}
33+
34+
export function getControlProps() {
35+
return getContext<{[control: string]: Record<string, any>}>(ControlPropsContextKey);
36+
}
1637
</script>
1738

1839
<script lang="ts">
1940
import type { JSONSchema7 } from "json-schema";
2041
import type UISchema from "./UISchema";
2142
import { isBoolean } from "./utilities";
22-
import * as controls from "./controls";
2343
2444
export let schema: JSONSchema7 | undefined;
2545
export let data: any = undefined;
2646
export let uischema: UISchema = {};
2747
export let force: boolean = false;
2848
49+
const allControlProps = getControlProps();
2950
let control: any;
51+
let controlProps: Record<string, any> = {};
3052
3153
$: updateControlType(schema);
3254
@@ -35,8 +57,9 @@
3557
const updatedControl = controls[singleType as keyof typeof controls] as any;
3658
if (updatedControl != control) {
3759
control = updatedControl;
60+
controlProps = allControlProps[singleType];
3861
}
3962
}
4063
</script>
4164

42-
<svelte:component this={control} {...schema} bind:data {uischema} {force} />
65+
<svelte:component this={control} {...controlProps} {...schema} bind:data {uischema} {force} />

src/lib/SchemaForm.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@
99
import Paper, { Title, Subtitle, Content } from '@smui/paper';
1010
import createMountedEventDispatcher from './createMountedEventDispatcher';
1111
import ObjectProps from "./controls/ObjectProps.svelte";
12-
import Control from "./Control.svelte";
12+
import Control, { setControlProps } from "./Control.svelte";
1313
import { isObjectSchema, isString, isBoolean } from './utilities';
1414
import libVersion from "./version";
1515
1616
export let schema: JSONSchema7Definition = {};
1717
export let data: { [prop: string]: any } = {};
1818
export let uischema: UISchema = {};
1919
20+
setControlProps($$restProps);
2021
const dispatch = createMountedEventDispatcher();
2122
/* A bit of a hack - When bulding the static test site, the dereferencer is still behind a
2223
* `.default` property for some reason. I'm guessing it has something to do with how modules are

src/lib/controls/StringControl.svelte

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<script lang="ts">
2+
import { isString } from "$lib/utilities";
23
import UISchema from "$lib/UISchema";
34
import Textfield from "@smui/textfield";
45
import HelperText from "@smui/textfield/helper-text";
@@ -15,6 +16,9 @@
1516
export let isRequired: boolean | undefined = undefined;
1617
export let force: boolean = false;
1718
19+
export let prepend: ConstructorOfATypedSvelteComponent | string | undefined = undefined;
20+
export let append: ConstructorOfATypedSvelteComponent | string | undefined = undefined;
21+
1822
let value: string = data ?? "";
1923
let enumValues: string[] | undefined = undefined;
2024
@@ -41,6 +45,12 @@
4145
</script>
4246

4347
<div class="jsonschema-form-control control-string">
48+
{#if isString(prepend)}
49+
{@html prepend}
50+
{:else if prepend != null}
51+
<svelte:component this={prepend} {...$$props} />
52+
{/if}
53+
4454
{#if enumValues?.length}
4555
<Select
4656
variant="outlined"
@@ -79,9 +89,22 @@
7989
</svelte:fragment>
8090
</Textfield>
8191
{/if}
92+
93+
{#if isString(append)}
94+
{@html append}
95+
{:else if append != null}
96+
<svelte:component this={append} {...$$props} />
97+
{/if}
8298
</div>
8399

84100
<style>
101+
.control-string {
102+
display: flex;
103+
flex-direction: row;
104+
align-items: center;
105+
gap: 3px;
106+
}
107+
85108
.control-string > :global(.mdc-text-field),
86109
.control-string > :global(.mdc-select) {
87110
width: 100%;

0 commit comments

Comments
 (0)