@stubber/form-fields 1.4.6 → 1.5.1
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 +61 -295
- package/dist/fields2/FieldLabel.svelte +8 -0
- package/dist/fields2/FieldLabel.svelte.d.ts +20 -0
- package/dist/fields2/FieldMessage.svelte +16 -0
- package/dist/fields2/FieldMessage.svelte.d.ts +20 -0
- package/dist/fields2/Form.svelte +29 -0
- package/dist/fields2/Form.svelte.d.ts +23 -0
- package/dist/fields2/fileserver.d.ts +15 -0
- package/dist/fields2/fileserver.js +52 -0
- package/dist/fields2/form-field.svelte +10 -0
- package/dist/fields2/form-field.svelte.d.ts +20 -0
- package/dist/fields2/index.d.ts +3 -0
- package/dist/fields2/index.js +2 -0
- package/dist/fields2/interfaces.d.ts +207 -0
- package/dist/fields2/interfaces.js +82 -0
- package/dist/fields2/sub/array-builder-field.svelte +110 -0
- package/dist/fields2/sub/array-builder-field.svelte.d.ts +27 -0
- package/dist/fields2/sub/checkbox-autocomplete.svelte +56 -0
- package/dist/fields2/sub/checkbox-autocomplete.svelte.d.ts +27 -0
- package/dist/fields2/sub/checkbox-field.svelte +41 -0
- package/dist/fields2/sub/checkbox-field.svelte.d.ts +28 -0
- package/dist/fields2/sub/code-field.svelte +146 -0
- package/dist/fields2/sub/code-field.svelte.d.ts +27 -0
- package/dist/fields2/sub/contact-selector-field.svelte +84 -0
- package/dist/fields2/sub/contact-selector-field.svelte.d.ts +30 -0
- package/dist/fields2/sub/currency-field.svelte +197 -0
- package/dist/fields2/sub/currency-field.svelte.d.ts +29 -0
- package/dist/fields2/sub/data-indication-field.svelte +19 -0
- package/dist/fields2/sub/data-indication-field.svelte.d.ts +23 -0
- package/dist/fields2/sub/date-field.svelte +31 -0
- package/dist/fields2/sub/date-field.svelte.d.ts +23 -0
- package/dist/fields2/sub/date-time-field.svelte +31 -0
- package/dist/fields2/sub/date-time-field.svelte.d.ts +23 -0
- package/dist/fields2/sub/email-field.svelte +40 -0
- package/dist/fields2/sub/email-field.svelte.d.ts +23 -0
- package/dist/fields2/sub/field-builder-field.svelte +525 -0
- package/dist/fields2/sub/field-builder-field.svelte.d.ts +23 -0
- package/dist/fields2/sub/file-field.svelte +150 -0
- package/dist/fields2/sub/file-field.svelte.d.ts +27 -0
- package/dist/fields2/sub/grid-field.svelte +54 -0
- package/dist/fields2/sub/grid-field.svelte.d.ts +30 -0
- package/dist/fields2/sub/heading-field.svelte +28 -0
- package/dist/fields2/sub/heading-field.svelte.d.ts +28 -0
- package/dist/fields2/sub/hidden-field.svelte +142 -0
- package/dist/fields2/sub/hidden-field.svelte.d.ts +37 -0
- package/dist/fields2/sub/hidden-location-field.svelte +23 -0
- package/dist/fields2/sub/hidden-location-field.svelte.d.ts +23 -0
- package/dist/fields2/sub/html-field.svelte +22 -0
- package/dist/fields2/sub/html-field.svelte.d.ts +27 -0
- package/dist/fields2/sub/json-editor-bound.svelte +17 -0
- package/dist/fields2/sub/json-editor-bound.svelte.d.ts +65 -0
- package/dist/fields2/sub/jsoneditor-field.svelte +23 -0
- package/dist/fields2/sub/jsoneditor-field.svelte.d.ts +27 -0
- package/dist/fields2/sub/map-field.svelte +144 -0
- package/dist/fields2/sub/map-field.svelte.d.ts +28 -0
- package/dist/fields2/sub/multi-checkbox-field.svelte +83 -0
- package/dist/fields2/sub/multi-checkbox-field.svelte.d.ts +34 -0
- package/dist/fields2/sub/multistep-field.svelte +70 -0
- package/dist/fields2/sub/multistep-field.svelte.d.ts +24 -0
- package/dist/fields2/sub/note-field.svelte +18 -0
- package/dist/fields2/sub/note-field.svelte.d.ts +23 -0
- package/dist/fields2/sub/number-field.svelte +77 -0
- package/dist/fields2/sub/number-field.svelte.d.ts +29 -0
- package/dist/fields2/sub/object-builder-field.svelte +123 -0
- package/dist/fields2/sub/object-builder-field.svelte.d.ts +28 -0
- package/dist/fields2/sub/qr-code-scanner-field.svelte +86 -0
- package/dist/fields2/sub/qr-code-scanner-field.svelte.d.ts +23 -0
- package/dist/fields2/sub/radio-field.svelte +69 -0
- package/dist/fields2/sub/radio-field.svelte.d.ts +30 -0
- package/dist/fields2/sub/screenrecorder-field.svelte +182 -0
- package/dist/fields2/sub/screenrecorder-field.svelte.d.ts +27 -0
- package/dist/fields2/sub/screenshot-field.svelte +165 -0
- package/dist/fields2/sub/screenshot-field.svelte.d.ts +26 -0
- package/dist/fields2/sub/scroll-and-read-display-field.svelte +92 -0
- package/dist/fields2/sub/scroll-and-read-display-field.svelte.d.ts +29 -0
- package/dist/fields2/sub/section-field.svelte +27 -0
- package/dist/fields2/sub/section-field.svelte.d.ts +26 -0
- package/dist/fields2/sub/select-field.svelte +138 -0
- package/dist/fields2/sub/select-field.svelte.d.ts +34 -0
- package/dist/fields2/sub/selectresource-field.svelte +69 -0
- package/dist/fields2/sub/selectresource-field.svelte.d.ts +29 -0
- package/dist/fields2/sub/signature-field.svelte +84 -0
- package/dist/fields2/sub/signature-field.svelte.d.ts +23 -0
- package/dist/fields2/sub/slider-field.svelte +28 -0
- package/dist/fields2/sub/slider-field.svelte.d.ts +28 -0
- package/dist/fields2/sub/smart-text-field.svelte +245 -0
- package/dist/fields2/sub/smart-text-field.svelte.d.ts +36 -0
- package/dist/fields2/sub/telephone-field.svelte +68 -0
- package/dist/fields2/sub/telephone-field.svelte.d.ts +26 -0
- package/dist/fields2/sub/text-field.svelte +46 -0
- package/dist/fields2/sub/text-field.svelte.d.ts +27 -0
- package/dist/fields2/sub/voicenote-field.svelte +161 -0
- package/dist/fields2/sub/voicenote-field.svelte.d.ts +26 -0
- package/dist/fields2/utils.d.ts +9 -0
- package/dist/fields2/utils.js +116 -0
- package/dist/fields2/validations/validate_field.d.ts +11 -0
- package/dist/fields2/validations/validate_field.js +121 -0
- package/package.json +10 -9
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
<script context="module">import {} from "../interfaces";
|
|
2
|
+
export const code_field_param_spec = {
|
|
3
|
+
spec: {
|
|
4
|
+
fields: {
|
|
5
|
+
globals: {
|
|
6
|
+
fieldtype: "jsoneditor",
|
|
7
|
+
help: "Global variables available in the code editor."
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<script>import { Textarea } from "@stubber/ui/textarea";
|
|
15
|
+
import FieldLabel from "../FieldLabel.svelte";
|
|
16
|
+
import FieldMessage from "../FieldMessage.svelte";
|
|
17
|
+
import {
|
|
18
|
+
acceptCompletion,
|
|
19
|
+
autocompletion,
|
|
20
|
+
CompletionContext,
|
|
21
|
+
completionKeymap,
|
|
22
|
+
startCompletion
|
|
23
|
+
} from "@codemirror/autocomplete";
|
|
24
|
+
import { javascript, javascriptLanguage } from "@codemirror/lang-javascript";
|
|
25
|
+
import { EditorState } from "@codemirror/state";
|
|
26
|
+
import { EditorView, keymap } from "@codemirror/view";
|
|
27
|
+
import { basicSetup } from "codemirror";
|
|
28
|
+
export let fieldStore;
|
|
29
|
+
let value = $fieldStore.value || "";
|
|
30
|
+
let editor_view;
|
|
31
|
+
const custom_completion_keymap = completionKeymap.filter((binding) => binding.key != "Enter").concat([
|
|
32
|
+
{
|
|
33
|
+
key: "Enter",
|
|
34
|
+
run: () => {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
key: "Tab",
|
|
40
|
+
run: acceptCompletion
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
key: "Ctrl-Space",
|
|
44
|
+
run: startCompletion,
|
|
45
|
+
stopPropagation: true
|
|
46
|
+
}
|
|
47
|
+
]);
|
|
48
|
+
function keysFor(obj) {
|
|
49
|
+
return Object.keys(obj ?? {});
|
|
50
|
+
}
|
|
51
|
+
function globalCompletions(ctx) {
|
|
52
|
+
const m = ctx.matchBefore(/[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*\.?/);
|
|
53
|
+
if (!m && !ctx.explicit) return null;
|
|
54
|
+
const text = m?.text ?? "";
|
|
55
|
+
const trailingDot = text.endsWith(".");
|
|
56
|
+
const parts = (trailingDot ? text.slice(0, -1) : text).split(".").filter(Boolean);
|
|
57
|
+
let container = $fieldStore.params?.globals || {};
|
|
58
|
+
for (let i = 0; i < Math.max(0, parts.length - (trailingDot ? 0 : 1)); i++) {
|
|
59
|
+
container = container?.[parts[i]];
|
|
60
|
+
if (!container) break;
|
|
61
|
+
}
|
|
62
|
+
const last = trailingDot ? "" : parts[parts.length - 1] ?? "";
|
|
63
|
+
const from = ctx.pos - last.length;
|
|
64
|
+
return {
|
|
65
|
+
from,
|
|
66
|
+
options: keysFor(container).map((key) => ({
|
|
67
|
+
label: key,
|
|
68
|
+
type: "property"
|
|
69
|
+
// 👈 simplified
|
|
70
|
+
})),
|
|
71
|
+
validFor: /^\w*$/
|
|
72
|
+
// keep suggestions stable while typing
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const stubber_completions = javascriptLanguage.data.of({
|
|
76
|
+
autocomplete: globalCompletions
|
|
77
|
+
});
|
|
78
|
+
function bind_codemirror(el) {
|
|
79
|
+
const min_height_editor = EditorView.theme({
|
|
80
|
+
".cm-content, .cm-gutter": { minHeight: "200px" },
|
|
81
|
+
"&": { maxHeight: "300px" },
|
|
82
|
+
".cm-scroller": { overflow: "auto" }
|
|
83
|
+
});
|
|
84
|
+
editor_view = new EditorView({
|
|
85
|
+
state: EditorState.create({
|
|
86
|
+
doc: value,
|
|
87
|
+
extensions: [
|
|
88
|
+
basicSetup,
|
|
89
|
+
javascript(),
|
|
90
|
+
stubber_completions,
|
|
91
|
+
autocompletion({ defaultKeymap: false }),
|
|
92
|
+
keymap.of(custom_completion_keymap),
|
|
93
|
+
min_height_editor,
|
|
94
|
+
update_listener
|
|
95
|
+
]
|
|
96
|
+
}),
|
|
97
|
+
parent: el
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
const update_listener = EditorView.updateListener.of((update) => {
|
|
101
|
+
if (update.docChanged) {
|
|
102
|
+
const new_value = update.state.doc.toString();
|
|
103
|
+
if (new_value !== value) {
|
|
104
|
+
value = new_value;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
$: sync_field_to_editor(value);
|
|
109
|
+
const sync_field_to_editor = (new_value) => {
|
|
110
|
+
if (editor_view && editor_view.state.doc.toString() !== new_value) {
|
|
111
|
+
editor_view.dispatch({
|
|
112
|
+
changes: {
|
|
113
|
+
from: 0,
|
|
114
|
+
to: editor_view.state.doc.length,
|
|
115
|
+
insert: new_value
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
if ($fieldStore.value !== new_value) {
|
|
120
|
+
$fieldStore.value = new_value;
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
$: sync_field_to_value($fieldStore.value);
|
|
124
|
+
const sync_field_to_value = (new_value) => {
|
|
125
|
+
if (new_value !== value) {
|
|
126
|
+
value = new_value;
|
|
127
|
+
if (editor_view?.state.doc.toString() !== new_value) {
|
|
128
|
+
editor_view.dispatch({
|
|
129
|
+
changes: {
|
|
130
|
+
from: 0,
|
|
131
|
+
to: editor_view.state.doc.length,
|
|
132
|
+
insert: new_value
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
</script>
|
|
139
|
+
|
|
140
|
+
<div class="flex flex-col w-full my-2">
|
|
141
|
+
<FieldLabel {fieldStore} />
|
|
142
|
+
<div class="relative rounded-md">
|
|
143
|
+
<div use:bind_codemirror />
|
|
144
|
+
</div>
|
|
145
|
+
<FieldMessage {fieldStore} />
|
|
146
|
+
</div>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
import type { Writable } from "svelte/store";
|
|
3
|
+
import { type IBaseField, type IBuiltField, type IInitialForm } from "../interfaces";
|
|
4
|
+
interface ICodeFieldParams {
|
|
5
|
+
globals?: Record<string, any>;
|
|
6
|
+
}
|
|
7
|
+
export declare const code_field_param_spec: IInitialForm;
|
|
8
|
+
export interface ICodeField extends IBaseField<ICodeFieldParams> {
|
|
9
|
+
fieldtype: "code";
|
|
10
|
+
}
|
|
11
|
+
declare const __propDef: {
|
|
12
|
+
props: {
|
|
13
|
+
fieldStore: Writable<IBuiltField<ICodeFieldParams>>;
|
|
14
|
+
};
|
|
15
|
+
events: {
|
|
16
|
+
[evt: string]: CustomEvent<any>;
|
|
17
|
+
};
|
|
18
|
+
slots: {};
|
|
19
|
+
exports?: {} | undefined;
|
|
20
|
+
bindings?: string | undefined;
|
|
21
|
+
};
|
|
22
|
+
export type CodeFieldProps = typeof __propDef.props;
|
|
23
|
+
export type CodeFieldEvents = typeof __propDef.events;
|
|
24
|
+
export type CodeFieldSlots = typeof __propDef.slots;
|
|
25
|
+
export default class CodeField extends SvelteComponent<CodeFieldProps, CodeFieldEvents, CodeFieldSlots> {
|
|
26
|
+
}
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
<script context="module">export const contact_selector_field_param_spec = {
|
|
2
|
+
spec: {
|
|
3
|
+
fields: {
|
|
4
|
+
label: {
|
|
5
|
+
fieldtype: "text",
|
|
6
|
+
help: "The contact field to use as the label in the dropdown options."
|
|
7
|
+
},
|
|
8
|
+
limit: {
|
|
9
|
+
fieldtype: "number",
|
|
10
|
+
help: "Limit the number of contacts returned."
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<script>import { Button } from "@stubber/ui/button";
|
|
18
|
+
import SelectField, {} from "./select-field.svelte";
|
|
19
|
+
export let fieldStore;
|
|
20
|
+
const params = $fieldStore.params || {};
|
|
21
|
+
const dependencies = $fieldStore.formDependencies;
|
|
22
|
+
const createWantToModal = dependencies?.createWantToModal;
|
|
23
|
+
const show_create_contact_modal = () => {
|
|
24
|
+
const stubref = dependencies?.stubber?.stubref;
|
|
25
|
+
const orguuid = dependencies?.stubber?.orguuid;
|
|
26
|
+
createWantToModal("_create_new_contact", stubref, orguuid);
|
|
27
|
+
};
|
|
28
|
+
const field = $fieldStore;
|
|
29
|
+
if (field.params) {
|
|
30
|
+
field.params.load_options = async (search_term) => {
|
|
31
|
+
const socket = dependencies?.clienthub?.socket;
|
|
32
|
+
const orguuid = dependencies?.stubber?.orguuid;
|
|
33
|
+
const stubref = dependencies?.stubber?.stubref;
|
|
34
|
+
if (!socket || !orguuid || !stubref) {
|
|
35
|
+
console.error("ClientHub socket or stubber details not available.");
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
const details = {
|
|
39
|
+
resource_name: "contacts"
|
|
40
|
+
};
|
|
41
|
+
details.params = $fieldStore.params || {};
|
|
42
|
+
details.params.orguuid = orguuid;
|
|
43
|
+
details.params.stubref = stubref;
|
|
44
|
+
details.params.input = search_term;
|
|
45
|
+
if (details.params.limit === void 0) {
|
|
46
|
+
details.params.limit = 50;
|
|
47
|
+
}
|
|
48
|
+
console.log("Loading contacts with details:", details);
|
|
49
|
+
return new Promise((resolve, reject) => {
|
|
50
|
+
socket.emit("request", { type: "resource", details }, (res) => {
|
|
51
|
+
if (res.success) {
|
|
52
|
+
console.log("Contacts loaded:", res);
|
|
53
|
+
const contacts = res.payload?.contacts || [];
|
|
54
|
+
const result = contacts.map((contact) => {
|
|
55
|
+
let label = contact._default_label;
|
|
56
|
+
if (params.label && contact[params.label]) {
|
|
57
|
+
label = contact[params.label];
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
value: contact,
|
|
61
|
+
label
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
resolve(result);
|
|
65
|
+
} else {
|
|
66
|
+
console.error("Failed to load contacts:", res);
|
|
67
|
+
resolve([]);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
</script>
|
|
74
|
+
|
|
75
|
+
<SelectField {fieldStore}>
|
|
76
|
+
<Button
|
|
77
|
+
on:click={show_create_contact_modal}
|
|
78
|
+
variant="ghost"
|
|
79
|
+
class="ml-auto text-surface-500 text-sm hover:text-surface-700"
|
|
80
|
+
>
|
|
81
|
+
<i class="fa-regular fa-plus" />
|
|
82
|
+
Create new contact
|
|
83
|
+
</Button>
|
|
84
|
+
</SelectField>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
import type { Writable } from "svelte/store";
|
|
3
|
+
import type { IBaseField, IBuiltField, IInitialForm } from "../interfaces";
|
|
4
|
+
export interface IContactSelectorFieldParams {
|
|
5
|
+
label?: string;
|
|
6
|
+
limit?: number;
|
|
7
|
+
load_options?: (search_term: string) => Promise<ISelectFieldOption[]>;
|
|
8
|
+
}
|
|
9
|
+
export declare const contact_selector_field_param_spec: IInitialForm;
|
|
10
|
+
export interface IContactSelectorField extends IBaseField<IContactSelectorFieldParams> {
|
|
11
|
+
fieldtype: "contactselector";
|
|
12
|
+
}
|
|
13
|
+
import { type ISelectFieldOption } from "./select-field.svelte";
|
|
14
|
+
declare const __propDef: {
|
|
15
|
+
props: {
|
|
16
|
+
fieldStore: Writable<IBuiltField<IContactSelectorFieldParams>>;
|
|
17
|
+
};
|
|
18
|
+
events: {
|
|
19
|
+
[evt: string]: CustomEvent<any>;
|
|
20
|
+
};
|
|
21
|
+
slots: {};
|
|
22
|
+
exports?: {} | undefined;
|
|
23
|
+
bindings?: string | undefined;
|
|
24
|
+
};
|
|
25
|
+
export type ContactSelectorFieldProps = typeof __propDef.props;
|
|
26
|
+
export type ContactSelectorFieldEvents = typeof __propDef.events;
|
|
27
|
+
export type ContactSelectorFieldSlots = typeof __propDef.slots;
|
|
28
|
+
export default class ContactSelectorField extends SvelteComponent<ContactSelectorFieldProps, ContactSelectorFieldEvents, ContactSelectorFieldSlots> {
|
|
29
|
+
}
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
<script context="module">const currency_codes = Intl.supportedValuesOf("currency");
|
|
2
|
+
const currency_code_options = currency_codes.map((code) => ({
|
|
3
|
+
label: code,
|
|
4
|
+
value: code
|
|
5
|
+
}));
|
|
6
|
+
export const currency_field_param_spec = {
|
|
7
|
+
spec: {
|
|
8
|
+
fields: {
|
|
9
|
+
currency: {
|
|
10
|
+
fieldtype: "select",
|
|
11
|
+
without_value_details: true,
|
|
12
|
+
params: {
|
|
13
|
+
options: currency_code_options
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
currency_whitelist: {
|
|
17
|
+
fieldtype: "arraybuilder",
|
|
18
|
+
params: {
|
|
19
|
+
new_entry_field: {
|
|
20
|
+
fieldtype: "select",
|
|
21
|
+
without_value_details: true,
|
|
22
|
+
params: {
|
|
23
|
+
options: currency_code_options
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
help: "List of allowed currency codes (ISO 4217)"
|
|
28
|
+
},
|
|
29
|
+
currency_blacklist: {
|
|
30
|
+
fieldtype: "arraybuilder",
|
|
31
|
+
help: "List of disallowed currency codes (ISO 4217)",
|
|
32
|
+
params: {
|
|
33
|
+
new_entry_field: {
|
|
34
|
+
fieldtype: "select",
|
|
35
|
+
without_value_details: true,
|
|
36
|
+
params: {
|
|
37
|
+
options: currency_code_options
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
</script>
|
|
46
|
+
|
|
47
|
+
<script>import * as utils from "../../utils/index.js";
|
|
48
|
+
import { Button } from "@stubber/ui/button";
|
|
49
|
+
import * as Command from "@stubber/ui/command";
|
|
50
|
+
import * as Popover from "@stubber/ui/popover";
|
|
51
|
+
import getSymbolFromCurrency from "currency-symbol-map";
|
|
52
|
+
import currency from "currency.js";
|
|
53
|
+
import { get } from "lodash-es";
|
|
54
|
+
import { get as get_store_value } from "svelte/store";
|
|
55
|
+
import FieldLabel from "../FieldLabel.svelte";
|
|
56
|
+
import FieldMessage from "../FieldMessage.svelte";
|
|
57
|
+
import { set_value_details } from "../utils";
|
|
58
|
+
export let fieldStore;
|
|
59
|
+
let field = $fieldStore;
|
|
60
|
+
let params = field.params;
|
|
61
|
+
const currencyRegex = /^([0-9]+(\.?[0-9]?[0-9]?)?)$/;
|
|
62
|
+
const currencyName = new Intl.DisplayNames("en-US", {
|
|
63
|
+
type: "currency"
|
|
64
|
+
});
|
|
65
|
+
let { inputRegexMask } = utils;
|
|
66
|
+
let initial_ui_value = $fieldStore.value || "";
|
|
67
|
+
let currency_list = [];
|
|
68
|
+
const build_currency_list_from_codes = (codes) => {
|
|
69
|
+
const currencies = [];
|
|
70
|
+
for (const code of codes) {
|
|
71
|
+
try {
|
|
72
|
+
const name = currencyName.of(code);
|
|
73
|
+
if (!name) continue;
|
|
74
|
+
const symbol = getSymbolFromCurrency(code);
|
|
75
|
+
if (!symbol) continue;
|
|
76
|
+
currencies.push({
|
|
77
|
+
value: code,
|
|
78
|
+
symbol,
|
|
79
|
+
name
|
|
80
|
+
});
|
|
81
|
+
} catch (err) {
|
|
82
|
+
console.warn(err);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return currencies;
|
|
87
|
+
};
|
|
88
|
+
if (params?.currency_whitelist && params.currency_whitelist.length > 0) {
|
|
89
|
+
currency_list = build_currency_list_from_codes(params.currency_whitelist);
|
|
90
|
+
} else if (params?.currency_blacklist && params.currency_blacklist.length > 0) {
|
|
91
|
+
const filtered_currencies = currency_codes.filter(
|
|
92
|
+
(c) => !params.currency_blacklist?.includes(c)
|
|
93
|
+
);
|
|
94
|
+
currency_list = build_currency_list_from_codes(filtered_currencies);
|
|
95
|
+
} else {
|
|
96
|
+
currency_list = build_currency_list_from_codes(currency_codes);
|
|
97
|
+
}
|
|
98
|
+
const details_data_path = field.data_path + "_details";
|
|
99
|
+
let current_details = get(get_store_value(field.formStore), details_data_path);
|
|
100
|
+
if (!current_details) {
|
|
101
|
+
current_details = {
|
|
102
|
+
cents: 0,
|
|
103
|
+
amount: 0,
|
|
104
|
+
currencycode: params?.currency || "USD",
|
|
105
|
+
currencysymbol: getSymbolFromCurrency(params?.currency || "USD") || "$"
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
const on_input = (e) => {
|
|
109
|
+
const input = e.target;
|
|
110
|
+
const new_value = input.value;
|
|
111
|
+
const currencycode_valid = current_details?.currencycode && currency_list.some((c) => c.value === current_details.currencycode);
|
|
112
|
+
if (!currencycode_valid) {
|
|
113
|
+
if (params?.currency && currency_list.some((c) => c.value === params.currency)) {
|
|
114
|
+
current_details.currencycode = params.currency;
|
|
115
|
+
} else if (currency_list.length > 0) {
|
|
116
|
+
current_details.currencycode = currency_list[0].value;
|
|
117
|
+
} else {
|
|
118
|
+
current_details.currencycode = "USD";
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
current_details.currencysymbol = getSymbolFromCurrency(current_details.currencycode) || current_details.currencysymbol || "USD";
|
|
122
|
+
current_details.cents = currency(new_value).intValue;
|
|
123
|
+
current_details.amount = currency(new_value).value;
|
|
124
|
+
field.value = current_details.amount ? current_details.amount.toFixed(2).toString() : "";
|
|
125
|
+
set_value_details(field, "details", current_details);
|
|
126
|
+
};
|
|
127
|
+
let open = false;
|
|
128
|
+
$: selectedValue = currency_list.find((c) => c.value === current_details?.currencycode)?.value || "Select Currency...";
|
|
129
|
+
</script>
|
|
130
|
+
|
|
131
|
+
<FieldLabel {fieldStore} />
|
|
132
|
+
<div
|
|
133
|
+
class="flex-row items-center gap-2 border-input bg-background selection:bg-primary dark:bg-input/30 selection:text-primary-foreground ring-offset-background placeholder:text-muted-foreground shadow-xs flex h-9 w-full min-w-0 rounded-md border px-3 py-1 text-base outline-none transition-[color,box-shadow] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-[invalid]:border-destructive aria-[invalid]:ring-destructive/50 aria-[invalid]:focus-visible:ring-destructive/50"
|
|
134
|
+
>
|
|
135
|
+
<!-- currency indicator front left -->
|
|
136
|
+
<div class="pointer-events-none text-gray-500">
|
|
137
|
+
{#if current_details?.currencysymbol}
|
|
138
|
+
{current_details.currencysymbol}
|
|
139
|
+
{:else if params?.currency}
|
|
140
|
+
{getSymbolFromCurrency(params.currency) || params.currency}
|
|
141
|
+
{:else}
|
|
142
|
+
$
|
|
143
|
+
{/if}
|
|
144
|
+
</div>
|
|
145
|
+
<input
|
|
146
|
+
class="w-full focus-within:outline-none bg-transparent"
|
|
147
|
+
use:inputRegexMask={currencyRegex}
|
|
148
|
+
value={initial_ui_value}
|
|
149
|
+
inputmode="decimal"
|
|
150
|
+
aria-invalid={$fieldStore.validation_result?.type == "error" ? true : undefined}
|
|
151
|
+
on:input={on_input}
|
|
152
|
+
/>
|
|
153
|
+
|
|
154
|
+
<!-- currency selector back right -->
|
|
155
|
+
{#if currency_list.length > 1 && !params?.currency}
|
|
156
|
+
<Popover.Root bind:open let:ids>
|
|
157
|
+
<Popover.Trigger asChild let:builder>
|
|
158
|
+
<Button
|
|
159
|
+
builders={[builder]}
|
|
160
|
+
variant="outline"
|
|
161
|
+
role="combobox"
|
|
162
|
+
aria-expanded={open}
|
|
163
|
+
class="w-28 border-none bg-transparent px-1 justify-between"
|
|
164
|
+
>
|
|
165
|
+
{selectedValue}
|
|
166
|
+
<i class="fas fa-sort ml-2 h-4 w-4 shrink-0 opacity-50" />
|
|
167
|
+
</Button>
|
|
168
|
+
</Popover.Trigger>
|
|
169
|
+
<Popover.Content class="p-0 max-h-[50vh] overflow-y-scroll">
|
|
170
|
+
<Command.Root>
|
|
171
|
+
<Command.Input placeholder="Search currencies..." />
|
|
172
|
+
<Command.Empty>No currency found.</Command.Empty>
|
|
173
|
+
<Command.Group>
|
|
174
|
+
{#each currency_list as c}
|
|
175
|
+
<Command.Item
|
|
176
|
+
value={c.value}
|
|
177
|
+
onSelect={(currentValue) => {
|
|
178
|
+
current_details = {
|
|
179
|
+
...current_details,
|
|
180
|
+
currencycode: currentValue,
|
|
181
|
+
currencysymbol: getSymbolFromCurrency(currentValue) || "",
|
|
182
|
+
};
|
|
183
|
+
set_value_details($fieldStore, "details", current_details);
|
|
184
|
+
open = false;
|
|
185
|
+
}}
|
|
186
|
+
class={selectedValue === c.value ? "bg-primary-100" : ""}
|
|
187
|
+
>
|
|
188
|
+
{c.value} - {c.name} ({c.symbol})
|
|
189
|
+
</Command.Item>
|
|
190
|
+
{/each}
|
|
191
|
+
</Command.Group>
|
|
192
|
+
</Command.Root>
|
|
193
|
+
</Popover.Content>
|
|
194
|
+
</Popover.Root>
|
|
195
|
+
{/if}
|
|
196
|
+
</div>
|
|
197
|
+
<FieldMessage {fieldStore} />
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
import type { IBaseField, IBuiltField, IInitialForm } from "../interfaces";
|
|
3
|
+
export interface ICurrencyFieldParams {
|
|
4
|
+
currency?: string;
|
|
5
|
+
currency_whitelist?: string[];
|
|
6
|
+
currency_blacklist?: string[];
|
|
7
|
+
}
|
|
8
|
+
export declare const currency_field_param_spec: IInitialForm;
|
|
9
|
+
export interface ICurrencyField extends IBaseField<ICurrencyFieldParams> {
|
|
10
|
+
fieldtype: "currency";
|
|
11
|
+
}
|
|
12
|
+
import { type Writable } from "svelte/store";
|
|
13
|
+
declare const __propDef: {
|
|
14
|
+
props: {
|
|
15
|
+
fieldStore: Writable<IBuiltField<ICurrencyFieldParams>>;
|
|
16
|
+
};
|
|
17
|
+
events: {
|
|
18
|
+
[evt: string]: CustomEvent<any>;
|
|
19
|
+
};
|
|
20
|
+
slots: {};
|
|
21
|
+
exports?: {} | undefined;
|
|
22
|
+
bindings?: string | undefined;
|
|
23
|
+
};
|
|
24
|
+
export type CurrencyFieldProps = typeof __propDef.props;
|
|
25
|
+
export type CurrencyFieldEvents = typeof __propDef.events;
|
|
26
|
+
export type CurrencyFieldSlots = typeof __propDef.slots;
|
|
27
|
+
export default class CurrencyField extends SvelteComponent<CurrencyFieldProps, CurrencyFieldEvents, CurrencyFieldSlots> {
|
|
28
|
+
}
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script context="module"></script>
|
|
2
|
+
|
|
3
|
+
<script>import { isString } from "lodash-es";
|
|
4
|
+
import FieldLabel from "../FieldLabel.svelte";
|
|
5
|
+
import FieldMessage from "../FieldMessage.svelte";
|
|
6
|
+
export let fieldStore;
|
|
7
|
+
let value;
|
|
8
|
+
$: {
|
|
9
|
+
const new_value = $fieldStore.value;
|
|
10
|
+
const is_string = isString(new_value);
|
|
11
|
+
value = is_string ? new_value : JSON.stringify(new_value, null, 2);
|
|
12
|
+
}
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<FieldLabel {fieldStore} />
|
|
16
|
+
<div class="relative mt-2 rounded-md bg-surface-100 p-2">
|
|
17
|
+
<pre class="rounded-md">{value ?? ""}</pre>
|
|
18
|
+
</div>
|
|
19
|
+
<FieldMessage {fieldStore} />
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
import type { Writable } from "svelte/store";
|
|
3
|
+
import type { IBaseField, IBuiltField } from "../interfaces";
|
|
4
|
+
export interface IDataIndicationField extends IBaseField<{}> {
|
|
5
|
+
fieldtype: "dataindication";
|
|
6
|
+
}
|
|
7
|
+
declare const __propDef: {
|
|
8
|
+
props: {
|
|
9
|
+
fieldStore: Writable<IBuiltField>;
|
|
10
|
+
};
|
|
11
|
+
events: {
|
|
12
|
+
[evt: string]: CustomEvent<any>;
|
|
13
|
+
};
|
|
14
|
+
slots: {};
|
|
15
|
+
exports?: {} | undefined;
|
|
16
|
+
bindings?: string | undefined;
|
|
17
|
+
};
|
|
18
|
+
export type DataIndicationFieldProps = typeof __propDef.props;
|
|
19
|
+
export type DataIndicationFieldEvents = typeof __propDef.events;
|
|
20
|
+
export type DataIndicationFieldSlots = typeof __propDef.slots;
|
|
21
|
+
export default class DataIndicationField extends SvelteComponent<DataIndicationFieldProps, DataIndicationFieldEvents, DataIndicationFieldSlots> {
|
|
22
|
+
}
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<script context="module"></script>
|
|
2
|
+
|
|
3
|
+
<script>import { Input } from "@stubber/ui/input";
|
|
4
|
+
import FieldLabel from "../FieldLabel.svelte";
|
|
5
|
+
import FieldMessage from "../FieldMessage.svelte";
|
|
6
|
+
export let fieldStore;
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<FieldLabel {fieldStore} />
|
|
10
|
+
<Input
|
|
11
|
+
id={$fieldStore.id}
|
|
12
|
+
bind:value={$fieldStore.value}
|
|
13
|
+
type="date"
|
|
14
|
+
aria-invalid={$fieldStore.validation_result?.type == "error" ? true : undefined}
|
|
15
|
+
class="w-full date-input {!$fieldStore.value ? 'text-muted-foreground' : ''}"
|
|
16
|
+
aria-describedby="message-{$fieldStore.id}"
|
|
17
|
+
/>
|
|
18
|
+
<FieldMessage {fieldStore} />
|
|
19
|
+
|
|
20
|
+
<style>
|
|
21
|
+
:global(input[type="date"].date-input) {
|
|
22
|
+
position: relative;
|
|
23
|
+
padding-right: 2rem;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
:global(input[type="date"].date-input::-webkit-calendar-picker-indicator) {
|
|
27
|
+
position: absolute;
|
|
28
|
+
right: 0.5rem;
|
|
29
|
+
cursor: pointer;
|
|
30
|
+
}
|
|
31
|
+
</style>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
import type { Writable } from "svelte/store";
|
|
3
|
+
import type { IBaseField, IBuiltField } from "../interfaces";
|
|
4
|
+
export interface IDateField extends IBaseField<{}> {
|
|
5
|
+
fieldtype: "date";
|
|
6
|
+
}
|
|
7
|
+
declare const __propDef: {
|
|
8
|
+
props: {
|
|
9
|
+
fieldStore: Writable<IBuiltField>;
|
|
10
|
+
};
|
|
11
|
+
events: {
|
|
12
|
+
[evt: string]: CustomEvent<any>;
|
|
13
|
+
};
|
|
14
|
+
slots: {};
|
|
15
|
+
exports?: {} | undefined;
|
|
16
|
+
bindings?: string | undefined;
|
|
17
|
+
};
|
|
18
|
+
export type DateFieldProps = typeof __propDef.props;
|
|
19
|
+
export type DateFieldEvents = typeof __propDef.events;
|
|
20
|
+
export type DateFieldSlots = typeof __propDef.slots;
|
|
21
|
+
export default class DateField extends SvelteComponent<DateFieldProps, DateFieldEvents, DateFieldSlots> {
|
|
22
|
+
}
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<script context="module"></script>
|
|
2
|
+
|
|
3
|
+
<script>import { Input } from "@stubber/ui/input";
|
|
4
|
+
import FieldLabel from "../FieldLabel.svelte";
|
|
5
|
+
import FieldMessage from "../FieldMessage.svelte";
|
|
6
|
+
export let fieldStore;
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<FieldLabel {fieldStore} />
|
|
10
|
+
<Input
|
|
11
|
+
id={$fieldStore.id}
|
|
12
|
+
bind:value={$fieldStore.value}
|
|
13
|
+
type="datetime-local"
|
|
14
|
+
aria-invalid={$fieldStore.validation_result?.type == "error" ? true : undefined}
|
|
15
|
+
class="w-full date-input {!$fieldStore.value ? 'text-muted-foreground' : ''}"
|
|
16
|
+
aria-describedby="message-{$fieldStore.id}"
|
|
17
|
+
/>
|
|
18
|
+
<FieldMessage {fieldStore} />
|
|
19
|
+
|
|
20
|
+
<style>
|
|
21
|
+
:global(input[type="datetime-local"].date-input) {
|
|
22
|
+
position: relative;
|
|
23
|
+
padding-right: 2rem;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
:global(input[type="datetime-local"].date-input::-webkit-calendar-picker-indicator) {
|
|
27
|
+
position: absolute;
|
|
28
|
+
right: 0.5rem;
|
|
29
|
+
cursor: pointer;
|
|
30
|
+
}
|
|
31
|
+
</style>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
import type { Writable } from "svelte/store";
|
|
3
|
+
import type { IBaseField, IBuiltField } from "../interfaces";
|
|
4
|
+
export interface IDateTimeField extends IBaseField<{}> {
|
|
5
|
+
fieldtype: "datetime";
|
|
6
|
+
}
|
|
7
|
+
declare const __propDef: {
|
|
8
|
+
props: {
|
|
9
|
+
fieldStore: Writable<IBuiltField>;
|
|
10
|
+
};
|
|
11
|
+
events: {
|
|
12
|
+
[evt: string]: CustomEvent<any>;
|
|
13
|
+
};
|
|
14
|
+
slots: {};
|
|
15
|
+
exports?: {} | undefined;
|
|
16
|
+
bindings?: string | undefined;
|
|
17
|
+
};
|
|
18
|
+
export type DateTimeFieldProps = typeof __propDef.props;
|
|
19
|
+
export type DateTimeFieldEvents = typeof __propDef.events;
|
|
20
|
+
export type DateTimeFieldSlots = typeof __propDef.slots;
|
|
21
|
+
export default class DateTimeField extends SvelteComponent<DateTimeFieldProps, DateTimeFieldEvents, DateTimeFieldSlots> {
|
|
22
|
+
}
|
|
23
|
+
export {};
|