@stubber/form-fields 1.2.3 → 1.3.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.
@@ -1,113 +1,77 @@
1
1
  <script>
2
- import { syncStoreToStore } from "../../utils/syncing";
3
- import { deepEqual } from "fast-equals";
4
- import _ from "lodash-es";
2
+ import { merge, startCase } from "lodash-es";
5
3
  import { onMount } from "svelte";
6
- import { writable } from "svelte/store";
7
4
 
8
5
  import { Checkbox } from "@stubber/ui/checkbox";
9
6
  import { Label } from "@stubber/ui/label";
10
7
 
11
8
  export let field;
12
9
 
13
- const internal = writable({
14
- checks: [],
15
- });
16
-
17
10
  $: state_key = $field.state?.state_key;
18
11
  $: label = $field.spec?.title;
19
12
  $: hide_label = $field.spec?.hide_label;
20
13
  $: isValid = !$field.state?.validation || $field.state?.validation?.valid;
21
14
  $: validationMessage = $field.state?.validation?.message;
22
- $: items = _.isArray($field.spec?.params?.options)
23
- ? $field.spec?.params?.options?.map((o, index) => {
24
- let { label, value } = o || {};
25
- let _value = value !== undefined ? value : label;
26
- let _label = label ?? value;
27
- let _key = `${state_key}${label}${index}`;
28
- return { _key, _label, _value };
29
- })
30
- : [];
15
+ $: options = $field.spec?.params?.options; // options is an object with a label property, value property (optional) and checked property
31
16
 
32
- onMount(() => {
33
- // set field values that aren't set yet
34
- let f = _.cloneDeep($field);
35
- let initial_value = f?.data?.base || [];
36
- let initial_data = {
37
- ...f?.data,
38
- base: initial_value,
39
- };
40
- let initial_state_internal = {
41
- ...f?.state?.internal,
42
- checks: items.map((i) =>
43
- Boolean(
44
- initial_value.find((iv) => deepEqual(iv.value, i._value) && deepEqual(iv.label, i._label))
45
- )
46
- ),
47
- };
48
- _.set(f, "state.internal", initial_state_internal);
49
- _.set(f, "data", initial_data);
50
- if (!deepEqual(f, $field)) $field = f;
17
+ // $: console.log("field", $field);
51
18
 
52
- syncStoreToStore(
53
- field,
54
- internal,
55
- (a, b) => {
56
- let _clone = _.cloneDeep(a.state?.internal) || {};
19
+ // $: console.log("options", options);
20
+ onMount(() => {
21
+ /// merge all options into data.base
22
+ field.update((f) => {
23
+ if (!f.data) {
24
+ f.data = {};
25
+ }
26
+ if (!f.data.base) {
27
+ f.data.base = {};
28
+ }
57
29
 
58
- // get parts from data
59
- _clone.checks = items.map((i) =>
60
- Boolean(
61
- a?.data?.base.find(
62
- (iv) => deepEqual(iv.value, i._value) && deepEqual(iv.label, i._label)
63
- )
64
- )
65
- );
30
+ const merged_base = merge({}, options, f.data.base);
31
+ // ensure all options have a checked property
66
32
 
67
- // set field state if changed
68
- if (!deepEqual(a?.state?.internal, _clone)) {
69
- $field.state.internal = _clone;
33
+ Object.entries(merged_base).forEach(([key, item]) => {
34
+ if (typeof item === "object" && item.checked === undefined) {
35
+ item.checked = false;
70
36
  }
37
+ });
71
38
 
72
- return _clone;
73
- },
74
- (a, b) => {
75
- let _clone = _.cloneDeep(a) || {};
76
- // update the state
77
- _.set(_clone, "state.internal", _.cloneDeep(b));
78
- // update the data
79
- let base = [];
80
- b.checks.forEach((c, index) => {
81
- if (c)
82
- base.push({
83
- value: items[index]._value,
84
- label: items[index]._label,
85
- });
86
- });
87
- _.set(_clone, "data.base", base);
88
- return _clone;
89
- }
90
- );
39
+ f.data.base = merged_base;
40
+ return f;
41
+ });
91
42
  });
43
+
44
+ //: boolean | "indeterminate" | undefined
45
+ const on_change = (new_value, key) => {
46
+ field.update((f) => {
47
+ if (!f.data.base[key]) {
48
+ f.data.base[key] = {};
49
+ }
50
+ f.data.base[key].checked = new_value;
51
+ return f;
52
+ });
53
+ };
92
54
  </script>
93
55
 
94
- {#if $internal}
95
- <div class="flex flex-col w-full {!isValid ? `text-danger-500` : `text-surface-900`}">
96
- {#each items as item, index}
97
- <div class="flex space-x-3 relative mt-2">
98
- <Checkbox
99
- id="input_{state_key}_{index}"
100
- name={state_key}
101
- bind:checked={$internal.checks[index]}
102
- />
56
+ <div class="flex flex-col w-full {!isValid ? `text-danger-500` : `text-surface-900`}">
57
+ <Label class="block pb-2 {hide_label ? 'hidden' : ''}">
58
+ {label}
59
+ </Label>
60
+ {#each Object.entries(options) as [key, item] (key)}
61
+ <div class="flex space-x-3 relative mt-2">
62
+ <Checkbox
63
+ id="input_{state_key}_{key}"
64
+ name={key}
65
+ checked={$field.data?.base?.[key]?.checked || false}
66
+ onCheckedChange={(new_value) => on_change(new_value, key)}
67
+ />
103
68
 
104
- <Label for="input_{state_key}" class=" {hide_label ? 'hidden' : ''}">
105
- {item._label}
106
- </Label>
107
- </div>
108
- {/each}
109
- {#if validationMessage}
110
- <Label class={!isValid ? `text-danger-500` : `text-success-500`}>{validationMessage}</Label>
111
- {/if}
112
- </div>
113
- {/if}
69
+ <Label for="input_{state_key}_${key}" class=" {hide_label ? 'hidden' : ''}">
70
+ {item.label || startCase(key)}
71
+ </Label>
72
+ </div>
73
+ {/each}
74
+ {#if validationMessage}
75
+ <Label class={!isValid ? `text-danger-500` : `text-success-500`}>{validationMessage}</Label>
76
+ {/if}
77
+ </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stubber/form-fields",
3
- "version": "1.2.3",
3
+ "version": "1.3.0",
4
4
  "description": "An automatic form builder based on field specifications",
5
5
  "keywords": [
6
6
  "components",