Skip to content

Commit

Permalink
✨ [#2] Implement map component schema type definition
Browse files Browse the repository at this point in the history
  • Loading branch information
sergei-maertens committed Dec 4, 2023
1 parent 1c13f2f commit ae7508e
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/formio/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export * from './selectboxes';
export * from './file';
export * from './radio';
export * from './address';
export * from './map';

// Layout components
export * from './content';
Expand Down
60 changes: 60 additions & 0 deletions src/formio/components/map.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import {InputComponentSchema} from '..';

type Validator = 'required';
type TranslatableKeys = 'label' | 'description' | 'tooltip';

/**
* The map value type.
*
* Currently this is limited to a tuple of coordinates identifying a single point on
* the map. It is expected that in the future this will become a full blown GeoJSON
* shape.
*/
export type MapValue = [number, number];

export type MapInputSchema = InputComponentSchema<null | MapValue, Validator, TranslatableKeys>;

/**
* Custom Formio component type.
*
* @group Form.io components
* @category Concrete types
*/
export interface MapComponentSchema
extends Omit<MapInputSchema, 'hideLabel' | 'disabled' | 'placeholder'> {
type: 'map';
/**
* Default zoom level, limited by Leaflet and the available tile service zoom levels.
*
* Leaflet zoom level is a range of 1-20, but the Dutch tile service only supports up
* to level 13.
*
* @todo Make property required, which requires a data migration.
*/
defaultZoom?: null | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13;
/**
* Coordinates to center the map on initially.
*
* @todo Make property required, which requires a data migration.
*/
initialCenter?: {
lat?: number;
lng?: number;
};
/**
* If true, the backend must apply the globally configured defaults to a particular
* map instance. This results in populating `defaultZoom` and `initialCenter`, so for
* the SDK this property has no effect.
*
* @todo Make property required, which requires a data migration.
*/
useConfigDefaultMapSettings?: boolean;
/**
* Only specified to be able to type the submission data value. We do not see a use
* case for pre-selecting a particular location on a map component, as the SDK asks
* the user for their location anyway.
*
* @todo Do not add the default value to the builder.
*/
defaultValue?: null | MapValue;
}
2 changes: 2 additions & 0 deletions src/formio/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
FileComponentSchema,
IbanComponentSchema,
LicensePlateComponentSchema,
MapComponentSchema,
NpFamilyMembersComponentSchema,
NumberComponentSchema,
PhoneNumberComponentSchema,
Expand Down Expand Up @@ -70,6 +71,7 @@ export type AnyComponentSchema =
| BsnComponentSchema
| NpFamilyMembersComponentSchema
| AddressComponentSchema
| MapComponentSchema
// layout
| ContentComponentSchema
| ColumnsComponentSchema
Expand Down
108 changes: 108 additions & 0 deletions test-d/formio/components/map.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import {expectAssignable, expectNotAssignable} from 'tsd';

import {MapComponentSchema} from '../../../lib/';

// minimal map component schema
expectAssignable<MapComponentSchema>({
id: 'yejak',
type: 'map',
key: 'someMap',
label: 'Some map',
});

// with additional, map-component specific properties
expectAssignable<MapComponentSchema>({
id: 'yejak',
type: 'map',
key: 'someMap',
label: 'Some map',
defaultZoom: 10,
initialCenter: {
lat: 52.37403,
lng: 4.88969,
},
useConfigDefaultMapSettings: false,
defaultValue: null,
});

// full, correct schema
expectAssignable<MapComponentSchema>({
id: 'yejak',
type: 'map',
defaultValue: null,
// basic tab in builder form
label: 'Some map',
key: 'someMap',
description: 'A description',
tooltip: 'A tooltip',
showInSummary: true,
showInEmail: false,
showInPDF: true,
hidden: false,
clearOnHide: true,
isSensitiveData: false,
defaultZoom: 10,
initialCenter: {
lat: 52.37403,
lng: 4.88969,
},
useConfigDefaultMapSettings: false,
// advanced tab in builder form
conditional: {
show: undefined,
when: undefined,
eq: undefined,
},
// validation tab in builder form
validate: {
required: false,
plugins: undefined,
},
translatedErrors: {
nl: {
required: 'Je moet een waarde opgeven!!!',
},
},
errors: {
// translatedErrors is converted into errors by the backend
required: 'Je moet een waarde opgeven!!!',
},
// registration tab in builder form
registration: {
attribute: '',
},
// translations tab in builder form
openForms: {
translations: {
nl: {
label: 'foo',
description: 'bar',
},
},
},
});

// different component type
expectNotAssignable<MapComponentSchema>({
type: 'fieldset',
} as const);

// no 'multiple' support
expectNotAssignable<MapComponentSchema>({
id: 'yejak',
type: 'map',
key: 'someMap',
label: 'Some map',
multiple: true,
} as const);

// incorrect, invalid validator key
expectNotAssignable<MapComponentSchema>({
id: 'yejak',
type: 'map',
key: 'someMap',
label: 'Some map',
validate: {
maxLength: 100,
},
} as const);

0 comments on commit ae7508e

Please sign in to comment.