diff --git a/src/formio/components/index.ts b/src/formio/components/index.ts index 70e30e5..b8fa54f 100644 --- a/src/formio/components/index.ts +++ b/src/formio/components/index.ts @@ -19,6 +19,7 @@ export * from './selectboxes'; export * from './file'; export * from './radio'; export * from './address'; +export * from './map'; // Layout components export * from './content'; diff --git a/src/formio/components/map.ts b/src/formio/components/map.ts new file mode 100644 index 0000000..79fda20 --- /dev/null +++ b/src/formio/components/map.ts @@ -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; + +/** + * Custom Formio component type. + * + * @group Form.io components + * @category Concrete types + */ +export interface MapComponentSchema + extends Omit { + 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; +} diff --git a/src/formio/index.ts b/src/formio/index.ts index 50b1679..b4e6bf1 100644 --- a/src/formio/index.ts +++ b/src/formio/index.ts @@ -12,6 +12,7 @@ import { FileComponentSchema, IbanComponentSchema, LicensePlateComponentSchema, + MapComponentSchema, NpFamilyMembersComponentSchema, NumberComponentSchema, PhoneNumberComponentSchema, @@ -70,6 +71,7 @@ export type AnyComponentSchema = | BsnComponentSchema | NpFamilyMembersComponentSchema | AddressComponentSchema + | MapComponentSchema // layout | ContentComponentSchema | ColumnsComponentSchema diff --git a/test-d/formio/components/map.test-d.ts b/test-d/formio/components/map.test-d.ts new file mode 100644 index 0000000..d63ae12 --- /dev/null +++ b/test-d/formio/components/map.test-d.ts @@ -0,0 +1,108 @@ +import {expectAssignable, expectNotAssignable} from 'tsd'; + +import {MapComponentSchema} from '../../../lib/'; + +// minimal map component schema +expectAssignable({ + id: 'yejak', + type: 'map', + key: 'someMap', + label: 'Some map', +}); + +// with additional, map-component specific properties +expectAssignable({ + 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({ + 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({ + type: 'fieldset', +} as const); + +// no 'multiple' support +expectNotAssignable({ + id: 'yejak', + type: 'map', + key: 'someMap', + label: 'Some map', + multiple: true, +} as const); + +// incorrect, invalid validator key +expectNotAssignable({ + id: 'yejak', + type: 'map', + key: 'someMap', + label: 'Some map', + validate: { + maxLength: 100, + }, +} as const);