• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ginkgobioworks / react-json-schema-form-builder / 20682242618

03 Jan 2026 08:03PM UTC coverage: 72.475% (+0.02%) from 72.451%
20682242618

push

github

raymond-lam
Refactor types and improve build configuration

- Split types.ts into internalTypes.ts and publicTypes.ts for better organization
- Make type definitions public by separating public API types from internal-only types
- Rename types for consistency (with backward compatibility aliases):
  - CardComponentPropsType → CardComponentProps
  - CardComponentType → CardComponent
  - InputSelectDataType → InputSelectData
  - SectionPropsType → SectionProps
  - CardModalType → CardModal
- Export public types from index.ts for better API discoverability
- Keep types.ts as the main import point for all types (re-exports from publicTypes.ts and internalTypes.ts)
- Improve build configuration and tooling

Documentation updates:
- Update Mods.md to show how to import types from the package instead of inline definitions
- Update Usage.md to use new type names and improve custom form input examples
- Replace email example with comprehensive phone number example in Usage.md
- Update all documentation screenshots with fresh captures from live application
- Update screenshots: array.png, array2.png, card.png, collapsed.png, dependency1.png, dependency2.png, modal.png, reference.png, section.png
- Remove visualDemo.gif as it is no longer referenced in documentation

790 of 1122 branches covered (70.41%)

Branch coverage included in aggregate %.

18 of 19 new or added lines in 10 files covered. (94.74%)

1 existing line in 1 file now uncovered.

882 of 1185 relevant lines covered (74.43%)

22.68 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

56.67
/src/formBuilder/defaults/arrayInputs.tsx
1
import React, { useState } from 'react';
2
import TextField from '@mui/material/TextField';
3
import Box from '@mui/material/Box';
4
import Typography from '@mui/material/Typography';
5
import {
6
  excludeKeys,
7
  generateElementComponentsFromSchemas,
8
  generateCategoryHash,
9
} from '../utils';
10
import Card from '../Card';
11
import Section from '../Section';
12
import FBCheckbox from '../FBCheckbox';
13
import shortAnswerInputs from './shortAnswerInputs';
14
import longAnswerInputs from './longAnswerInputs';
15
import numberInputs from './numberInputs';
16
import defaultInputs from './defaultInputs';
17
import { getRandomId } from '../utils';
18
import type { FormInput, CardComponent, CardComponentProps } from '../types';
19

20
// specify the inputs required for a string type object
21
const CardArrayParameterInputs: CardComponent = ({ parameters, onChange }) => {
7✔
UNCOV
22
  return (
×
23
    <Box>
24
      <Typography variant='subtitle2' fontWeight='bold'>
25
        Minimum Items
26
      </Typography>
27
      <TextField
28
        value={parameters.minItems || ''}
×
29
        placeholder='ex: 2'
30
        type='number'
31
        onChange={(ev) => {
32
          onChange({
×
33
            ...parameters,
34
            minItems: parseInt(ev.target.value, 10),
35
          });
36
        }}
37
        size='small'
38
        fullWidth
39
        sx={{ mb: 2 }}
40
      />
41
      <Typography variant='subtitle2' fontWeight='bold'>
42
        Maximum Items
43
      </Typography>
44
      <TextField
45
        value={parameters.maxItems || ''}
×
46
        placeholder='ex: 2'
47
        type='number'
48
        onChange={(ev) => {
49
          onChange({
×
50
            ...parameters,
51
            maxItems: parseInt(ev.target.value, 10),
52
          });
53
        }}
54
        size='small'
55
        fullWidth
56
        sx={{ mb: 2 }}
57
      />
58
    </Box>
59
  );
60
};
61

62
const InnerCard: CardComponent = ({ parameters, onChange, mods }) => {
7✔
63
  const [elementId] = useState(getRandomId);
1✔
64
  const newDataProps: { [key: string]: any } = {};
1✔
65
  const newUiProps: { [key: string]: any } = {};
1✔
66
  const allFormInputs = excludeKeys(
1✔
67
    Object.assign({}, defaultFormInputs, (mods && mods.customFormInputs) || {}),
2!
68
    mods && mods.deactivatedFormInputs,
2✔
69
  );
70

71
  // parse components into data and ui relevant pieces
72
  Object.keys(parameters).forEach((propName: string) => {
1✔
73
    if (propName.startsWith('ui:*')) {
15✔
74
      newUiProps[propName.substring(4)] =
1✔
75
        parameters[propName as keyof CardComponentProps];
76
    } else if (propName.startsWith('ui:')) {
14!
NEW
77
      newUiProps[propName] = parameters[propName as keyof CardComponentProps];
×
78
    } else if (!['name', 'required'].includes(propName)) {
14✔
79
      newDataProps[propName] = parameters[propName as keyof CardComponentProps];
12✔
80
    }
81
  });
82

83
  const definitionData = parameters.definitionData
1!
84
    ? parameters.definitionData
85
    : {};
86
  const definitionUi = parameters.definitionUi ? parameters.definitionUi : {};
1!
87
  const [cardOpen, setCardOpen] = React.useState(false);
1✔
88
  if (parameters.type !== 'array') {
1!
89
    return (
×
90
      <Typography variant='body2' color='error'>
91
        Not an array
92
      </Typography>
93
    );
94
  }
95
  return (
1✔
96
    <>
97
      <FBCheckbox
98
        onChangeValue={() => {
99
          if (newDataProps.items.type === 'object') {
×
100
            onChange({
×
101
              ...parameters,
102
              items: {
103
                ...newDataProps.items,
104
                type: 'string',
105
              },
106
            });
107
          } else {
108
            onChange({
×
109
              ...parameters,
110
              items: {
111
                ...newDataProps.items,
112
                type: 'object',
113
              },
114
            });
115
          }
116
        }}
117
        isChecked={newDataProps.items.type === 'object'}
118
        label='Section'
119
      />
120
      {generateElementComponentsFromSchemas({
121
        schemaData: { properties: { item: newDataProps.items } },
122
        uiSchemaData: { item: newUiProps.items },
123
        onChange: (schema, uischema) => {
124
          onChange({
×
125
            ...parameters,
126
            items: schema.properties.item,
127
            'ui:*items': uischema.item || {},
×
128
          });
129
        },
130
        path: elementId,
131
        definitionData,
132
        definitionUi,
133
        hideKey: true,
134
        cardOpenArray: [cardOpen],
135
        setCardOpenArray: (updater) => {
136
          const newArr =
137
            typeof updater === 'function' ? updater([cardOpen]) : updater;
×
138
          setCardOpen(newArr[0]);
×
139
        },
140
        allFormInputs,
141
        mods,
142
        categoryHash: generateCategoryHash(allFormInputs),
143
        Card: (props) => <Card {...props} showObjectNameInput={false} />,
1✔
144
        Section,
145
      })}
146
    </>
147
  );
148
};
149

150
function getInnerCardComponent(): CardComponent {
151
  return InnerCard;
14✔
152
}
153

154
const defaultFormInputs: { [key: string]: FormInput } = {
7✔
155
  ...defaultInputs,
156
  ...shortAnswerInputs,
157
  ...longAnswerInputs,
158
  ...numberInputs,
159
};
160
defaultFormInputs.array = {
7✔
161
  displayName: 'Array',
162
  matchIf: [
163
    {
164
      types: ['array'],
165
    },
166
  ],
167
  defaultDataSchema: {
168
    items: { type: 'string' },
169
  },
170
  defaultUiSchema: {},
171
  type: 'array',
172
  cardBody: getInnerCardComponent(),
173
  modalBody: CardArrayParameterInputs,
174
};
175

176
const ArrayInputs: { [key: string]: FormInput } = {
7✔
177
  array: {
178
    displayName: 'Array',
179
    matchIf: [
180
      {
181
        types: ['array'],
182
      },
183
    ],
184
    defaultDataSchema: {
185
      items: { type: 'string' },
186
    },
187
    defaultUiSchema: {},
188
    type: 'array',
189
    cardBody: getInnerCardComponent(),
190
    modalBody: CardArrayParameterInputs,
191
  },
192
};
193

194
export default ArrayInputs;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc