@stubber/form-fields 1.0.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.
Files changed (151) hide show
  1. package/README.md +303 -0
  2. package/dist/Field.svelte +36 -0
  3. package/dist/Field.svelte.d.ts +31 -0
  4. package/dist/Form.svelte +34 -0
  5. package/dist/Form.svelte.d.ts +29 -0
  6. package/dist/NullFieldWrapper.svelte +6 -0
  7. package/dist/NullFieldWrapper.svelte.d.ts +25 -0
  8. package/dist/fields/component_parts/arraybuilder/FieldWrapper.svelte +69 -0
  9. package/dist/fields/component_parts/arraybuilder/FieldWrapper.svelte.d.ts +29 -0
  10. package/dist/fields/component_parts/fieldbuilder/FieldWrapper.svelte +8 -0
  11. package/dist/fields/component_parts/fieldbuilder/FieldWrapper.svelte.d.ts +25 -0
  12. package/dist/fields/components/AgGrid.svelte +53 -0
  13. package/dist/fields/components/AgGrid.svelte.d.ts +18 -0
  14. package/dist/fields/components/Arraybuilder.svelte +101 -0
  15. package/dist/fields/components/Arraybuilder.svelte.d.ts +25 -0
  16. package/dist/fields/components/Checkbox.svelte +100 -0
  17. package/dist/fields/components/Checkbox.svelte.d.ts +23 -0
  18. package/dist/fields/components/CheckboxAutocomplete.svelte +92 -0
  19. package/dist/fields/components/CheckboxAutocomplete.svelte.d.ts +23 -0
  20. package/dist/fields/components/Contactselector.svelte +348 -0
  21. package/dist/fields/components/Contactselector.svelte.d.ts +25 -0
  22. package/dist/fields/components/Currency.svelte +258 -0
  23. package/dist/fields/components/Currency.svelte.d.ts +23 -0
  24. package/dist/fields/components/Dataindication.svelte +35 -0
  25. package/dist/fields/components/Dataindication.svelte.d.ts +23 -0
  26. package/dist/fields/components/Date.svelte +94 -0
  27. package/dist/fields/components/Date.svelte.d.ts +23 -0
  28. package/dist/fields/components/Datetime.svelte +94 -0
  29. package/dist/fields/components/Datetime.svelte.d.ts +23 -0
  30. package/dist/fields/components/Email.svelte +124 -0
  31. package/dist/fields/components/Email.svelte.d.ts +23 -0
  32. package/dist/fields/components/Fieldbuilder.svelte +340 -0
  33. package/dist/fields/components/Fieldbuilder.svelte.d.ts +25 -0
  34. package/dist/fields/components/Fieldsbuilder.svelte +122 -0
  35. package/dist/fields/components/Fieldsbuilder.svelte.d.ts +25 -0
  36. package/dist/fields/components/File.svelte +230 -0
  37. package/dist/fields/components/File.svelte.d.ts +25 -0
  38. package/dist/fields/components/Heading.svelte +17 -0
  39. package/dist/fields/components/Heading.svelte.d.ts +23 -0
  40. package/dist/fields/components/Hidden.svelte +7 -0
  41. package/dist/fields/components/Hidden.svelte.d.ts +23 -0
  42. package/dist/fields/components/Hiddenlocation.svelte +28 -0
  43. package/dist/fields/components/Hiddenlocation.svelte.d.ts +23 -0
  44. package/dist/fields/components/Html.svelte +13 -0
  45. package/dist/fields/components/Html.svelte.d.ts +23 -0
  46. package/dist/fields/components/Jsoneditor.svelte +94 -0
  47. package/dist/fields/components/Jsoneditor.svelte.d.ts +23 -0
  48. package/dist/fields/components/Map.svelte +192 -0
  49. package/dist/fields/components/Map.svelte.d.ts +25 -0
  50. package/dist/fields/components/Multicheckbox.svelte +119 -0
  51. package/dist/fields/components/Multicheckbox.svelte.d.ts +23 -0
  52. package/dist/fields/components/Multistep.svelte +86 -0
  53. package/dist/fields/components/Multistep.svelte.d.ts +25 -0
  54. package/dist/fields/components/Note.svelte +92 -0
  55. package/dist/fields/components/Note.svelte.d.ts +23 -0
  56. package/dist/fields/components/Number.svelte +118 -0
  57. package/dist/fields/components/Number.svelte.d.ts +23 -0
  58. package/dist/fields/components/Objectbuilder.svelte +152 -0
  59. package/dist/fields/components/Objectbuilder.svelte.d.ts +25 -0
  60. package/dist/fields/components/Qrcodescanner.svelte +198 -0
  61. package/dist/fields/components/Qrcodescanner.svelte.d.ts +23 -0
  62. package/dist/fields/components/Radio.svelte +116 -0
  63. package/dist/fields/components/Radio.svelte.d.ts +23 -0
  64. package/dist/fields/components/Renderfield.svelte +58 -0
  65. package/dist/fields/components/Renderfield.svelte.d.ts +25 -0
  66. package/dist/fields/components/Screenrecorder.svelte +277 -0
  67. package/dist/fields/components/Screenrecorder.svelte.d.ts +25 -0
  68. package/dist/fields/components/Screenshot.svelte +270 -0
  69. package/dist/fields/components/Screenshot.svelte.d.ts +25 -0
  70. package/dist/fields/components/Scrollandreaddisplay.svelte +122 -0
  71. package/dist/fields/components/Scrollandreaddisplay.svelte.d.ts +23 -0
  72. package/dist/fields/components/Section.svelte +64 -0
  73. package/dist/fields/components/Section.svelte.d.ts +25 -0
  74. package/dist/fields/components/Select.svelte +229 -0
  75. package/dist/fields/components/Select.svelte.d.ts +23 -0
  76. package/dist/fields/components/Selectresource.svelte +291 -0
  77. package/dist/fields/components/Selectresource.svelte.d.ts +25 -0
  78. package/dist/fields/components/Signature.svelte +153 -0
  79. package/dist/fields/components/Signature.svelte.d.ts +25 -0
  80. package/dist/fields/components/Slider.svelte +101 -0
  81. package/dist/fields/components/Slider.svelte.d.ts +23 -0
  82. package/dist/fields/components/SmartText.svelte +330 -0
  83. package/dist/fields/components/SmartText.svelte.d.ts +23 -0
  84. package/dist/fields/components/Telephone.svelte +153 -0
  85. package/dist/fields/components/Telephone.svelte.d.ts +23 -0
  86. package/dist/fields/components/Text.svelte +106 -0
  87. package/dist/fields/components/Text.svelte.d.ts +23 -0
  88. package/dist/fields/components/Voicenote.svelte +268 -0
  89. package/dist/fields/components/Voicenote.svelte.d.ts +25 -0
  90. package/dist/fields/components/index.d.ts +81 -0
  91. package/dist/fields/components/index.js +82 -0
  92. package/dist/fields/definitions/_all.json +38 -0
  93. package/dist/fields/definitions/_valid_fieldtype.json +220 -0
  94. package/dist/fields/definitions/arraybuilder.json +39 -0
  95. package/dist/fields/definitions/checkbox.json +44 -0
  96. package/dist/fields/definitions/contactselector.json +15 -0
  97. package/dist/fields/definitions/currency.json +42 -0
  98. package/dist/fields/definitions/dataindication.json +16 -0
  99. package/dist/fields/definitions/date.json +16 -0
  100. package/dist/fields/definitions/datetime.json +15 -0
  101. package/dist/fields/definitions/email.json +16 -0
  102. package/dist/fields/definitions/fieldbuilder.json +64 -0
  103. package/dist/fields/definitions/fieldsbuilder.json +38 -0
  104. package/dist/fields/definitions/file.json +42 -0
  105. package/dist/fields/definitions/grid.json +47 -0
  106. package/dist/fields/definitions/heading.json +38 -0
  107. package/dist/fields/definitions/hidden.json +89 -0
  108. package/dist/fields/definitions/hiddenlocation.json +15 -0
  109. package/dist/fields/definitions/html.json +34 -0
  110. package/dist/fields/definitions/index.d.ts +86 -0
  111. package/dist/fields/definitions/index.js +96 -0
  112. package/dist/fields/definitions/jsoneditor.json +33 -0
  113. package/dist/fields/definitions/map.json +36 -0
  114. package/dist/fields/definitions/multicheckbox.json +47 -0
  115. package/dist/fields/definitions/multistep.json +35 -0
  116. package/dist/fields/definitions/note.json +16 -0
  117. package/dist/fields/definitions/number.json +42 -0
  118. package/dist/fields/definitions/objectbuilder.json +39 -0
  119. package/dist/fields/definitions/qrcodescanner.json +16 -0
  120. package/dist/fields/definitions/radio.json +47 -0
  121. package/dist/fields/definitions/renderfield.json +36 -0
  122. package/dist/fields/definitions/richtext.json +16 -0
  123. package/dist/fields/definitions/screenrecorder.json +42 -0
  124. package/dist/fields/definitions/screenshot.json +42 -0
  125. package/dist/fields/definitions/scrollandreaddisplay.json +49 -0
  126. package/dist/fields/definitions/section.json +50 -0
  127. package/dist/fields/definitions/select.json +47 -0
  128. package/dist/fields/definitions/selectresource.json +48 -0
  129. package/dist/fields/definitions/signature.json +16 -0
  130. package/dist/fields/definitions/slider.json +78 -0
  131. package/dist/fields/definitions/smart_text.json +101 -0
  132. package/dist/fields/definitions/telephone.json +16 -0
  133. package/dist/fields/definitions/text.json +35 -0
  134. package/dist/fields/definitions/voicenote.json +43 -0
  135. package/dist/index.d.ts +2 -0
  136. package/dist/index.js +3 -0
  137. package/dist/thirdparty/mapbox/GeoCoder.svelte +10 -0
  138. package/dist/thirdparty/mapbox/GeoCoder.svelte.d.ts +25 -0
  139. package/dist/thirdparty/mapbox/Map.svelte +30 -0
  140. package/dist/thirdparty/mapbox/Map.svelte.d.ts +20 -0
  141. package/dist/thirdparty/mapbox/MapMarker.svelte +13 -0
  142. package/dist/thirdparty/mapbox/MapMarker.svelte.d.ts +31 -0
  143. package/dist/utils/createField.d.ts +6 -0
  144. package/dist/utils/createField.js +33 -0
  145. package/dist/utils/createForm.d.ts +1 -0
  146. package/dist/utils/createForm.js +501 -0
  147. package/dist/utils/index.d.ts +18 -0
  148. package/dist/utils/index.js +126 -0
  149. package/dist/utils/syncing.d.ts +11 -0
  150. package/dist/utils/syncing.js +134 -0
  151. package/package.json +78 -0
@@ -0,0 +1,118 @@
1
+ <script>
2
+ import { syncStoreToStore } from "../../utils/syncing";
3
+ import { deepEqual } from "fast-equals";
4
+ import _ from "lodash-es";
5
+ import { onMount } from "svelte";
6
+ import { writable } from "svelte/store";
7
+
8
+ export let field;
9
+
10
+ const internal = writable();
11
+
12
+ $: state_key = $field.state?.state_key;
13
+ $: label = $field.spec?.title;
14
+ $: hide_label = $field.spec?.hide_label;
15
+ $: isValid = !$field.state?.validation || $field.state?.validation?.valid;
16
+ $: validationMessage = $field.state?.validation?.message;
17
+ $: min_setting = $field.spec.params.min ?? false;
18
+ $: max_setting = $field.spec.params.max ?? false;
19
+ $: step_setting = $field.spec.params.step ?? 1;
20
+ $: has_step = $field.spec.params.step ?? false;
21
+
22
+ onMount(() => {
23
+ // set field values that aren't set yet
24
+ let f = _.cloneDeep($field);
25
+ let initial_value = f?.data?.base ?? "";
26
+ let initial_data = {
27
+ ...f?.data,
28
+ base: initial_value,
29
+ };
30
+ let initial_state_internal = {
31
+ ...f?.state?.internal,
32
+ raw: initial_value,
33
+ };
34
+ _.set(f, "data", initial_data);
35
+ _.set(f, "state.internal", initial_state_internal);
36
+ if (!deepEqual(f, $field)) $field = f;
37
+
38
+ syncStoreToStore(
39
+ field,
40
+ internal,
41
+ (a, b) => {
42
+ let _clone = _.cloneDeep(a.state?.internal) || {};
43
+
44
+ // get parts from data
45
+ _clone.raw = a?.data?.base;
46
+
47
+ // set field state if changed
48
+ if (!deepEqual(a?.state?.internal, _clone)) {
49
+ $field.state.internal = _clone;
50
+ }
51
+
52
+ return _clone;
53
+ },
54
+ (a, b) => {
55
+ let _clone = _.cloneDeep(a) || {};
56
+
57
+ let raw = b.raw;
58
+
59
+ // check if raw is valid
60
+ if (max_setting != false && raw > max_setting) {
61
+ raw = max_setting;
62
+ }
63
+ if (min_setting != false && raw < min_setting) {
64
+ raw = min_setting;
65
+ }
66
+ if (has_step) {
67
+ raw = Math.round(raw / step_setting) * step_setting;
68
+ }
69
+
70
+ // if raw is different to b.raw, update internal
71
+ if (raw !== b.raw) $internal.raw = raw;
72
+
73
+ b.raw = raw;
74
+
75
+ // update the state
76
+ _.set(_clone, "state.internal", _.cloneDeep(b));
77
+ // update the data
78
+ _.set(_clone, "data.base", raw);
79
+ return _clone;
80
+ },
81
+ null,
82
+ 300
83
+ );
84
+ });
85
+ </script>
86
+
87
+ {#if $internal}
88
+ <div class="flex flex-col w-full text-surface-900">
89
+ <label for="input_{state_key}" class="block text-label {hide_label ? 'hidden' : ''}">
90
+ {label}
91
+ </label>
92
+ <div class="relative rounded-md">
93
+ <input
94
+ on:keydown={(e) => {
95
+ if (e.key === "Enter") {
96
+ e.preventDefault();
97
+ }
98
+ }}
99
+ type="number"
100
+ id="input_{state_key}"
101
+ placeholder={label}
102
+ class="block w-full text-field rounded-md border-0 py-2 pl-3 text-surface-900 ring-1 ring-inset {!isValid
103
+ ? 'ring-danger-500'
104
+ : 'ring-surface-300 focus:ring-primary-400'} focus:outline-none placeholder:text-surface-400 focus:ring-2 focus:ring-inset"
105
+ name={state_key}
106
+ min={min_setting}
107
+ max={max_setting}
108
+ step={step_setting}
109
+ bind:value={$internal.raw}
110
+ />
111
+ </div>
112
+ {#if validationMessage}
113
+ <p class="text-label {!isValid ? `text-danger-500` : `text-success-500`}">
114
+ {validationMessage}
115
+ </p>
116
+ {/if}
117
+ </div>
118
+ {/if}
@@ -0,0 +1,23 @@
1
+ /** @typedef {typeof __propDef.props} NumberProps */
2
+ /** @typedef {typeof __propDef.events} NumberEvents */
3
+ /** @typedef {typeof __propDef.slots} NumberSlots */
4
+ export default class Number extends SvelteComponentTyped<{
5
+ field: any;
6
+ }, {
7
+ [evt: string]: CustomEvent<any>;
8
+ }, {}> {
9
+ }
10
+ export type NumberProps = typeof __propDef.props;
11
+ export type NumberEvents = typeof __propDef.events;
12
+ export type NumberSlots = typeof __propDef.slots;
13
+ import { SvelteComponentTyped } from "svelte";
14
+ declare const __propDef: {
15
+ props: {
16
+ field: any;
17
+ };
18
+ events: {
19
+ [evt: string]: CustomEvent<any>;
20
+ };
21
+ slots: {};
22
+ };
23
+ export {};
@@ -0,0 +1,152 @@
1
+ <script>
2
+ import { Form } from "../..";
3
+ import _ from "lodash-es";
4
+ import { syncStoreToStore } from "../../utils/syncing";
5
+ import { writable } from "svelte/store";
6
+ import { onMount } from "svelte";
7
+ import { deepEqual } from "fast-equals";
8
+
9
+ export let form;
10
+ export let field;
11
+
12
+ let dependencies = form.dependencies;
13
+
14
+ $: state_key = $field.state?.state_key;
15
+ $: label = $field.spec?.title;
16
+ $: hide_label = $field.spec?.hide_label;
17
+ $: with_order = $field.spec?.params?.with_order;
18
+ $: key_field_spec = $field.spec?.params?.key_field_spec || {};
19
+ $: value_field_spec = $field.spec?.params?.value_field_spec || {};
20
+ $: isValid = !$field.state?.validation || $field.state?.validation?.valid;
21
+ $: validationMessage = $field.state?.validation?.message;
22
+
23
+ let initial_form;
24
+ let settings_form = writable();
25
+ onMount(() => {
26
+ // set field values that aren't set yet
27
+ let f = _.cloneDeep($field);
28
+ let initial_value = f?.data?.base ?? {};
29
+ let initial_data = _.merge(
30
+ {
31
+ base: initial_value,
32
+ },
33
+ f?.data
34
+ );
35
+ _.set(f, "data", initial_data);
36
+ if (!deepEqual(f, $field)) $field = f;
37
+
38
+ initial_form = {
39
+ spec: {
40
+ fields: {
41
+ entries: {
42
+ fieldtype: "arraybuilder",
43
+ hide_label: true,
44
+ params: {
45
+ new_entry_field: {
46
+ fieldtype: "section",
47
+ fields: {
48
+ key: _.merge({}, { title: "Key" }, key_field_spec),
49
+ value: _.merge({}, { title: "Value" }, value_field_spec),
50
+ },
51
+ },
52
+ },
53
+ },
54
+ },
55
+ },
56
+ data: {
57
+ entries: _.cloneDeep(
58
+ Object.entries(initial_value ?? {})
59
+ .sort((a, b) => {
60
+ let a_order = a[1]?.__order ?? 0;
61
+ let b_order = b[1]?.__order ?? 0;
62
+ return a_order - b_order;
63
+ })
64
+ .map((e) => {
65
+ return {
66
+ value: e[1],
67
+ key: e[0],
68
+ };
69
+ })
70
+ ),
71
+ },
72
+ };
73
+
74
+ syncStoreToStore(
75
+ field,
76
+ settings_form,
77
+ (a, b) => {
78
+ let _clone = _.cloneDeep(b) || {};
79
+
80
+ let internal_entries = _.cloneDeep(a?.state?.internal || []);
81
+ let entries = Object.entries(a?.data?.base || {})
82
+ .sort((a, b) => {
83
+ let a_order = a[1]?.__order ?? 0;
84
+ let b_order = b[1]?.__order ?? 0;
85
+ return a_order - b_order;
86
+ })
87
+ .map((e, index) => {
88
+ let internal_state = internal_entries[index] || {};
89
+ return {
90
+ ...internal_state,
91
+ value: e[1],
92
+ key: e[0],
93
+ };
94
+ });
95
+
96
+ _.set(_clone, "data.entries", entries);
97
+
98
+ if (!deepEqual(entries, a?.state?.internal)) {
99
+ $field.state.internal = _.cloneDeep(entries);
100
+ }
101
+
102
+ return _clone;
103
+ },
104
+ (a, b) => {
105
+ let _clone = _.cloneDeep(a) || {};
106
+
107
+ let uentries = _.cloneDeep(b.data.entries || []);
108
+ let entries = [];
109
+ uentries.forEach((curr, index) => {
110
+ let key = curr.key ?? "";
111
+ if (_.isObject(key)) key = JSON.stringify(key);
112
+ key = key.toString().trim();
113
+ let value = curr.value ?? null;
114
+ if (_.isObject(value) && with_order) {
115
+ value.__order = index;
116
+ }
117
+ let key_exists = entries.find((e) => e.key === key);
118
+ if (key_exists) key = key + " (copy)";
119
+ entries.push({ ...curr, key, value });
120
+ });
121
+
122
+ if (!deepEqual(entries, b.data.entries)) {
123
+ $settings_form.data.entries = _.cloneDeep(entries);
124
+ }
125
+
126
+ let base = entries.reduce((acc, curr) => {
127
+ acc[curr.key] = curr.value;
128
+ return acc;
129
+ }, {});
130
+
131
+ _.set(_clone, "data.base", _.cloneDeep(base));
132
+ _.set(_clone, "state.internal", _.cloneDeep(entries));
133
+
134
+ return _clone;
135
+ }
136
+ );
137
+ });
138
+ </script>
139
+
140
+ <div class="flex flex-col w-full text-surface-900">
141
+ <label for="input_{state_key}" class="block text-label {hide_label ? 'hidden' : ''}">
142
+ {label}
143
+ </label>
144
+ {#if initial_form}
145
+ <Form bind:form={settings_form} {initial_form} {dependencies} />
146
+ {/if}
147
+ {#if validationMessage}
148
+ <p class="text-label {!isValid ? `text-danger-500` : `text-success-500`}">
149
+ {validationMessage}
150
+ </p>
151
+ {/if}
152
+ </div>
@@ -0,0 +1,25 @@
1
+ /** @typedef {typeof __propDef.props} ObjectbuilderProps */
2
+ /** @typedef {typeof __propDef.events} ObjectbuilderEvents */
3
+ /** @typedef {typeof __propDef.slots} ObjectbuilderSlots */
4
+ export default class Objectbuilder extends SvelteComponentTyped<{
5
+ form: any;
6
+ field: any;
7
+ }, {
8
+ [evt: string]: CustomEvent<any>;
9
+ }, {}> {
10
+ }
11
+ export type ObjectbuilderProps = typeof __propDef.props;
12
+ export type ObjectbuilderEvents = typeof __propDef.events;
13
+ export type ObjectbuilderSlots = typeof __propDef.slots;
14
+ import { SvelteComponentTyped } from "svelte";
15
+ declare const __propDef: {
16
+ props: {
17
+ form: any;
18
+ field: any;
19
+ };
20
+ events: {
21
+ [evt: string]: CustomEvent<any>;
22
+ };
23
+ slots: {};
24
+ };
25
+ export {};
@@ -0,0 +1,198 @@
1
+ <script>
2
+ import { syncStoreToStore } from "../../utils/syncing";
3
+ import { deepEqual } from "fast-equals";
4
+ import _ from "lodash-es";
5
+ import { onMount } from "svelte";
6
+ import { writable } from "svelte/store";
7
+ import { fade } from "svelte/transition";
8
+ import { Html5Qrcode } from "html5-qrcode";
9
+ import { Button } from "@stubber/ui";
10
+
11
+ export let field;
12
+
13
+ const internal = writable();
14
+ let html5Qrcode;
15
+ let isScannerModalOpen = false;
16
+ let isCameraAvailable = false;
17
+ let scansuccess = false;
18
+ let scannedResult = "";
19
+
20
+ async function openScannerModal() {
21
+ if (isScannerModalOpen == false) {
22
+ isScannerModalOpen = true;
23
+ scannedResult = "";
24
+ scansuccess = false;
25
+ let cameras = await Html5Qrcode.getCameras();
26
+ if (!cameras) {
27
+ isCameraAvailable = false;
28
+ return;
29
+ }
30
+ isCameraAvailable = true;
31
+ let cameraId = cameras[0].id;
32
+ html5Qrcode = new Html5Qrcode("reader");
33
+ html5Qrcode.start(cameraId, { fps: 2 }, onScanSuccess, onScanFailure);
34
+ }
35
+ }
36
+
37
+ function closeScannerModal() {
38
+ isScannerModalOpen = false;
39
+ html5Qrcode.stop();
40
+ }
41
+
42
+ function onScanSuccess(decodedText, decodedResult) {
43
+ scannedResult = decodedText;
44
+ scansuccess = true;
45
+ }
46
+
47
+ function onScanFailure(error) {
48
+ // handle scan failure, usually better to ignore and keep scanning.
49
+ }
50
+
51
+ $: state_key = $field.state?.state_key;
52
+ $: label = $field.spec?.title;
53
+ $: hide_label = $field.spec?.hide_label;
54
+ $: isValid = !$field.state?.validation || $field.state?.validation?.valid;
55
+ $: validationMessage = $field.state?.validation?.message;
56
+
57
+ function confirmScan() {
58
+ closeScannerModal();
59
+ $internal.raw = scannedResult;
60
+ }
61
+
62
+ onMount(() => {
63
+ // set field values that aren't set yet
64
+ let f = _.cloneDeep($field);
65
+ let initial_value = f?.data?.base ?? "";
66
+ let initial_data = {
67
+ ...f?.data,
68
+ base: initial_value,
69
+ };
70
+ let initial_state_internal = {
71
+ ...f?.state?.internal,
72
+ raw: initial_value,
73
+ };
74
+ _.set(f, "data", initial_data);
75
+ _.set(f, "state.internal", initial_state_internal);
76
+ if (!deepEqual(f, $field)) $field = f;
77
+
78
+ syncStoreToStore(
79
+ field,
80
+ internal,
81
+ (a, b) => {
82
+ let _clone = _.cloneDeep(a.state?.internal) || {};
83
+
84
+ // get parts from data
85
+ _clone.raw = a?.data?.base;
86
+
87
+ // set field state if changed
88
+ if (!deepEqual(a?.state?.internal, _clone)) {
89
+ $field.state.internal = _clone;
90
+ }
91
+
92
+ return _clone;
93
+ },
94
+ (a, b) => {
95
+ let _clone = _.cloneDeep(a) || {};
96
+ // update the state
97
+ _.set(_clone, "state.internal", _.cloneDeep(b));
98
+ // update the data
99
+ _.set(_clone, "data.base", b?.raw);
100
+ return _clone;
101
+ }
102
+ );
103
+ });
104
+ </script>
105
+
106
+ {#if $internal}
107
+ {#if isScannerModalOpen}
108
+ <div class="fixed inset-0 w-screen h-screen bg-black/50 z-30">
109
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
110
+ <!-- svelte-ignore a11y-no-static-element-interactions -->
111
+ <div
112
+ in:fade|global
113
+ out:fade|global={{ duration: 100 }}
114
+ on:click|self={() => {
115
+ closeScannerModal();
116
+ }}
117
+ class="fixed inset-0 flex justify-center items-center z-30 my-6"
118
+ >
119
+ <div
120
+ class="max-w-full max-h-full overflow-auto bg-surface-0 p-6 pt-4 rounded-2xl border shadow-2xl"
121
+ >
122
+ <button
123
+ type="button"
124
+ class="block ml-auto text-surface-700 font-bold text-lg"
125
+ on:click={closeScannerModal}
126
+ >
127
+ <i class="fa-regular fa-xmark" />
128
+ </button>
129
+ <div class="px-2 space-y-3">
130
+ <h4
131
+ class="text-start text-surface-900 text-heading-6 font-medium border-b border-surface-200"
132
+ >
133
+ Scan code
134
+ </h4>
135
+ <div id="reader" class="w-[250px] sm:w-[310px] flex flex-col items-center" />
136
+ {#if isCameraAvailable}
137
+ {#if scansuccess}
138
+ <div class="flex items-center space-x-2">
139
+ <i class="fas fa-circle text-success-400 fa-2xs" />
140
+ <p class="text-label text-surface-800">{scannedResult}</p>
141
+ </div>
142
+ {:else}
143
+ <div class="flex items-center space-x-2">
144
+ <i class="fas fa-circle text-surface-200 fa-2xs" />
145
+ <p class="text-label text-surface-800">Searching for code ...</p>
146
+ </div>
147
+ {/if}
148
+ <div class="flex">
149
+ <div class="flex ml-auto">
150
+ <Button
151
+ disabled={!scansuccess}
152
+ on:click={confirmScan}>
153
+ Confirm
154
+ </Button>
155
+ </div>
156
+ </div>
157
+ {:else}
158
+ <div class="w-[250px] sm:w-[310px] aspect-square flex items-center justify-center">
159
+ <p class="text-surface-800 text-label">No camera found</p>
160
+ </div>
161
+ {/if}
162
+ </div>
163
+ </div>
164
+ </div>
165
+ </div>
166
+ {/if}
167
+
168
+ <div class="flex flex-col w-full text-surface-900">
169
+ <label for="input_{state_key}" class="block text-label {hide_label ? 'hidden' : ''}">
170
+ {label}
171
+ </label>
172
+ <div class="relative mt-2 rounded-md">
173
+ <div class="flex items-center space-x-3">
174
+ {#if $internal.raw}
175
+ <input
176
+ readonly
177
+ type="text"
178
+ id="input_{state_key}"
179
+ placeholder={label}
180
+ class="block w-full text-field rounded-md border-0 py-2 pl-3 text-surface-900 ring-1 ring-inset {!isValid
181
+ ? 'ring-danger-500'
182
+ : 'ring-surface-300 focus:ring-primary-400'} focus:outline-none placeholder:text-surface-400 focus:ring-2 focus:ring-inset"
183
+ name={state_key}
184
+ value={$internal.raw}
185
+ />
186
+ {/if}
187
+ <div class="shrink-0">
188
+ <Button icon="camera" label="Scan code" on:click={openScannerModal} />
189
+ </div>
190
+ </div>
191
+ </div>
192
+ {#if validationMessage}
193
+ <p class="text-label {!isValid ? `text-danger-500` : `text-success-500`}">
194
+ {validationMessage}
195
+ </p>
196
+ {/if}
197
+ </div>
198
+ {/if}
@@ -0,0 +1,23 @@
1
+ /** @typedef {typeof __propDef.props} QrcodescannerProps */
2
+ /** @typedef {typeof __propDef.events} QrcodescannerEvents */
3
+ /** @typedef {typeof __propDef.slots} QrcodescannerSlots */
4
+ export default class Qrcodescanner extends SvelteComponentTyped<{
5
+ field: any;
6
+ }, {
7
+ [evt: string]: CustomEvent<any>;
8
+ }, {}> {
9
+ }
10
+ export type QrcodescannerProps = typeof __propDef.props;
11
+ export type QrcodescannerEvents = typeof __propDef.events;
12
+ export type QrcodescannerSlots = typeof __propDef.slots;
13
+ import { SvelteComponentTyped } from "svelte";
14
+ declare const __propDef: {
15
+ props: {
16
+ field: any;
17
+ };
18
+ events: {
19
+ [evt: string]: CustomEvent<any>;
20
+ };
21
+ slots: {};
22
+ };
23
+ export {};
@@ -0,0 +1,116 @@
1
+ <script>
2
+ import { syncStoreToStore } from "../../utils/syncing";
3
+ import { deepEqual } from "fast-equals";
4
+ import _ from "lodash-es";
5
+ import { onMount } from "svelte";
6
+ import { writable } from "svelte/store";
7
+
8
+ export let field;
9
+
10
+ const internal = writable();
11
+
12
+ $: state_key = $field.state?.state_key;
13
+ $: label = $field.spec?.title;
14
+ $: hide_label = $field.spec?.hide_label;
15
+ $: isValid = !$field.state?.validation || $field.state?.validation?.valid;
16
+ $: validationMessage = $field.state?.validation?.message;
17
+ $: items = _.isArray($field.spec?.params?.options)
18
+ ? $field.spec?.params?.options?.map((o, index) => {
19
+ let { label, value } = o || {};
20
+ let _value = value !== undefined ? value : label;
21
+ let _label = label ?? value;
22
+ let _key = `${state_key}${label}${index}`;
23
+ return { _key, _label, _value };
24
+ })
25
+ : [];
26
+
27
+ onMount(() => {
28
+ // set field values that aren't set yet
29
+ let f = _.cloneDeep($field);
30
+ let initial_item = items?.find((i) => deepEqual($field.data.base, i._value));
31
+ if (!initial_item) initial_item = items[0];
32
+ let initial_data = {
33
+ ...f?.data,
34
+ base: initial_item?._value,
35
+ };
36
+ if (!f?.spec?.without_value_details) initial_data.base_label = initial_item?._label;
37
+ let initial_state_internal = {
38
+ ...f?.state?.internal,
39
+ selected_item_key: initial_item?._key,
40
+ };
41
+ _.set(f, "data", initial_data);
42
+ _.set(f, "state.internal", initial_state_internal);
43
+ if (!deepEqual(f, $field)) $field = f;
44
+
45
+ syncStoreToStore(
46
+ field,
47
+ internal,
48
+ (a, b) => {
49
+ let _clone = _.cloneDeep(a.state?.internal) || {};
50
+
51
+ // get parts from data
52
+ let item = items.find((i) => i._value === a?.data?.base);
53
+ if (!item) item = items[0];
54
+ if (item) {
55
+ _clone.selected_item_key = item?._key;
56
+
57
+ // set field_label if changed
58
+ if (!deepEqual(a?.data?.base_label, item?._label) && !a?.spec?.without_value_details) {
59
+ $field.data.base_label = item?._label;
60
+ }
61
+
62
+ // set field state if changed
63
+ if (!deepEqual(a?.state?.internal, _clone)) {
64
+ $field.state.internal = _clone;
65
+ }
66
+ }
67
+
68
+ return _clone;
69
+ },
70
+ (a, b) => {
71
+ let _clone = _.cloneDeep(a) || {};
72
+ // update the state
73
+ _.set(_clone, "state.internal", _.cloneDeep(b));
74
+ // update the data
75
+ let item = items.find((i) => i._key === b?.selected_item_key);
76
+ _.set(_clone, "data.base", item?._value);
77
+ if (!a?.spec?.without_value_details) _.set(_clone, "data.base_label", item?._label);
78
+ return _clone;
79
+ }
80
+ );
81
+ });
82
+ </script>
83
+
84
+ {#if $internal}
85
+ <div class="flex flex-col w-full text-surface-900">
86
+ <label for="input_{state_key}" class="block text-label {hide_label ? 'hidden' : ''}">
87
+ {label}
88
+ </label>
89
+ {#if items?.length}
90
+ <fieldset
91
+ class="flex flex-col border {!isValid
92
+ ? 'border-warning-500'
93
+ : 'border-surface-300'} rounded-md px-2 py-1"
94
+ id="input_{state_key}"
95
+ >
96
+ {#each items as item}
97
+ <div class="py-1">
98
+ <input
99
+ id="input_{item._key}"
100
+ name={state_key}
101
+ bind:group={$internal.selected_item_key}
102
+ type="radio"
103
+ value={item._key}
104
+ />
105
+ <label for="input_{item._key}" class="text-field">{item._label}</label>
106
+ </div>
107
+ {/each}
108
+ </fieldset>
109
+ {/if}
110
+ {#if validationMessage}
111
+ <p class="text-label {!isValid ? `text-danger-500` : `text-success-500`}">
112
+ {validationMessage}
113
+ </p>
114
+ {/if}
115
+ </div>
116
+ {/if}
@@ -0,0 +1,23 @@
1
+ /** @typedef {typeof __propDef.props} RadioProps */
2
+ /** @typedef {typeof __propDef.events} RadioEvents */
3
+ /** @typedef {typeof __propDef.slots} RadioSlots */
4
+ export default class Radio extends SvelteComponentTyped<{
5
+ field: any;
6
+ }, {
7
+ [evt: string]: CustomEvent<any>;
8
+ }, {}> {
9
+ }
10
+ export type RadioProps = typeof __propDef.props;
11
+ export type RadioEvents = typeof __propDef.events;
12
+ export type RadioSlots = typeof __propDef.slots;
13
+ import { SvelteComponentTyped } from "svelte";
14
+ declare const __propDef: {
15
+ props: {
16
+ field: any;
17
+ };
18
+ events: {
19
+ [evt: string]: CustomEvent<any>;
20
+ };
21
+ slots: {};
22
+ };
23
+ export {};