@rettangoli/ui 0.1.2-rc2 → 0.1.2-rc21

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 (45) hide show
  1. package/dist/rettangoli-iife-layout.min.js +102 -32
  2. package/dist/rettangoli-iife-ui.min.js +182 -69
  3. package/package.json +5 -3
  4. package/src/cli/buildSvg.js +86 -0
  5. package/src/cli/index.js +1 -0
  6. package/src/components/breadcrumb/breadcrumb.handlers.js +9 -0
  7. package/src/components/breadcrumb/breadcrumb.store.js +29 -0
  8. package/src/components/breadcrumb/breadcrumb.view.yaml +64 -0
  9. package/src/components/dropdownMenu/dropdownMenu.handlers.js +4 -4
  10. package/src/components/dropdownMenu/dropdownMenu.store.js +5 -17
  11. package/src/components/dropdownMenu/dropdownMenu.view.yaml +15 -13
  12. package/src/components/form/form.handlers.js +133 -24
  13. package/src/components/form/form.store.js +125 -23
  14. package/src/components/form/form.view.yaml +139 -29
  15. package/src/components/pageOutline/pageOutline.handlers.js +1 -1
  16. package/src/components/popoverInput/popoverInput.handlers.js +99 -0
  17. package/src/components/popoverInput/popoverInput.store.js +48 -0
  18. package/src/components/popoverInput/popoverInput.view.yaml +55 -0
  19. package/src/components/select/select.handlers.js +2 -5
  20. package/src/components/select/select.view.yaml +3 -3
  21. package/src/components/sidebar/sidebar.view.yaml +1 -1
  22. package/src/components/sliderInput/sliderInput.handlers.js +24 -0
  23. package/src/components/sliderInput/sliderInput.store.js +17 -0
  24. package/src/components/sliderInput/sliderInput.view.yaml +42 -0
  25. package/src/components/table/table.handlers.js +1 -1
  26. package/src/components/tabs/tabs.handlers.js +10 -0
  27. package/src/components/tabs/tabs.store.js +29 -0
  28. package/src/components/tabs/tabs.view.yaml +64 -0
  29. package/src/components/waveform/waveform.handlers.js +92 -0
  30. package/src/components/waveform/waveform.store.js +17 -0
  31. package/src/components/waveform/waveform.view.yaml +38 -0
  32. package/src/entry-iife-layout.js +3 -0
  33. package/src/entry-iife-ui.js +4 -0
  34. package/src/index.js +5 -1
  35. package/src/primitives/dialog.js +208 -0
  36. package/src/primitives/input.js +32 -11
  37. package/src/primitives/popover.js +275 -0
  38. package/src/primitives/slider.js +8 -9
  39. package/src/styles/viewStyles.js +1 -0
  40. package/src/components/dialog/dialog.handlers.js +0 -5
  41. package/src/components/dialog/dialog.store.js +0 -25
  42. package/src/components/dialog/dialog.view.yaml +0 -44
  43. package/src/components/popover/popover.handlers.js +0 -5
  44. package/src/components/popover/popover.store.js +0 -12
  45. package/src/components/popover/popover.view.yaml +0 -57
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rettangoli/ui",
3
- "version": "0.1.2-rc2",
3
+ "version": "0.1.2-rc21",
4
4
  "description": "A UI component library for building web interfaces.",
5
5
  "main": "dist/rettangoli-esm.min.js",
6
6
  "type": "module",
@@ -9,7 +9,8 @@
9
9
  "src"
10
10
  ],
11
11
  "exports": {
12
- ".": "./src/index.js"
12
+ ".": "./src/index.js",
13
+ "./cli": "./src/cli/index.js"
13
14
  },
14
15
  "module": "./src/index.js",
15
16
  "repository": {
@@ -48,10 +49,11 @@
48
49
  "homepage": "https://github.com/yuusoft-org/rettangoli#readme",
49
50
  "dependencies": {
50
51
  "@floating-ui/dom": "^1.6.13",
52
+ "@rettangoli/fe": "0.0.7-rc11",
51
53
  "commander": "^13.1.0",
54
+ "jempl": "^0.1.2",
52
55
  "js-yaml": "^4.1.0",
53
56
  "liquidjs": "^10.21.0",
54
- "@rettangoli/fe": "0.0.7-rc4",
55
57
  "snabbdom": "^3.6.2"
56
58
  }
57
59
  }
@@ -0,0 +1,86 @@
1
+ import { readFileSync, writeFileSync, readdirSync, statSync } from 'node:fs';
2
+ import { join, basename } from 'node:path';
3
+
4
+ function getAllSvgFiles(dir) {
5
+ const svgFiles = [];
6
+
7
+ function traverse(currentDir) {
8
+ const files = readdirSync(currentDir);
9
+
10
+ for (const file of files) {
11
+ const fullPath = join(currentDir, file);
12
+ const stats = statSync(fullPath);
13
+
14
+ if (stats.isDirectory()) {
15
+ traverse(fullPath);
16
+ } else if (file.endsWith('.svg')) {
17
+ svgFiles.push(fullPath);
18
+ }
19
+ }
20
+ }
21
+
22
+ traverse(dir);
23
+ return svgFiles;
24
+ }
25
+
26
+ function removeFrontmatter(content) {
27
+ // Look for a line containing only '---'
28
+ const lines = content.split('\n');
29
+
30
+ for (let i = 0; i < lines.length; i++) {
31
+ if (lines[i].trim() === '---') {
32
+ // Found the separator, return everything after it
33
+ return lines.slice(i + 1).join('\n').trim();
34
+ }
35
+ }
36
+
37
+ // No frontmatter separator found, return original content
38
+ return content;
39
+ }
40
+
41
+ const buildSvgIcons = (options) => {
42
+ const { dir, outfile } = options;
43
+
44
+ if (!dir || !outfile) {
45
+ console.error('Error: Both dir and outfile options are required');
46
+ return;
47
+ }
48
+
49
+ console.log(`Scanning for SVG files in: ${dir}`);
50
+
51
+ const svgFiles = getAllSvgFiles(dir);
52
+
53
+ if (svgFiles.length === 0) {
54
+ console.log('No SVG files found');
55
+ return;
56
+ }
57
+
58
+ console.log(`Found ${svgFiles.length} SVG files`);
59
+
60
+ const icons = {};
61
+
62
+ for (const filePath of svgFiles) {
63
+ const fileName = basename(filePath, '.svg');
64
+ let content = readFileSync(filePath, 'utf8');
65
+
66
+ content = removeFrontmatter(content);
67
+
68
+ content = content.replace(/\n/g, ' ').replace(/\s+/g, ' ').trim();
69
+
70
+ icons[fileName] = content;
71
+ }
72
+
73
+ // Convert to custom format with single quotes for keys and backticks for values
74
+ const iconEntries = Object.entries(icons).map(([key, value]) => {
75
+ return ` '${key}': \`${value}\``;
76
+ });
77
+
78
+ const output = `window.rtglIcons = {\n${iconEntries.join(',\n')}\n};`;
79
+
80
+ writeFileSync(outfile, output);
81
+
82
+ console.log(`SVG icons written to: ${outfile}`);
83
+ console.log(`Total icons: ${Object.keys(icons).length}`);
84
+ };
85
+
86
+ export default buildSvgIcons;
@@ -0,0 +1 @@
1
+ export { default as buildSvg } from './buildSvg.js';
@@ -0,0 +1,9 @@
1
+ export const handleClickItem = (e, deps) => {
2
+ const { dispatchEvent } = deps;
3
+ const id = e.currentTarget.dataset.id;
4
+ dispatchEvent(new CustomEvent('item-click', {
5
+ detail: {
6
+ id
7
+ }
8
+ }));
9
+ }
@@ -0,0 +1,29 @@
1
+ export const INITIAL_STATE = Object.freeze({});
2
+
3
+ const blacklistedAttrs = ['id', 'class', 'style', 'slot'];
4
+
5
+ const stringifyAttrs = (attrs) => {
6
+ return Object.entries(attrs).filter(([key]) => !blacklistedAttrs.includes(key)).map(([key, value]) => `${key}=${value}`).join(' ');
7
+ }
8
+
9
+ export const toViewData = ({ props, attrs }) => {
10
+ const containerAttrString = stringifyAttrs(attrs);
11
+
12
+ const items = props.items || [];
13
+ const separator = props.separator || 'breadcrumb-arrow';
14
+
15
+ // Add separators between items, but not after the last one
16
+ const itemsWithSeparators = [];
17
+ items.forEach((item, index) => {
18
+ itemsWithSeparators.push(item);
19
+ if (index < items.length - 1) {
20
+ itemsWithSeparators.push({ isSeparator: true });
21
+ }
22
+ });
23
+
24
+ return {
25
+ containerAttrString,
26
+ items: itemsWithSeparators,
27
+ separator
28
+ };
29
+ }
@@ -0,0 +1,64 @@
1
+ elementName: rtgl-breadcrumb
2
+
3
+ viewDataSchema:
4
+ type: object
5
+ properties:
6
+ containerAttrString:
7
+ type: string
8
+ items:
9
+ type: array
10
+ items:
11
+ type: object
12
+ properties:
13
+ label:
14
+ type: string
15
+ id:
16
+ type: string
17
+ separator:
18
+ type: string
19
+
20
+ propsSchema:
21
+ type: object
22
+ properties:
23
+ items:
24
+ type: array
25
+ items:
26
+ type: object
27
+ properties:
28
+ label:
29
+ type: string
30
+ id:
31
+ type: string
32
+ separator:
33
+ type: string
34
+ default: "breadcrumb-arrow"
35
+
36
+ refs:
37
+ item-*:
38
+ eventListeners:
39
+ click:
40
+ handler: handleClickItem
41
+ events:
42
+ item-click:
43
+ type: object
44
+ properties:
45
+ item:
46
+ type: object
47
+ properties:
48
+ label:
49
+ type: string
50
+ id:
51
+ type: string
52
+ index:
53
+ type: number
54
+
55
+ template:
56
+ - rtgl-view d=h av=c g=md p=sm ${containerAttrString}:
57
+ - $for item in items:
58
+ - $if item.isSeparator:
59
+ - rtgl-svg wh=16 svg=${separator} c=mu-fg:
60
+ $elif item.id:
61
+ - rtgl-view#item-${item.id} data-id=${item.id} cur=p:
62
+ - rtgl-text s=sm c=mu-fg: "${item.label}"
63
+ $else:
64
+ - rtgl-text s=sm c=mu-fg: "${item.label}"
@@ -1,18 +1,18 @@
1
1
 
2
- export const handleClickPopoverOverlay = (e, deps) => {
2
+ export const handleClosePopover = (e, deps) => {
3
3
  const { dispatchEvent } = deps;
4
- dispatchEvent(new CustomEvent('click-overlay'));
4
+ dispatchEvent(new CustomEvent('close'));
5
5
  }
6
6
 
7
7
  export const handleClickMenuItem = (e, deps) => {
8
8
  const { dispatchEvent } = deps;
9
9
  const index = parseInt(e.currentTarget.id.replace('option-', ''));
10
10
  const item = deps.props.items[index];
11
-
11
+
12
12
  dispatchEvent(new CustomEvent('click-item', {
13
13
  detail: {
14
14
  index,
15
15
  item
16
16
  }
17
17
  }));
18
- }
18
+ }
@@ -2,24 +2,12 @@
2
2
  export const INITIAL_STATE = Object.freeze({
3
3
  });
4
4
 
5
- export const toViewData = ({ state, props }) => {
5
+ export const toViewData = ({ props, attrs }) => {
6
6
  return {
7
7
  items: props.items || [],
8
- isOpen: props.isOpen || false,
9
- position: props.position || {
10
- x: 0,
11
- y: 0,
12
- },
8
+ open: !!attrs.open,
9
+ x: attrs.x,
10
+ y: attrs.y,
11
+ placement: attrs.placement
13
12
  };
14
13
  }
15
-
16
- export const selectState = ({ state }) => {
17
- return state;
18
- }
19
-
20
- export const setState = (state) => {
21
- // do doSomething
22
- }
23
-
24
-
25
-
@@ -19,28 +19,31 @@ propsSchema:
19
19
  - label
20
20
  - item
21
21
  - separator
22
- isOpen:
23
- type: boolean
24
- position:
25
- type: object
26
- properties:
27
- x:
28
- type: number
29
- y:
30
- type: number
22
+
23
+ attrsSchema:
24
+ type: object
25
+ properties:
26
+ open:
27
+ type: string
28
+ x:
29
+ type: string
30
+ y:
31
+ type: string
32
+ placement:
33
+ type: string
31
34
 
32
35
  refs:
33
36
  popover:
34
37
  eventListeners:
35
- click-overlay:
36
- handler: handleClickPopoverOverlay
38
+ close:
39
+ handler: handleClosePopover
37
40
  option-*:
38
41
  eventListeners:
39
42
  click:
40
43
  handler: handleClickMenuItem
41
44
 
42
45
  template:
43
- - rtgl-popover#popover .isOpen=isOpen .position=position:
46
+ - rtgl-popover#popover ?open=${open} x=${x} y=${y} placement=${placement}:
44
47
  - rtgl-view wh=300 g=xs slot=content bgc=background br=md:
45
48
  - $for item, i in items:
46
49
  - $if item.type == 'label':
@@ -51,4 +54,3 @@ template:
51
54
  - rtgl-text: ${item.label}
52
55
  $elif item.type == 'separator':
53
56
  - rtgl-view w=f h=1 ph=lg mv=md bgc=bo:
54
-
@@ -1,13 +1,25 @@
1
- export const handleOnMount = (deps) => {
1
+ export const handleBeforeMount = (deps) => {
2
2
  const { store, props } = deps;
3
- store.setDefaultValues(props.defaultValues);
3
+ store.setFormValues(props.defaultValues);
4
4
  };
5
5
 
6
- const dispatchFormChange = (fieldName, fieldValue, formValues, dispatchEvent) => {
6
+ export const handleOnUpdate = (changes, deps) => {
7
+ const { oldAttrs, newAttrs } = changes;
8
+ const { store, props, render } = deps;
9
+
10
+ if (oldAttrs?.key === newAttrs?.key) {
11
+ return;
12
+ }
13
+
14
+ store.setFormValues(props.defaultValues);
15
+ render();
16
+ };
17
+
18
+ const dispatchFormChange = (name, fieldValue, formValues, dispatchEvent) => {
7
19
  dispatchEvent(
8
20
  new CustomEvent("form-change", {
9
21
  detail: {
10
- fieldName,
22
+ name,
11
23
  fieldValue,
12
24
  formValues,
13
25
  },
@@ -29,51 +41,148 @@ export const handleActionClick = (e, deps) => {
29
41
  };
30
42
 
31
43
  export const handleInputChange = (e, deps) => {
44
+ const { store, dispatchEvent, props } = deps;
45
+ const name = e.currentTarget.id.replace("input-", "");
46
+ // TODO fix double event
47
+ if (name && e.detail.value !== undefined) {
48
+ store.setFormFieldValue({
49
+ name: name,
50
+ value: e.detail.value,
51
+ props,
52
+ });
53
+ dispatchFormChange(
54
+ name,
55
+ e.detail.value,
56
+ store.selectFormValues(),
57
+ dispatchEvent,
58
+ );
59
+ }
60
+ };
61
+
62
+ export const handlePopoverInputChange = (e, deps) => {
32
63
  const { store, dispatchEvent } = deps;
33
- const id = e.currentTarget.id.replace("input-", "");
64
+ const name = e.currentTarget.id.replace("popover-input-", "");
34
65
  // TODO fix double event
35
- if (id && e.detail.value !== undefined) {
66
+ if (name && e.detail.value !== undefined) {
36
67
  store.setFormFieldValue({
37
- // TODO user field name instead of id
38
- fieldName: id,
68
+ name: name,
39
69
  value: e.detail.value,
70
+ props,
40
71
  });
41
- dispatchFormChange(id, e.detail.value, store.selectFormValues(), dispatchEvent);
72
+ dispatchFormChange(
73
+ name,
74
+ e.detail.value,
75
+ store.selectFormValues(),
76
+ dispatchEvent,
77
+ );
42
78
  }
43
79
  };
44
80
 
45
81
  export const handleSelectChange = (e, deps) => {
46
- const { store, dispatchEvent } = deps;
47
- const id = e.currentTarget.id.replace("select-", "");
48
- if (id && e.detail.selectedValue !== undefined) {
82
+ const { store, dispatchEvent, render, props } = deps;
83
+ const name = e.currentTarget.id.replace("select-", "");
84
+ if (name && e.detail.selectedValue !== undefined) {
49
85
  store.setFormFieldValue({
50
- fieldName: id,
86
+ name: name,
51
87
  value: e.detail.selectedValue,
88
+ props,
52
89
  });
53
- dispatchFormChange(id, e.detail.selectedValue, store.selectFormValues(), dispatchEvent);
90
+ dispatchFormChange(
91
+ name,
92
+ e.detail.selectedValue,
93
+ store.selectFormValues(),
94
+ dispatchEvent,
95
+ );
96
+ render();
54
97
  }
55
98
  };
56
99
 
57
100
  export const handleColorPickerChange = (e, deps) => {
58
- const { store, dispatchEvent } = deps;
59
- const id = e.currentTarget.id.replace("colorpicker-", "");
60
- if (id && e.detail.value !== undefined) {
101
+ const { store, dispatchEvent, props } = deps;
102
+ const name = e.currentTarget.id.replace("colorpicker-", "");
103
+ if (name && e.detail.value !== undefined) {
61
104
  store.setFormFieldValue({
62
- fieldName: id,
105
+ name: name,
63
106
  value: e.detail.value,
107
+ props,
64
108
  });
65
- dispatchFormChange(id, e.detail.value, store.selectFormValues(), dispatchEvent);
109
+ dispatchFormChange(
110
+ name,
111
+ e.detail.value,
112
+ store.selectFormValues(),
113
+ dispatchEvent,
114
+ );
66
115
  }
67
116
  };
68
117
 
69
118
  export const handleSliderChange = (e, deps) => {
70
- const { store, dispatchEvent } = deps;
71
- const id = e.currentTarget.id.replace("slider-", "");
72
- if (id && e.detail.value !== undefined) {
119
+ const { store, dispatchEvent, props } = deps;
120
+ const name = e.currentTarget.id.replace("slider-", "");
121
+ if (name && e.detail.value !== undefined) {
73
122
  store.setFormFieldValue({
74
- fieldName: id,
123
+ name: name,
75
124
  value: e.detail.value,
125
+ props,
76
126
  });
77
- dispatchFormChange(id, e.detail.value, store.selectFormValues(), dispatchEvent);
127
+ dispatchFormChange(
128
+ name,
129
+ e.detail.value,
130
+ store.selectFormValues(),
131
+ dispatchEvent,
132
+ );
78
133
  }
79
134
  };
135
+
136
+ export const handleSliderInputChange = (e, deps) => {
137
+ const { store, dispatchEvent, props } = deps;
138
+ const name = e.currentTarget.id.replace("slider-input-", "");
139
+ if (name && e.detail.value !== undefined) {
140
+ store.setFormFieldValue({
141
+ name: name,
142
+ value: e.detail.value,
143
+ props,
144
+ });
145
+ dispatchFormChange(
146
+ name,
147
+ e.detail.value,
148
+ store.selectFormValues(),
149
+ dispatchEvent,
150
+ );
151
+ }
152
+ };
153
+
154
+ export const handleImageClick = (e, deps) => {
155
+ if (e.type === "contextmenu") {
156
+ e.preventDefault();
157
+ }
158
+ const { dispatchEvent } = deps;
159
+ const name = e.currentTarget.id.replace("image-", "");
160
+ dispatchEvent(
161
+ new CustomEvent("extra-event", {
162
+ detail: {
163
+ name: name,
164
+ x: e.clientX,
165
+ y: e.clientY,
166
+ trigger: e.type,
167
+ },
168
+ }),
169
+ );
170
+ };
171
+
172
+ export const handleWaveformClick = (e, deps) => {
173
+ if (e.type === "contextmenu") {
174
+ e.preventDefault();
175
+ }
176
+ const { dispatchEvent } = deps;
177
+ const name = e.currentTarget.id.replace("waveform-", "");
178
+ dispatchEvent(
179
+ new CustomEvent("extra-event", {
180
+ detail: {
181
+ name: name,
182
+ x: e.clientX,
183
+ y: e.clientY,
184
+ trigger: e.type,
185
+ },
186
+ }),
187
+ );
188
+ };
@@ -1,45 +1,147 @@
1
+ import { parseAndRender } from "jempl";
2
+
3
+ function pick(obj, keys) {
4
+ return keys.reduce((acc, key) => {
5
+ if (key in obj) acc[key] = obj[key];
6
+ return acc;
7
+ }, {});
8
+ }
9
+
1
10
  export const INITIAL_STATE = Object.freeze({
2
- formValues: {}
11
+ formValues: {},
3
12
  });
4
13
 
5
- const blacklistedAttrs = ['id', 'class', 'style', 'slot'];
14
+ // Lodash-like utility functions for nested property access
15
+ const get = (obj, path, defaultValue = undefined) => {
16
+ if (!path) {
17
+ return;
18
+ }
19
+ const keys = path.split(/[\[\].]/).filter((key) => key !== "");
20
+ let current = obj;
21
+
22
+ for (const key of keys) {
23
+ if (current === null || current === undefined || !(key in current)) {
24
+ return defaultValue;
25
+ }
26
+ current = current[key];
27
+ }
28
+ return current;
29
+ };
30
+
31
+ const set = (obj, path, value) => {
32
+ const keys = path.split(/[\[\].]/).filter((key) => key !== "");
33
+
34
+ // If path contains array notation, delete the original flat key
35
+ if (path.includes("[") && path in obj) {
36
+ delete obj[path];
37
+ }
38
+
39
+ let current = obj;
40
+
41
+ for (let i = 0; i < keys.length - 1; i++) {
42
+ const key = keys[i];
43
+ if (
44
+ !(key in current) ||
45
+ typeof current[key] !== "object" ||
46
+ current[key] === null
47
+ ) {
48
+ // Check if next key is a number to create array
49
+ const nextKey = keys[i + 1];
50
+ const isArrayIndex = /^\d+$/.test(nextKey);
51
+ current[key] = isArrayIndex ? [] : {};
52
+ }
53
+ current = current[key];
54
+ }
55
+
56
+ current[keys[keys.length - 1]] = value;
57
+ return obj;
58
+ };
59
+
60
+ const blacklistedAttrs = ["id", "class", "style", "slot"];
6
61
 
7
62
  const stringifyAttrs = (attrs) => {
8
- return Object.entries(attrs).filter(([key]) => !blacklistedAttrs.includes(key)).map(([key, value]) => `${key}=${value}`).join(' ');
9
- }
63
+ return Object.entries(attrs)
64
+ .filter(([key]) => !blacklistedAttrs.includes(key))
65
+ .map(([key, value]) => `${key}=${value}`)
66
+ .join(" ");
67
+ };
68
+
69
+ export const selectForm = ({ state, props }) => {
70
+ const { form } = props;
71
+ const { context } = props;
72
+
73
+ if (context) {
74
+ return parseAndRender(form, context);
75
+ }
76
+
77
+ return form;
78
+ };
10
79
 
11
80
  export const toViewData = ({ state, props, attrs }) => {
12
81
  const containerAttrString = stringifyAttrs(attrs);
82
+ const defaultValues = props.defaultValues || {};
83
+
84
+ const form = selectForm({ state, props });
85
+ const fields = structuredClone(form.fields || []);
86
+ fields.forEach((field) => {
87
+ field.defaultValue = get(defaultValues, field.name);
88
+
89
+ if (field.inputType === "image") {
90
+ const src = field.src;
91
+ // Only set imageSrc if src exists and is not empty
92
+ field.imageSrc = src && src.trim() ? src : null;
93
+ // Set placeholder text
94
+ field.placeholderText = field.placeholder || "No Image";
95
+ }
96
+ if (field.inputType === "waveform") {
97
+ const waveformData = field.waveformData;
98
+ // Only set waveformData if it exists
99
+ field.waveformData = waveformData || null;
100
+ // Set placeholder text
101
+ field.placeholderText = field.placeholder || "No Waveform";
102
+ }
103
+ });
104
+
13
105
  return {
14
106
  containerAttrString,
15
- title: props.form?.title || '',
16
- description: props?.form?.description || '',
17
- fields: props?.form?.fields || [],
107
+ title: form?.title || "",
108
+ description: form?.description || "",
109
+ fields: fields,
18
110
  actions: props?.form?.actions || {
19
- buttons: []
111
+ buttons: [],
20
112
  },
21
- // TODO fix default values
22
113
  formValues: state.formValues,
23
114
  };
24
- }
115
+ };
25
116
 
26
117
  export const selectState = ({ state }) => {
27
118
  return state;
28
- }
119
+ };
29
120
 
30
- export const selectFormValues = ({ state }) => {
31
- return state.formValues;
32
- }
121
+ export const selectFormValues = ({ state, props }) => {
122
+ const form = selectForm({ state, props });
33
123
 
34
- export const setState = (state) => {
35
- // do doSomething
36
- }
124
+ return pick(
125
+ state.formValues,
126
+ form.fields.map((field) => field.name),
127
+ );
128
+ };
37
129
 
38
- export const setDefaultValues = (state, defaultValues) => {
39
- state.formValues = defaultValues || {};
40
- }
130
+ export const getFormFieldValue = ({ state }, name) => {
131
+ return get(state.formValues, name);
132
+ };
41
133
 
42
- export const setFormFieldValue = (state, { fieldName, value }) => {
43
- state.formValues[fieldName] = value;
44
- }
134
+ export const setFormValues = (state, defaultValues) => {
135
+ state.formValues = defaultValues || {};
136
+ };
45
137
 
138
+ export const setFormFieldValue = (state, { name, value, props }) => {
139
+ set(state.formValues, name, value);
140
+ // remove non visible values
141
+ const form = selectForm({ state, props });
142
+ const formValues = pick(
143
+ state.formValues,
144
+ form.fields.map((field) => field.name),
145
+ );
146
+ state.formValues = formValues;
147
+ };