113 lines
3.3 KiB
Svelte
113 lines
3.3 KiB
Svelte
<svelte:options
|
|
customElement={{
|
|
props: {
|
|
identifier_hints: { attribute: "identifier-hints", type: "Array" },
|
|
value: { reflect: true, type: "Object" },
|
|
},
|
|
shadow: "none",
|
|
tag: "expression-editor",
|
|
}}
|
|
/>
|
|
|
|
<script lang="ts">
|
|
import EncodableEditor from "./encodable-editor.svelte";
|
|
import ExpressionSelector from "./expression-selector.svelte";
|
|
import { type PgExpressionAny } from "./expression.svelte";
|
|
import ExpressionEditor from "./expression-editor.webc.svelte";
|
|
import {
|
|
DEFAULT_EDITOR_STATE,
|
|
editor_state_from_encodable,
|
|
type EditorState,
|
|
encodable_from_editor_state,
|
|
} from "./editor-state.svelte";
|
|
import { type FieldInfo } from "./field.svelte";
|
|
import { type Presentation } from "./presentation.svelte";
|
|
|
|
const ASSIGNABLE_PRESENTATIONS: Presentation[] = [
|
|
{ t: "Text", c: { input_mode: { t: "MultiLine", c: {} } } },
|
|
{ t: "Timestamp", c: {} },
|
|
{ t: "Uuid", c: {} },
|
|
];
|
|
const ASSIGNABLE_FIELDS: FieldInfo[] = ASSIGNABLE_PRESENTATIONS.map(
|
|
(presentation) => ({
|
|
field: {
|
|
id: "",
|
|
table_label: "",
|
|
name: "",
|
|
presentation,
|
|
table_width_px: -1,
|
|
},
|
|
not_null: true,
|
|
has_default: false,
|
|
}),
|
|
);
|
|
|
|
type Props = {
|
|
identifier_hints?: string[];
|
|
value?: PgExpressionAny;
|
|
};
|
|
|
|
let { identifier_hints = [], value = $bindable() }: Props = $props();
|
|
|
|
let editor_state = $state<EditorState>(
|
|
value?.t === "Literal"
|
|
? editor_state_from_encodable(value.c)
|
|
: DEFAULT_EDITOR_STATE,
|
|
);
|
|
let editor_field_info = $state<FieldInfo>(ASSIGNABLE_FIELDS[0]);
|
|
|
|
$effect(() => {
|
|
if (value?.t === "Literal" && editor_field_info) {
|
|
const encodable_value = encodable_from_editor_state(
|
|
editor_state,
|
|
editor_field_info.field.presentation,
|
|
);
|
|
if (encodable_value) {
|
|
value.c = encodable_value;
|
|
}
|
|
}
|
|
});
|
|
|
|
function handle_identifier_selector_change(
|
|
ev: Event & { currentTarget: HTMLSelectElement },
|
|
) {
|
|
if (value?.t === "Identifier") {
|
|
value.c.parts_raw = [ev.currentTarget.value];
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<div class="expression-editor__container">
|
|
<div class="expression-editor__sidebar">
|
|
<ExpressionSelector bind:value />
|
|
</div>
|
|
{#if value !== undefined}
|
|
<div class="expression-editor__main">
|
|
<div class="expression-editor__params">
|
|
{#if value.t === "Comparison"}
|
|
{#if value.c.t === "Infix"}
|
|
<ExpressionEditor bind:value={value.c.c.lhs} {identifier_hints} />
|
|
<ExpressionEditor bind:value={value.c.c.rhs} {identifier_hints} />
|
|
{:else if value.c.t === "IsNull" || value.c.t === "IsNotNull"}
|
|
<ExpressionEditor bind:value={value.c.c.lhs} {identifier_hints} />
|
|
{/if}
|
|
{:else if value.t === "Identifier"}
|
|
<select
|
|
onchange={handle_identifier_selector_change}
|
|
value={value.c.parts_raw[0]}
|
|
>
|
|
{#each identifier_hints as hint}
|
|
<option value={hint}>{hint}</option>
|
|
{/each}
|
|
</select>
|
|
{:else if value.t === "Literal"}
|
|
<EncodableEditor
|
|
bind:editor_state
|
|
bind:field_info={editor_field_info}
|
|
assignable_fields={ASSIGNABLE_FIELDS}
|
|
/>
|
|
{/if}
|
|
</div>
|
|
</div>
|
|
{/if}
|
|
</div>
|