@stubber/form-fields 1.6.3 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -52
- package/dist/fields2/FieldExprToggle.svelte +29 -0
- package/dist/fields2/FieldExprToggle.svelte.d.ts +20 -0
- package/dist/fields2/FieldLabel.svelte +7 -3
- package/dist/fields2/FieldMessage.svelte +2 -3
- package/dist/fields2/FieldMessage.svelte.d.ts +1 -1
- package/dist/fields2/Form.svelte +4 -1
- package/dist/fields2/Form.svelte.d.ts +1 -0
- package/dist/fields2/form-field.svelte +22 -2
- package/dist/fields2/form-field.svelte.d.ts +2 -2
- package/dist/fields2/interfaces.d.ts +2 -1
- package/dist/fields2/interfaces.js +16 -2
- package/dist/fields2/sub/array-builder-field.svelte +13 -5
- package/dist/fields2/sub/checkbox-field.svelte +3 -1
- package/dist/fields2/sub/field-builder-field.svelte +77 -18
- package/dist/fields2/sub/grid-field.svelte +8 -3
- package/dist/fields2/sub/object-builder-field.svelte +11 -7
- package/dist/fields2/sub/scroll-and-read-display-field.svelte +5 -5
- package/dist/fields2/sub/section-field.svelte +5 -2
- package/dist/fields2/validations/validate_field.js +2 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -34,58 +34,48 @@ See default ruleset [here](https://github.com/semantic-release/commit-analyzer/b
|
|
|
34
34
|
|
|
35
35
|
Conversion Progress:
|
|
36
36
|
|
|
37
|
-
| Component | TS DONE |
|
|
38
|
-
| -------------------- | ---------- |
|
|
39
|
-
| AgGrid | x |
|
|
40
|
-
| Arraybuilder | x |
|
|
41
|
-
| Checkbox | x |
|
|
42
|
-
| CheckboxAutocomplete | x |
|
|
43
|
-
| Code | x |
|
|
44
|
-
| Contactselector | x |
|
|
45
|
-
| Currency | x |
|
|
46
|
-
| Dataindication | x |
|
|
47
|
-
| Date | x |
|
|
48
|
-
| Datetime | x |
|
|
49
|
-
| Email | x |
|
|
50
|
-
| Fieldbuilder | x |
|
|
51
|
-
| Fieldsbuilder | deprecated |
|
|
52
|
-
| File | x |
|
|
53
|
-
| Heading | x |
|
|
54
|
-
| Hidden | x |
|
|
55
|
-
| Hiddenlocation | x |
|
|
56
|
-
| Html | x |
|
|
57
|
-
| Jsoneditor | x |
|
|
58
|
-
| Map | x |
|
|
59
|
-
| Multicheckbox | x |
|
|
60
|
-
| Multistep | x |
|
|
61
|
-
| Note | x |
|
|
62
|
-
| Number | x |
|
|
63
|
-
| Objectbuilder | x |
|
|
64
|
-
| Qrcodescanner | x |
|
|
65
|
-
| Radio | x |
|
|
66
|
-
| Renderfield | deprecated |
|
|
67
|
-
| Screenrecorder | x |
|
|
68
|
-
| Screenshot | x |
|
|
69
|
-
| Scrollandreaddisplay | x |
|
|
70
|
-
| Section | x |
|
|
71
|
-
| Select | x |
|
|
72
|
-
| Selectresource | x |
|
|
73
|
-
| Signature | x |
|
|
74
|
-
| Slider | x |
|
|
75
|
-
| SmartText | x |
|
|
76
|
-
| Telephone | x |
|
|
77
|
-
| Text | x |
|
|
78
|
-
| Voicenote | x |
|
|
79
|
-
|
|
80
|
-
Generate Features
|
|
81
|
-
|
|
82
|
-
| Feature | TS DONE | TESTS DONE |
|
|
83
|
-
| --------------------- | ------- | ---------- |
|
|
84
|
-
| hide_label | x | |
|
|
85
|
-
| init_value | x | |
|
|
86
|
-
| without_value_details | x | |
|
|
87
|
-
| attachments | x | |
|
|
88
|
-
| fieldbuilder support | x | |
|
|
37
|
+
| Component | TS DONE | IS STRING |
|
|
38
|
+
| -------------------- | ---------- | --------- |
|
|
39
|
+
| AgGrid | x | |
|
|
40
|
+
| Arraybuilder | x | |
|
|
41
|
+
| Checkbox | x | |
|
|
42
|
+
| CheckboxAutocomplete | x | |
|
|
43
|
+
| Code | x | |
|
|
44
|
+
| Contactselector | x | |
|
|
45
|
+
| Currency | x | |
|
|
46
|
+
| Dataindication | x | |
|
|
47
|
+
| Date | x | |
|
|
48
|
+
| Datetime | x | |
|
|
49
|
+
| Email | x | |
|
|
50
|
+
| Fieldbuilder | x | |
|
|
51
|
+
| Fieldsbuilder | deprecated | |
|
|
52
|
+
| File | x | |
|
|
53
|
+
| Heading | x | |
|
|
54
|
+
| Hidden | x | |
|
|
55
|
+
| Hiddenlocation | x | |
|
|
56
|
+
| Html | x | |
|
|
57
|
+
| Jsoneditor | x | |
|
|
58
|
+
| Map | x | |
|
|
59
|
+
| Multicheckbox | x | |
|
|
60
|
+
| Multistep | x | |
|
|
61
|
+
| Note | x | |
|
|
62
|
+
| Number | x | |
|
|
63
|
+
| Objectbuilder | x | |
|
|
64
|
+
| Qrcodescanner | x | |
|
|
65
|
+
| Radio | x | |
|
|
66
|
+
| Renderfield | deprecated | |
|
|
67
|
+
| Screenrecorder | x | |
|
|
68
|
+
| Screenshot | x | |
|
|
69
|
+
| Scrollandreaddisplay | x | |
|
|
70
|
+
| Section | x | |
|
|
71
|
+
| Select | x | |
|
|
72
|
+
| Selectresource | x | |
|
|
73
|
+
| Signature | x | |
|
|
74
|
+
| Slider | x | |
|
|
75
|
+
| SmartText | x | |
|
|
76
|
+
| Telephone | x | |
|
|
77
|
+
| Text | x | |
|
|
78
|
+
| Voicenote | x | |
|
|
89
79
|
|
|
90
80
|
## TS Refactor
|
|
91
81
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<script>import { getContext } from "svelte";
|
|
2
|
+
export let fieldStore;
|
|
3
|
+
const field_component_store = getContext("field_component");
|
|
4
|
+
const show_toggle = getContext("show_field_expr_toggle") ?? false;
|
|
5
|
+
$: selected_fieldtype = $field_component_store.fieldtype;
|
|
6
|
+
$: is_true_field = $fieldStore.fieldtype === selected_fieldtype;
|
|
7
|
+
const handle_fieldtype_click = (ft) => {
|
|
8
|
+
$field_component_store.fieldtype = ft;
|
|
9
|
+
};
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
{#if show_toggle}
|
|
13
|
+
<div
|
|
14
|
+
class="ml-auto flex h-fit w-fit flex-row items-center gap-0.5 rounded bg-gray-300 p-0.5 text-xs"
|
|
15
|
+
>
|
|
16
|
+
<button
|
|
17
|
+
on:click={() => handle_fieldtype_click($fieldStore.fieldtype)}
|
|
18
|
+
class={is_true_field ? "rounded bg-white px-0.5" : ""}
|
|
19
|
+
>
|
|
20
|
+
field
|
|
21
|
+
</button>
|
|
22
|
+
<button
|
|
23
|
+
on:click={() => handle_fieldtype_click("smart_text")}
|
|
24
|
+
class={!is_true_field ? "rounded bg-white px-0.5" : ""}
|
|
25
|
+
>
|
|
26
|
+
expr
|
|
27
|
+
</button>
|
|
28
|
+
</div>
|
|
29
|
+
{/if}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
import type { Writable } from "svelte/store";
|
|
3
|
+
import type { IBuiltField } from "./interfaces";
|
|
4
|
+
declare const __propDef: {
|
|
5
|
+
props: {
|
|
6
|
+
fieldStore: Writable<IBuiltField>;
|
|
7
|
+
};
|
|
8
|
+
events: {
|
|
9
|
+
[evt: string]: CustomEvent<any>;
|
|
10
|
+
};
|
|
11
|
+
slots: {};
|
|
12
|
+
exports?: {} | undefined;
|
|
13
|
+
bindings?: string | undefined;
|
|
14
|
+
};
|
|
15
|
+
export type FieldExprToggleProps = typeof __propDef.props;
|
|
16
|
+
export type FieldExprToggleEvents = typeof __propDef.events;
|
|
17
|
+
export type FieldExprToggleSlots = typeof __propDef.slots;
|
|
18
|
+
export default class FieldExprToggle extends SvelteComponent<FieldExprToggleProps, FieldExprToggleEvents, FieldExprToggleSlots> {
|
|
19
|
+
}
|
|
20
|
+
export {};
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
<script>import { Label } from "@stubber/ui/label";
|
|
2
|
+
import FieldExprToggle from "./FieldExprToggle.svelte";
|
|
2
3
|
export let fieldStore;
|
|
3
4
|
$: hide_label = $fieldStore.hide_label;
|
|
4
5
|
</script>
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
{
|
|
7
|
+
<div class="mb-1 flex flex-row items-center justify-between">
|
|
8
|
+
{#if !hide_label}
|
|
9
|
+
<Label for={$fieldStore.id}>{$fieldStore.label}</Label>
|
|
10
|
+
{/if}
|
|
11
|
+
<FieldExprToggle {fieldStore} />
|
|
12
|
+
</div>
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
<script>import { Label } from "@stubber/ui/label";
|
|
2
|
-
import { get, startCase } from "lodash-es";
|
|
3
|
-
import { get_field_help_message } from "./utils";
|
|
4
2
|
export let fieldStore;
|
|
5
3
|
$: validation_result = $fieldStore.validation_result;
|
|
6
4
|
$: type = validation_result?.type;
|
|
@@ -8,7 +6,8 @@ $: type = validation_result?.type;
|
|
|
8
6
|
|
|
9
7
|
<Label
|
|
10
8
|
id="message-{$fieldStore.id}"
|
|
11
|
-
|
|
9
|
+
for={$fieldStore.id}
|
|
10
|
+
class="block truncate text-xs {!$fieldStore.validation_result ? 'invisible' : ''} {type == 'error'
|
|
12
11
|
? 'text-red-500'
|
|
13
12
|
: 'text-muted-foreground'}"
|
|
14
13
|
>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SvelteComponent } from "svelte";
|
|
2
|
-
import type { IBuiltField } from "./interfaces";
|
|
3
2
|
import type { Writable } from "svelte/store";
|
|
3
|
+
import type { IBuiltField } from "./interfaces";
|
|
4
4
|
declare const __propDef: {
|
|
5
5
|
props: {
|
|
6
6
|
fieldStore: Writable<IBuiltField>;
|
package/dist/fields2/Form.svelte
CHANGED
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
import FormField from "./form-field.svelte";
|
|
3
3
|
import { build_fields } from "./utils";
|
|
4
4
|
import { validate_field } from "./validations/validate_field";
|
|
5
|
+
import { setContext } from "svelte";
|
|
5
6
|
export let initial_form;
|
|
6
7
|
export let form;
|
|
7
8
|
export let attachments = writable([]);
|
|
8
9
|
export let dependencies = void 0;
|
|
9
10
|
export let form_valid = false;
|
|
11
|
+
export let show_field_expr_toggle = false;
|
|
12
|
+
setContext("show_field_expr_toggle", show_field_expr_toggle);
|
|
10
13
|
if (initial_form.data) {
|
|
11
14
|
form.update((data) => {
|
|
12
15
|
return { ...data, ...initial_form.data };
|
|
@@ -28,7 +31,7 @@ const validate_form = async (_) => {
|
|
|
28
31
|
};
|
|
29
32
|
</script>
|
|
30
33
|
|
|
31
|
-
<div class="flex flex-col gap-y-
|
|
34
|
+
<div class="flex flex-col gap-y-2">
|
|
32
35
|
{#each fields as fieldStore (getStoreValue(fieldStore).id)}
|
|
33
36
|
<FormField {fieldStore} />
|
|
34
37
|
{/each}
|
|
@@ -1,6 +1,26 @@
|
|
|
1
|
-
<script>import {
|
|
1
|
+
<script>import { set } from "lodash-es";
|
|
2
|
+
import { getContext, setContext } from "svelte";
|
|
3
|
+
import { writable } from "svelte/store";
|
|
4
|
+
import { component_for, final_field_type } from "./interfaces";
|
|
2
5
|
export let fieldStore;
|
|
3
|
-
const
|
|
6
|
+
const show_toggle = getContext("show_field_expr_toggle") ?? false;
|
|
7
|
+
let fieldtype = final_field_type($fieldStore, show_toggle);
|
|
8
|
+
let component = component_for(fieldtype);
|
|
9
|
+
const field_component_store = writable({ fieldtype });
|
|
10
|
+
setContext("field_component", field_component_store);
|
|
11
|
+
$: handle_field_type_change($field_component_store.fieldtype);
|
|
12
|
+
const handle_field_type_change = (new_fieldtype) => {
|
|
13
|
+
if (new_fieldtype === fieldtype) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
fieldtype = new_fieldtype;
|
|
17
|
+
const new_value = new_fieldtype == "smart_text" ? typeof $fieldStore.value === "string" ? $fieldStore.value : "" : new_fieldtype == "checkbox" ? false : new_fieldtype == "number" ? 0 : new_fieldtype == "arraybuilder" ? [] : new_fieldtype == "section" || new_fieldtype == "objectbuilder" ? {} : null;
|
|
18
|
+
$fieldStore.formStore.update((form) => {
|
|
19
|
+
set(form, $fieldStore.data_path, new_value);
|
|
20
|
+
return form;
|
|
21
|
+
});
|
|
22
|
+
component = component_for(new_fieldtype);
|
|
23
|
+
};
|
|
4
24
|
</script>
|
|
5
25
|
|
|
6
26
|
{#if !$fieldStore.hidden}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { SvelteComponent } from "svelte";
|
|
2
|
+
import { type Writable } from "svelte/store";
|
|
2
3
|
import { type IBuiltField } from "./interfaces";
|
|
3
|
-
import type { Writable } from "svelte/store";
|
|
4
4
|
declare const __propDef: {
|
|
5
5
|
props: {
|
|
6
|
-
fieldStore: Writable<IBuiltField
|
|
6
|
+
fieldStore: Writable<IBuiltField<any>>;
|
|
7
7
|
};
|
|
8
8
|
events: {
|
|
9
9
|
[evt: string]: CustomEvent<any>;
|
|
@@ -177,7 +177,8 @@ export interface IBuiltField<T = {}> {
|
|
|
177
177
|
set value(val: any);
|
|
178
178
|
params?: T;
|
|
179
179
|
}
|
|
180
|
-
export declare const
|
|
180
|
+
export declare const final_field_type: (f: IBuiltField, allow_dynamic_switching: boolean) => FieldType;
|
|
181
|
+
export declare const component_for: (fieldtype: FieldType) => typeof GridField | typeof TextField | typeof NumberField | typeof SectionField | typeof CheckboxField | typeof CheckboxAutocomplete | typeof ArrayBuilderField | typeof SelectField | typeof SelectresourceField | typeof SliderField | typeof ContactSelectorField | typeof CurrencyField | typeof DataIndicationField | typeof DateField | typeof DateTimeField | typeof EmailField | typeof FieldBuilderField | typeof JSONEditorField | typeof FileField | typeof HeadingField | typeof HiddenField | typeof HiddenLocationField | typeof HtmlField | typeof MapField | typeof TelephoneField | typeof NoteField | typeof MultistepField | typeof ObjectBuilderField | typeof RadioField | typeof MultiCheckboxField | typeof QrCodeScannerField | typeof ScrollAndReadDisplayField | typeof VoicenoteField | typeof SignatureField | typeof SmartTextField | typeof ScreenshotField | typeof ScreenrecorderField | typeof CodeField;
|
|
181
182
|
export interface IBaseValidation {
|
|
182
183
|
invalid_message?: string;
|
|
183
184
|
}
|
|
@@ -76,7 +76,21 @@ export const fields = {
|
|
|
76
76
|
screenrecorder: ScreenrecorderField,
|
|
77
77
|
code: CodeField,
|
|
78
78
|
};
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
const string_fields = ["text", "email", "telephone", "smart_text", "note", "code"];
|
|
80
|
+
export const final_field_type = (f, allow_dynamic_switching) => {
|
|
81
|
+
if (!allow_dynamic_switching) {
|
|
82
|
+
return f.fieldtype;
|
|
83
|
+
}
|
|
84
|
+
const is_string = typeof f.value === "string";
|
|
85
|
+
// if the initial value is a string
|
|
86
|
+
// but this field isn't typically a string field,
|
|
87
|
+
// rather render it as a smart_text field
|
|
88
|
+
if (is_string && !string_fields.includes(f.fieldtype)) {
|
|
89
|
+
return "smart_text";
|
|
90
|
+
}
|
|
91
|
+
return f.fieldtype;
|
|
92
|
+
};
|
|
93
|
+
export const component_for = (fieldtype) => {
|
|
94
|
+
return fields[fieldtype];
|
|
81
95
|
};
|
|
82
96
|
export const validation_types = ["required", "regex", "jsonata"];
|
|
@@ -17,11 +17,16 @@ import FieldLabel from "../FieldLabel.svelte";
|
|
|
17
17
|
import FieldMessage from "../FieldMessage.svelte";
|
|
18
18
|
import FormField from "../form-field.svelte";
|
|
19
19
|
import { build_field } from "../utils";
|
|
20
|
+
import FieldExprToggle from "../FieldExprToggle.svelte";
|
|
21
|
+
import { Label } from "@stubber/ui/label";
|
|
20
22
|
export let fieldStore;
|
|
21
23
|
const new_entry_field = $fieldStore?.params?.new_entry_field || {
|
|
22
24
|
fieldtype: "text"
|
|
23
25
|
};
|
|
24
26
|
const update_sub_fields = (new_value) => {
|
|
27
|
+
if (!Array.isArray(new_value)) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
25
30
|
const field = $fieldStore;
|
|
26
31
|
field.sub_fields = new_value.map((_value, index) => {
|
|
27
32
|
return build_field(
|
|
@@ -79,7 +84,7 @@ const move_value_down = (index) => {
|
|
|
79
84
|
<Collapsible.Root open={true} class="w-full">
|
|
80
85
|
<Collapsible.Trigger asChild let:builder>
|
|
81
86
|
<Button builders={[builder]} variant="ghost" class="w-full justify-between pl-0">
|
|
82
|
-
<
|
|
87
|
+
<Label>{$fieldStore.label}</Label>
|
|
83
88
|
<FieldMessage {fieldStore} />
|
|
84
89
|
|
|
85
90
|
<i class="fa fa-sort" />
|
|
@@ -87,7 +92,7 @@ const move_value_down = (index) => {
|
|
|
87
92
|
</Collapsible.Trigger>
|
|
88
93
|
<Collapsible.Content class="flex flex-col gap-y-1 pl-2">
|
|
89
94
|
{#each $fieldStore.sub_fields || [] as sub_field, index (get_store_value(sub_field).id)}
|
|
90
|
-
<div class="flex items-center space-x-2
|
|
95
|
+
<div class="flex w-full items-center space-x-2">
|
|
91
96
|
<!-- up and down sort buttons -->
|
|
92
97
|
<div class="flex flex-col items-center space-y-1">
|
|
93
98
|
<Button variant="ghost" class="h-6 w-6 p-2" on:click={() => move_value_up(index)}>
|
|
@@ -103,8 +108,11 @@ const move_value_down = (index) => {
|
|
|
103
108
|
</Button>
|
|
104
109
|
</div>
|
|
105
110
|
{/each}
|
|
106
|
-
<
|
|
107
|
-
<
|
|
108
|
-
|
|
111
|
+
<div class="flex items-center justify-between">
|
|
112
|
+
<Button size="icon" variant="outline" on:click={add_value}>
|
|
113
|
+
<i class="fa fa-plus" />
|
|
114
|
+
</Button>
|
|
115
|
+
<FieldExprToggle {fieldStore} />
|
|
116
|
+
</div>
|
|
109
117
|
</Collapsible.Content>
|
|
110
118
|
</Collapsible.Root>
|
|
@@ -19,6 +19,7 @@ import { Label } from "@stubber/ui/label";
|
|
|
19
19
|
import { isEqual } from "lodash-es";
|
|
20
20
|
import FieldMessage from "../FieldMessage.svelte";
|
|
21
21
|
import { set_value_details } from "../utils";
|
|
22
|
+
import FieldExprToggle from "../FieldExprToggle.svelte";
|
|
22
23
|
export let fieldStore;
|
|
23
24
|
let field = $fieldStore;
|
|
24
25
|
set_value_details(field, "label", field.label);
|
|
@@ -34,8 +35,9 @@ const on_change = (new_value) => {
|
|
|
34
35
|
};
|
|
35
36
|
</script>
|
|
36
37
|
|
|
37
|
-
<div class="w-full
|
|
38
|
+
<div class="flex w-full items-center gap-x-2">
|
|
38
39
|
<Checkbox {checked} onCheckedChange={on_change} />
|
|
39
40
|
<Label>{field.label}</Label>
|
|
41
|
+
<FieldExprToggle {fieldStore} />
|
|
40
42
|
</div>
|
|
41
43
|
<FieldMessage {fieldStore} />
|
|
@@ -115,6 +115,7 @@ function update_value(new_value) {
|
|
|
115
115
|
...cloneDeep(new_value)
|
|
116
116
|
};
|
|
117
117
|
update_params_from_value(value.params);
|
|
118
|
+
update_subfields_from_value(value.fields);
|
|
118
119
|
}
|
|
119
120
|
}
|
|
120
121
|
const field_types = Object.keys(fields).map((key) => ({
|
|
@@ -224,8 +225,24 @@ function update_params_from_value(new_value) {
|
|
|
224
225
|
}
|
|
225
226
|
function select_field_type(newValue, trigger) {
|
|
226
227
|
value.fieldtype = newValue;
|
|
228
|
+
field_param_spec = cloneDeep(field_params_spec_lookup[value.fieldtype ?? "unknown"]);
|
|
227
229
|
closeAndFocusTrigger(trigger);
|
|
228
230
|
}
|
|
231
|
+
let field_param_spec = cloneDeep(field_params_spec_lookup[value.fieldtype ?? "unknown"]);
|
|
232
|
+
const subfields_store = writable({});
|
|
233
|
+
$: update_subfields($subfields_store.fields);
|
|
234
|
+
function update_subfields(new_subfields) {
|
|
235
|
+
const cloned_new_subfields = cloneDeep(new_subfields);
|
|
236
|
+
if (!isEqual(value.fields, cloned_new_subfields) && !isEmpty(cloned_new_subfields)) {
|
|
237
|
+
value.fields = cloned_new_subfields;
|
|
238
|
+
update_fieldStore(value);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
function update_subfields_from_value(new_value) {
|
|
242
|
+
if (!isEqual(new_value, $subfields_store)) {
|
|
243
|
+
subfields_store.set({ fields: cloneDeep(new_value) || {} });
|
|
244
|
+
}
|
|
245
|
+
}
|
|
229
246
|
</script>
|
|
230
247
|
|
|
231
248
|
<FieldLabel {fieldStore} />
|
|
@@ -238,13 +255,13 @@ function select_field_type(newValue, trigger) {
|
|
|
238
255
|
variant="outline"
|
|
239
256
|
role="combobox"
|
|
240
257
|
aria-expanded={open}
|
|
241
|
-
class="w-full border-input bg-white bg-opacity-[15]
|
|
258
|
+
class="flex h-10 w-full justify-between rounded-md border border-input bg-white bg-opacity-[15] px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
|
242
259
|
>
|
|
243
260
|
{selectedValue}
|
|
244
261
|
<i class="fas fa-sort ml-2 h-4 w-4 shrink-0 opacity-50" />
|
|
245
262
|
</Button>
|
|
246
263
|
</Popover.Trigger>
|
|
247
|
-
<Popover.Content class="p-0" sameWidth>
|
|
264
|
+
<Popover.Content class="max-h-[50vh] overflow-y-scroll p-0" sameWidth>
|
|
248
265
|
<Command.Root>
|
|
249
266
|
<Command.Input placeholder="Search framework..." />
|
|
250
267
|
<Command.Empty>No fieldtype found.</Command.Empty>
|
|
@@ -281,11 +298,11 @@ function select_field_type(newValue, trigger) {
|
|
|
281
298
|
bind:value={value.title}
|
|
282
299
|
/>
|
|
283
300
|
</div>
|
|
284
|
-
<div class="w-full
|
|
301
|
+
<div class="flex w-full items-center space-x-2">
|
|
285
302
|
<Checkbox id="without_value_details" bind:checked={value.without_value_details} />
|
|
286
303
|
<Label for="without_value_details">Without Value Details</Label>
|
|
287
304
|
</div>
|
|
288
|
-
<div class="w-full
|
|
305
|
+
<div class="flex w-full items-center space-x-2">
|
|
289
306
|
<Checkbox id="hide_label" bind:checked={value.hide_label} />
|
|
290
307
|
<Label for="hide_label">Hide Label</Label>
|
|
291
308
|
</div>
|
|
@@ -300,8 +317,50 @@ function select_field_type(newValue, trigger) {
|
|
|
300
317
|
</Collapsible.Content>
|
|
301
318
|
</Collapsible.Root>
|
|
302
319
|
<hr />
|
|
320
|
+
<!-- subfields -->
|
|
321
|
+
{#if value.fieldtype === "section" || value.fieldtype === "multistep"}
|
|
322
|
+
<Collapsible.Root open={false} class="w-full">
|
|
323
|
+
<Collapsible.Trigger asChild let:builder>
|
|
324
|
+
<Button builders={[builder]} variant="ghost" class="w-full justify-between pl-0">
|
|
325
|
+
<Label>Fields</Label>
|
|
326
|
+
|
|
327
|
+
<i class="fa fa-sort" />
|
|
328
|
+
</Button>
|
|
329
|
+
</Collapsible.Trigger>
|
|
330
|
+
|
|
331
|
+
<Collapsible.Content class="flex flex-col gap-y-2 pl-2 pt-2">
|
|
332
|
+
<Form
|
|
333
|
+
form={subfields_store}
|
|
334
|
+
initial_form={{
|
|
335
|
+
spec: {
|
|
336
|
+
fields: {
|
|
337
|
+
fields: {
|
|
338
|
+
hide_label: true,
|
|
339
|
+
fieldtype: "objectbuilder",
|
|
340
|
+
help: "Fields within this section/multistep",
|
|
341
|
+
params: {
|
|
342
|
+
value_field_spec: {
|
|
343
|
+
fieldtype: "fieldbuilder",
|
|
344
|
+
initvalue: {
|
|
345
|
+
has_default: true,
|
|
346
|
+
default: {
|
|
347
|
+
fieldtype: "text",
|
|
348
|
+
},
|
|
349
|
+
},
|
|
350
|
+
},
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
}}
|
|
356
|
+
/>
|
|
357
|
+
</Collapsible.Content>
|
|
358
|
+
</Collapsible.Root>
|
|
359
|
+
<hr />
|
|
360
|
+
{/if}
|
|
361
|
+
|
|
303
362
|
<!-- params -->
|
|
304
|
-
<Collapsible.Root open={
|
|
363
|
+
<Collapsible.Root open={false} class="w-full">
|
|
305
364
|
<Collapsible.Trigger asChild let:builder>
|
|
306
365
|
<Button builders={[builder]} variant="ghost" class="w-full justify-between pl-0">
|
|
307
366
|
<Label>Params</Label>
|
|
@@ -311,16 +370,16 @@ function select_field_type(newValue, trigger) {
|
|
|
311
370
|
</Collapsible.Trigger>
|
|
312
371
|
|
|
313
372
|
<Collapsible.Content class="flex flex-col gap-y-2 pl-2 pt-2">
|
|
314
|
-
<!-- todo this doesnt update when fieldtype changes -->
|
|
315
|
-
{@const field_param_spec = field_params_spec_lookup[value.fieldtype ?? "unknown"]}
|
|
316
373
|
{#if field_param_spec}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
374
|
+
{#key value.fieldtype}
|
|
375
|
+
<Form
|
|
376
|
+
initial_form={field_param_spec}
|
|
377
|
+
form={params_store}
|
|
378
|
+
attachments={$fieldStore.attachmentsStore}
|
|
379
|
+
/>
|
|
380
|
+
{/key}
|
|
322
381
|
{:else}
|
|
323
|
-
<span class="text-muted-foreground
|
|
382
|
+
<span class="text-xs text-muted-foreground">No params available for this fieldtype.</span>
|
|
324
383
|
{/if}
|
|
325
384
|
</Collapsible.Content>
|
|
326
385
|
</Collapsible.Root>
|
|
@@ -367,14 +426,14 @@ function select_field_type(newValue, trigger) {
|
|
|
367
426
|
|
|
368
427
|
<Collapsible.Content class="flex flex-col gap-y-2 pl-2">
|
|
369
428
|
<div>
|
|
370
|
-
<div class="w-full
|
|
429
|
+
<div class="flex w-full items-center space-x-2">
|
|
371
430
|
<Checkbox id="has_default" bind:checked={value.initvalue.has_default} />
|
|
372
431
|
<Label for="has_default">Has Default</Label>
|
|
373
432
|
</div>
|
|
374
433
|
<JsonEditorBound bind:value={value.initvalue.default} />
|
|
375
434
|
</div>
|
|
376
435
|
<div>
|
|
377
|
-
<div class="w-full
|
|
436
|
+
<div class="flex w-full items-center space-x-2">
|
|
378
437
|
<Checkbox id="has_override" bind:checked={value.initvalue.has_override} />
|
|
379
438
|
<Label for="has_override">Has Override</Label>
|
|
380
439
|
</div>
|
|
@@ -400,7 +459,7 @@ function select_field_type(newValue, trigger) {
|
|
|
400
459
|
|
|
401
460
|
{#if value.conditions && value.conditions.length > 0}
|
|
402
461
|
{#each value.conditions as condition, index}
|
|
403
|
-
<div class="flex items-center space-x-2
|
|
462
|
+
<div class="flex w-full items-center space-x-2">
|
|
404
463
|
<!-- up and down sort buttons -->
|
|
405
464
|
<div class="flex flex-col items-center">
|
|
406
465
|
<Button
|
|
@@ -455,7 +514,7 @@ function select_field_type(newValue, trigger) {
|
|
|
455
514
|
|
|
456
515
|
{#if value.validations && value.validations.length > 0}
|
|
457
516
|
{#each value.validations as validation, index}
|
|
458
|
-
<div class="flex items-start space-x-2
|
|
517
|
+
<div class="flex w-full items-start space-x-2">
|
|
459
518
|
<!-- up and down sort buttons -->
|
|
460
519
|
<div class="flex flex-col items-center">
|
|
461
520
|
<Button
|
|
@@ -475,7 +534,7 @@ function select_field_type(newValue, trigger) {
|
|
|
475
534
|
<i class="fa fa-chevron-down" />
|
|
476
535
|
</Button>
|
|
477
536
|
</div>
|
|
478
|
-
<div class="w-full flex
|
|
537
|
+
<div class="flex w-full flex-col items-stretch gap-1">
|
|
479
538
|
<Select.Root
|
|
480
539
|
selected={{
|
|
481
540
|
label: value.validations[index].validationtype,
|
|
@@ -2,8 +2,13 @@
|
|
|
2
2
|
spec: {
|
|
3
3
|
fields: {
|
|
4
4
|
columnDefs: {
|
|
5
|
-
fieldtype: "
|
|
6
|
-
|
|
5
|
+
fieldtype: "arraybuilder",
|
|
6
|
+
params: {
|
|
7
|
+
new_entry_field: {
|
|
8
|
+
fieldtype: "jsoneditor"
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
help: "See https://www.ag-grid.com/javascript-data-grid/column-definitions/"
|
|
7
12
|
}
|
|
8
13
|
}
|
|
9
14
|
}
|
|
@@ -50,5 +55,5 @@ onMount(() => {
|
|
|
50
55
|
</script>
|
|
51
56
|
|
|
52
57
|
<FieldLabel {fieldStore} />
|
|
53
|
-
<div bind:this={gridDiv} class="ag-theme-material w-full
|
|
58
|
+
<div bind:this={gridDiv} class="ag-theme-material h-96 w-full" />
|
|
54
59
|
<FieldMessage {fieldStore} />
|
|
@@ -16,9 +16,9 @@ export const object_builder_field_param_spec = {
|
|
|
16
16
|
<script>import * as Collapsible from "@stubber/ui/collapsible";
|
|
17
17
|
import { Button } from "@stubber/ui/button";
|
|
18
18
|
import { Input } from "@stubber/ui/input";
|
|
19
|
-
import {
|
|
19
|
+
import { Label } from "@stubber/ui/label";
|
|
20
20
|
import { cloneDeep } from "lodash-es";
|
|
21
|
-
import
|
|
21
|
+
import FieldExprToggle from "../FieldExprToggle.svelte";
|
|
22
22
|
import FieldMessage from "../FieldMessage.svelte";
|
|
23
23
|
import FormField from "../form-field.svelte";
|
|
24
24
|
import { build_field } from "../utils";
|
|
@@ -73,7 +73,7 @@ const make_key_unique = (key) => {
|
|
|
73
73
|
<Collapsible.Root open={true} class="w-full">
|
|
74
74
|
<Collapsible.Trigger asChild let:builder>
|
|
75
75
|
<Button builders={[builder]} variant="ghost" class="w-full justify-between pl-0">
|
|
76
|
-
<
|
|
76
|
+
<Label>{$fieldStore.label}</Label>
|
|
77
77
|
<FieldMessage {fieldStore} />
|
|
78
78
|
|
|
79
79
|
<i class="fa fa-sort" />
|
|
@@ -102,7 +102,7 @@ const make_key_unique = (key) => {
|
|
|
102
102
|
</Button>
|
|
103
103
|
</div>
|
|
104
104
|
</div>
|
|
105
|
-
<Collapsible.Content class="pl-6
|
|
105
|
+
<Collapsible.Content class="mt-2 pl-6">
|
|
106
106
|
{@const built_value_field = build_field(
|
|
107
107
|
$fieldStore.formStore,
|
|
108
108
|
$fieldStore.attachmentsStore,
|
|
@@ -116,8 +116,12 @@ const make_key_unique = (key) => {
|
|
|
116
116
|
</Collapsible.Root>
|
|
117
117
|
<!-- <Separator class="my-2" /> -->
|
|
118
118
|
{/each}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
119
|
+
|
|
120
|
+
<div class="flex items-center justify-between">
|
|
121
|
+
<Button size="icon" variant="outline" on:click={add_value}>
|
|
122
|
+
<i class="fa fa-plus" />
|
|
123
|
+
</Button>
|
|
124
|
+
<FieldExprToggle {fieldStore} />
|
|
125
|
+
</div>
|
|
122
126
|
</Collapsible.Content>
|
|
123
127
|
</Collapsible.Root>
|
|
@@ -23,6 +23,7 @@ import { isEqual } from "lodash-es";
|
|
|
23
23
|
import FieldMessage from "../FieldMessage.svelte";
|
|
24
24
|
import { set_value_details } from "../utils";
|
|
25
25
|
import { onMount } from "svelte";
|
|
26
|
+
import FieldExprToggle from "../FieldExprToggle.svelte";
|
|
26
27
|
export let fieldStore;
|
|
27
28
|
let params = $fieldStore.params;
|
|
28
29
|
let yes_value = params?.checkedvalue ?? true;
|
|
@@ -59,11 +60,11 @@ const update_value_details = (new_value) => {
|
|
|
59
60
|
};
|
|
60
61
|
</script>
|
|
61
62
|
|
|
62
|
-
<div class="
|
|
63
|
+
<div class="my-2 flex w-full flex-col text-surface-900">
|
|
63
64
|
<!-- div with inner shadow -->
|
|
64
65
|
<div
|
|
65
66
|
bind:this={outer}
|
|
66
|
-
class="
|
|
67
|
+
class="max-h-[300px] overflow-y-scroll rounded-md border shadow-inner"
|
|
67
68
|
on:scroll={handle_scroll}
|
|
68
69
|
>
|
|
69
70
|
<div class="p-6 px-2">
|
|
@@ -73,9 +74,7 @@ const update_value_details = (new_value) => {
|
|
|
73
74
|
<div
|
|
74
75
|
class="{!scrolled_to_bottom
|
|
75
76
|
? 'opacity-20'
|
|
76
|
-
: ''}
|
|
77
|
-
? 'border-b border-warning-500'
|
|
78
|
-
: ''}"
|
|
77
|
+
: ''} relative mt-2 flex items-center gap-x-2 {is_error ? 'border-b border-warning-500' : ''}"
|
|
79
78
|
>
|
|
80
79
|
<Checkbox
|
|
81
80
|
disabled={!scrolled_to_bottom}
|
|
@@ -87,6 +86,7 @@ const update_value_details = (new_value) => {
|
|
|
87
86
|
<Label for="input_{$fieldStore.id}" class="block">
|
|
88
87
|
{$fieldStore.label}
|
|
89
88
|
</Label>
|
|
89
|
+
<FieldExprToggle {fieldStore} />
|
|
90
90
|
</div>
|
|
91
91
|
<FieldMessage {fieldStore} />
|
|
92
92
|
</div>
|
|
@@ -6,22 +6,25 @@ import * as Collapsible from "@stubber/ui/collapsible";
|
|
|
6
6
|
import FieldLabel from "../FieldLabel.svelte";
|
|
7
7
|
import FieldMessage from "../FieldMessage.svelte";
|
|
8
8
|
import FormField from "../form-field.svelte";
|
|
9
|
+
import { Label } from "@stubber/ui/label";
|
|
10
|
+
import FieldExprToggle from "../FieldExprToggle.svelte";
|
|
9
11
|
export let fieldStore;
|
|
10
12
|
</script>
|
|
11
13
|
|
|
12
14
|
<Collapsible.Root open={true} class="w-full">
|
|
13
15
|
<Collapsible.Trigger asChild let:builder>
|
|
14
16
|
<Button builders={[builder]} variant="ghost" class="w-full justify-between pl-0">
|
|
15
|
-
<
|
|
17
|
+
<Label>{$fieldStore.label}</Label>
|
|
16
18
|
<FieldMessage {fieldStore} />
|
|
17
19
|
|
|
18
20
|
<i class="fa fa-sort" />
|
|
19
21
|
</Button>
|
|
20
22
|
</Collapsible.Trigger>
|
|
21
23
|
|
|
22
|
-
<Collapsible.Content class="flex flex-col gap-y-
|
|
24
|
+
<Collapsible.Content class="flex flex-col gap-y-2 pl-2">
|
|
23
25
|
{#each $fieldStore.sub_fields || [] as sub_field (get_store_value(sub_field).id)}
|
|
24
26
|
<FormField fieldStore={sub_field} />
|
|
25
27
|
{/each}
|
|
28
|
+
<FieldExprToggle {fieldStore} />
|
|
26
29
|
</Collapsible.Content>
|
|
27
30
|
</Collapsible.Root>
|
|
@@ -87,8 +87,8 @@ export const regex_validation = (results, value, validation) => {
|
|
|
87
87
|
export const jsonata_validation = async (results, _value, validation, context = {}) => {
|
|
88
88
|
try {
|
|
89
89
|
let result = await jsonata(validation.params.jsonata).evaluate(context);
|
|
90
|
-
console.log(`jsonata context:`, context);
|
|
91
|
-
console.log(`jsonata ${validation.params.jsonata} result:`, result);
|
|
90
|
+
// console.log(`jsonata context:`, context);
|
|
91
|
+
// console.log(`jsonata ${validation.params.jsonata} result:`, result);
|
|
92
92
|
if (!result) {
|
|
93
93
|
results.push({
|
|
94
94
|
message: validation.invalid_message || "This field is invalid.",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stubber/form-fields",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "An automatic form builder based on field specifications",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"components",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"scripts": {
|
|
29
29
|
"dev": "vite dev --host",
|
|
30
|
-
"build": "vite build
|
|
30
|
+
"build": "vite build",
|
|
31
31
|
"package": "svelte-kit sync && svelte-package && publint",
|
|
32
32
|
"preview": "vite preview",
|
|
33
33
|
"check": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json",
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
},
|
|
95
95
|
"release": {
|
|
96
96
|
"branches": [
|
|
97
|
-
"
|
|
97
|
+
"staging"
|
|
98
98
|
],
|
|
99
99
|
"plugins": [
|
|
100
100
|
"@semantic-release/commit-analyzer",
|