@luomus/laji-form 14.3.6

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 (302) hide show
  1. package/CHANGELOG.md +215 -0
  2. package/LICENSE +21 -0
  3. package/README.md +180 -0
  4. package/cypress/fixtures/example.json +5 -0
  5. closes suggestion list (failed).png +0 -0
  6. is marked as suggested (failed).png +0 -0
  7. package/dist/images/finnish-flag.png +0 -0
  8. package/dist/images/handled.png +0 -0
  9. package/dist/images/heard.png +0 -0
  10. package/dist/images/indirect.png +0 -0
  11. package/dist/images/media.png +0 -0
  12. package/dist/images/seen.png +0 -0
  13. package/dist/images/specimen.png +0 -0
  14. package/dist/laji-form.js +2 -0
  15. package/dist/laji-form.js.LICENSE.txt +92 -0
  16. package/dist/styles.css +3771 -0
  17. package/lib/ApiClient.d.ts +46 -0
  18. package/lib/ApiClient.js +93 -0
  19. package/lib/Context.d.ts +8 -0
  20. package/lib/Context.js +18 -0
  21. package/lib/ReactContext.d.ts +7 -0
  22. package/lib/ReactContext.js +5 -0
  23. package/lib/components/BaseComponent.d.ts +9 -0
  24. package/lib/components/BaseComponent.js +29 -0
  25. package/lib/components/LajiForm.d.ts +221 -0
  26. package/lib/components/LajiForm.js +614 -0
  27. package/lib/components/VirtualSchemaField.d.ts +42 -0
  28. package/lib/components/VirtualSchemaField.js +74 -0
  29. package/lib/components/components.d.ts +119 -0
  30. package/lib/components/components.js +606 -0
  31. package/lib/components/fields/AnnotationField.d.ts +34 -0
  32. package/lib/components/fields/AnnotationField.js +242 -0
  33. package/lib/components/fields/AnyToBooleanField.d.ts +18 -0
  34. package/lib/components/fields/AnyToBooleanField.js +20 -0
  35. package/lib/components/fields/ArrayBulkField.d.ts +23 -0
  36. package/lib/components/fields/ArrayBulkField.js +82 -0
  37. package/lib/components/fields/ArrayCombinerField.d.ts +36 -0
  38. package/lib/components/fields/ArrayCombinerField.js +138 -0
  39. package/lib/components/fields/ArrayField.d.ts +39 -0
  40. package/lib/components/fields/ArrayField.js +148 -0
  41. package/lib/components/fields/AudioArrayField.d.ts +22 -0
  42. package/lib/components/fields/AudioArrayField.js +100 -0
  43. package/lib/components/fields/AutoArrayField.d.ts +24 -0
  44. package/lib/components/fields/AutoArrayField.js +56 -0
  45. package/lib/components/fields/AutosuggestField.d.ts +69 -0
  46. package/lib/components/fields/AutosuggestField.js +299 -0
  47. package/lib/components/fields/CombinedValueDisplayField.d.ts +41 -0
  48. package/lib/components/fields/CombinedValueDisplayField.js +100 -0
  49. package/lib/components/fields/ConditionalOnChangeField.d.ts +42 -0
  50. package/lib/components/fields/ConditionalOnChangeField.js +107 -0
  51. package/lib/components/fields/ConditionalUiSchemaField.d.ts +123 -0
  52. package/lib/components/fields/ConditionalUiSchemaField.js +143 -0
  53. package/lib/components/fields/ContextInjectionField.d.ts +24 -0
  54. package/lib/components/fields/ContextInjectionField.js +68 -0
  55. package/lib/components/fields/DataLeakerField.d.ts +40 -0
  56. package/lib/components/fields/DataLeakerField.js +68 -0
  57. package/lib/components/fields/DefaultValueArrayField.d.ts +34 -0
  58. package/lib/components/fields/DefaultValueArrayField.js +59 -0
  59. package/lib/components/fields/DependentBooleanField.d.ts +38 -0
  60. package/lib/components/fields/DependentBooleanField.js +87 -0
  61. package/lib/components/fields/DependentDisableField.d.ts +35 -0
  62. package/lib/components/fields/DependentDisableField.js +71 -0
  63. package/lib/components/fields/EnumRangeArrayField.d.ts +27 -0
  64. package/lib/components/fields/EnumRangeArrayField.js +115 -0
  65. package/lib/components/fields/ExtraLabelRowField.d.ts +38 -0
  66. package/lib/components/fields/ExtraLabelRowField.js +100 -0
  67. package/lib/components/fields/FakePropertyField.d.ts +18 -0
  68. package/lib/components/fields/FakePropertyField.js +48 -0
  69. package/lib/components/fields/FilterArrayField.d.ts +73 -0
  70. package/lib/components/fields/FilterArrayField.js +121 -0
  71. package/lib/components/fields/FlatField.d.ts +29 -0
  72. package/lib/components/fields/FlatField.js +171 -0
  73. package/lib/components/fields/GeocoderField.d.ts +47 -0
  74. package/lib/components/fields/GeocoderField.js +372 -0
  75. package/lib/components/fields/GridLayoutField.d.ts +18 -0
  76. package/lib/components/fields/GridLayoutField.js +32 -0
  77. package/lib/components/fields/HiddenField.d.ts +10 -0
  78. package/lib/components/fields/HiddenField.js +11 -0
  79. package/lib/components/fields/ImageArrayField.d.ts +153 -0
  80. package/lib/components/fields/ImageArrayField.js +696 -0
  81. package/lib/components/fields/ImageDisplayField.d.ts +18 -0
  82. package/lib/components/fields/ImageDisplayField.js +44 -0
  83. package/lib/components/fields/InitiallyHiddenField.d.ts +21 -0
  84. package/lib/components/fields/InitiallyHiddenField.js +58 -0
  85. package/lib/components/fields/InjectDefaultValueField.d.ts +37 -0
  86. package/lib/components/fields/InjectDefaultValueField.js +68 -0
  87. package/lib/components/fields/InjectField.d.ts +46 -0
  88. package/lib/components/fields/InjectField.js +88 -0
  89. package/lib/components/fields/InputWithDefaultValueButtonField.d.ts +25 -0
  90. package/lib/components/fields/InputWithDefaultValueButtonField.js +61 -0
  91. package/lib/components/fields/LocalityField.d.ts +22 -0
  92. package/lib/components/fields/LocalityField.js +94 -0
  93. package/lib/components/fields/LocationChooserField.d.ts +27 -0
  94. package/lib/components/fields/LocationChooserField.js +440 -0
  95. package/lib/components/fields/MapArrayField.d.ts +78 -0
  96. package/lib/components/fields/MapArrayField.js +1783 -0
  97. package/lib/components/fields/MapField.d.ts +48 -0
  98. package/lib/components/fields/MapField.js +434 -0
  99. package/lib/components/fields/MultiAnyToBooleanField.d.ts +25 -0
  100. package/lib/components/fields/MultiAnyToBooleanField.js +100 -0
  101. package/lib/components/fields/MultiArrayField.d.ts +53 -0
  102. package/lib/components/fields/MultiArrayField.js +224 -0
  103. package/lib/components/fields/MultiLanguageField.d.ts +13 -0
  104. package/lib/components/fields/MultiLanguageField.js +52 -0
  105. package/lib/components/fields/MultiTagArrayField.d.ts +36 -0
  106. package/lib/components/fields/MultiTagArrayField.js +142 -0
  107. package/lib/components/fields/NamedPlaceChooserField.d.ts +29 -0
  108. package/lib/components/fields/NamedPlaceChooserField.js +380 -0
  109. package/lib/components/fields/NamedPlaceSaverField.d.ts +29 -0
  110. package/lib/components/fields/NamedPlaceSaverField.js +237 -0
  111. package/lib/components/fields/NestField.d.ts +148 -0
  112. package/lib/components/fields/NestField.js +289 -0
  113. package/lib/components/fields/ObjectField.d.ts +2 -0
  114. package/lib/components/fields/ObjectField.js +119 -0
  115. package/lib/components/fields/PrefillingArrayField.d.ts +22 -0
  116. package/lib/components/fields/PrefillingArrayField.js +65 -0
  117. package/lib/components/fields/SchemaField.d.ts +7 -0
  118. package/lib/components/fields/SchemaField.js +109 -0
  119. package/lib/components/fields/ScopeField.d.ts +85 -0
  120. package/lib/components/fields/ScopeField.js +521 -0
  121. package/lib/components/fields/SectionArrayField.d.ts +38 -0
  122. package/lib/components/fields/SectionArrayField.js +614 -0
  123. package/lib/components/fields/SelectTreeField.d.ts +39 -0
  124. package/lib/components/fields/SelectTreeField.js +143 -0
  125. package/lib/components/fields/SingleActiveArrayField.d.ts +49 -0
  126. package/lib/components/fields/SingleActiveArrayField.js +974 -0
  127. package/lib/components/fields/SingleItemArrayField.d.ts +15 -0
  128. package/lib/components/fields/SingleItemArrayField.js +60 -0
  129. package/lib/components/fields/SortArrayField.d.ts +73 -0
  130. package/lib/components/fields/SortArrayField.js +351 -0
  131. package/lib/components/fields/SplitField.d.ts +28 -0
  132. package/lib/components/fields/SplitField.js +65 -0
  133. package/lib/components/fields/StringToArrayField.d.ts +24 -0
  134. package/lib/components/fields/StringToArrayField.js +48 -0
  135. package/lib/components/fields/SumField.d.ts +35 -0
  136. package/lib/components/fields/SumField.js +83 -0
  137. package/lib/components/fields/TableField.d.ts +18 -0
  138. package/lib/components/fields/TableField.js +136 -0
  139. package/lib/components/fields/TagArrayField.d.ts +38 -0
  140. package/lib/components/fields/TagArrayField.js +128 -0
  141. package/lib/components/fields/ToggleAdditionalArrayFieldsField.d.ts +26 -0
  142. package/lib/components/fields/ToggleAdditionalArrayFieldsField.js +81 -0
  143. package/lib/components/fields/UiFieldApplierField.d.ts +30 -0
  144. package/lib/components/fields/UiFieldApplierField.js +106 -0
  145. package/lib/components/fields/UiFieldMapperArrayField.d.ts +42 -0
  146. package/lib/components/fields/UiFieldMapperArrayField.js +121 -0
  147. package/lib/components/fields/UnitCountShorthandField.d.ts +22 -0
  148. package/lib/components/fields/UnitCountShorthandField.js +149 -0
  149. package/lib/components/fields/UnitListShorthandArrayField.d.ts +26 -0
  150. package/lib/components/fields/UnitListShorthandArrayField.js +108 -0
  151. package/lib/components/fields/UnitShorthandField.d.ts +32 -0
  152. package/lib/components/fields/UnitShorthandField.js +220 -0
  153. package/lib/components/templates/ArrayFieldTemplate.d.ts +85 -0
  154. package/lib/components/templates/ArrayFieldTemplate.js +416 -0
  155. package/lib/components/templates/BaseInputTemplate.d.ts +11 -0
  156. package/lib/components/templates/BaseInputTemplate.js +80 -0
  157. package/lib/components/templates/DescriptionField.d.ts +1 -0
  158. package/lib/components/templates/DescriptionField.js +37 -0
  159. package/lib/components/templates/ErrorListTemplate.d.ts +9 -0
  160. package/lib/components/templates/ErrorListTemplate.js +95 -0
  161. package/lib/components/templates/FieldTemplate.d.ts +6 -0
  162. package/lib/components/templates/FieldTemplate.js +112 -0
  163. package/lib/components/templates/ObjectFieldTemplate.d.ts +7 -0
  164. package/lib/components/templates/ObjectFieldTemplate.js +66 -0
  165. package/lib/components/templates/TitleField.d.ts +9 -0
  166. package/lib/components/templates/TitleField.js +51 -0
  167. package/lib/components/widgets/AnyToBooleanWidget.d.ts +20 -0
  168. package/lib/components/widgets/AnyToBooleanWidget.js +49 -0
  169. package/lib/components/widgets/AutosuggestWidget.d.ts +66 -0
  170. package/lib/components/widgets/AutosuggestWidget.js +1127 -0
  171. package/lib/components/widgets/CheckboxWidget.d.ts +37 -0
  172. package/lib/components/widgets/CheckboxWidget.js +139 -0
  173. package/lib/components/widgets/DateTimeWidget.d.ts +62 -0
  174. package/lib/components/widgets/DateTimeWidget.js +251 -0
  175. package/lib/components/widgets/DateWidget.d.ts +23 -0
  176. package/lib/components/widgets/DateWidget.js +41 -0
  177. package/lib/components/widgets/HiddenWidget.d.ts +15 -0
  178. package/lib/components/widgets/HiddenWidget.js +19 -0
  179. package/lib/components/widgets/ImageSelectWidget.d.ts +14 -0
  180. package/lib/components/widgets/ImageSelectWidget.js +57 -0
  181. package/lib/components/widgets/InformalTaxonGroupChooserWidget.d.ts +43 -0
  182. package/lib/components/widgets/InformalTaxonGroupChooserWidget.js +237 -0
  183. package/lib/components/widgets/InputGroupWidget.d.ts +21 -0
  184. package/lib/components/widgets/InputGroupWidget.js +36 -0
  185. package/lib/components/widgets/InputWithDefaultValueButtonWidget.d.ts +21 -0
  186. package/lib/components/widgets/InputWithDefaultValueButtonWidget.js +47 -0
  187. package/lib/components/widgets/NumberWidget.d.ts +13 -0
  188. package/lib/components/widgets/NumberWidget.js +21 -0
  189. package/lib/components/widgets/PlainTextWidget.d.ts +12 -0
  190. package/lib/components/widgets/PlainTextWidget.js +24 -0
  191. package/lib/components/widgets/SelectWidget.d.ts +52 -0
  192. package/lib/components/widgets/SelectWidget.js +158 -0
  193. package/lib/components/widgets/SeparatedDateTimeWidget.d.ts +19 -0
  194. package/lib/components/widgets/SeparatedDateTimeWidget.js +59 -0
  195. package/lib/components/widgets/TaxonImageWidget.d.ts +13 -0
  196. package/lib/components/widgets/TaxonImageWidget.js +30 -0
  197. package/lib/components/widgets/TextSelectWidget.d.ts +25 -0
  198. package/lib/components/widgets/TextSelectWidget.js +94 -0
  199. package/lib/components/widgets/TextareaWidget.d.ts +32 -0
  200. package/lib/components/widgets/TextareaWidget.js +87 -0
  201. package/lib/components/widgets/TimeWidget.d.ts +11 -0
  202. package/lib/components/widgets/TimeWidget.js +19 -0
  203. package/lib/components/widgets/URLWidget.d.ts +14 -0
  204. package/lib/components/widgets/URLWidget.js +12 -0
  205. package/lib/components/widgets/UpperCaseWidget.d.ts +13 -0
  206. package/lib/components/widgets/UpperCaseWidget.js +21 -0
  207. package/lib/index.d.ts +20 -0
  208. package/lib/index.js +50 -0
  209. package/lib/services/blocker-service.d.ts +11 -0
  210. package/lib/services/blocker-service.js +55 -0
  211. package/lib/services/custom-event-service.d.ts +17 -0
  212. package/lib/services/custom-event-service.js +35 -0
  213. package/lib/services/dom-id-service.d.ts +8 -0
  214. package/lib/services/dom-id-service.js +30 -0
  215. package/lib/services/focus-service.d.ts +13 -0
  216. package/lib/services/focus-service.js +60 -0
  217. package/lib/services/id-service.d.ts +22 -0
  218. package/lib/services/id-service.js +130 -0
  219. package/lib/services/key-handler-service.d.ts +56 -0
  220. package/lib/services/key-handler-service.js +184 -0
  221. package/lib/services/root-instance-service.d.ts +25 -0
  222. package/lib/services/root-instance-service.js +49 -0
  223. package/lib/services/settings-service.d.ts +34 -0
  224. package/lib/services/settings-service.js +154 -0
  225. package/lib/services/singleton-map-service.d.ts +23 -0
  226. package/lib/services/singleton-map-service.js +44 -0
  227. package/lib/services/submit-hook-service.d.ts +24 -0
  228. package/lib/services/submit-hook-service.js +73 -0
  229. package/lib/styles.d.ts +1 -0
  230. package/lib/styles.js +4 -0
  231. package/lib/themes/bs3.d.ts +3 -0
  232. package/lib/themes/bs3.js +133 -0
  233. package/lib/themes/bs5.d.ts +3 -0
  234. package/lib/themes/bs5.js +111 -0
  235. package/lib/themes/glyphicon-fa-mapping.d.ts +3 -0
  236. package/lib/themes/glyphicon-fa-mapping.js +271 -0
  237. package/lib/themes/stub.d.ts +3 -0
  238. package/lib/themes/stub.js +82 -0
  239. package/lib/themes/theme.d.ts +233 -0
  240. package/lib/themes/theme.js +2 -0
  241. package/lib/translations.json +842 -0
  242. package/lib/utils.d.ts +167 -0
  243. package/lib/utils.js +1191 -0
  244. package/lib/validation.d.ts +7 -0
  245. package/lib/validation.js +141 -0
  246. package/llol +10 -0
  247. package/llol.pdf +10 -0
  248. package/package.json +99 -0
  249. package/q +196 -0
  250. package/test-export/array-spec.d.ts +1 -0
  251. package/test-export/array-spec.js +204 -0
  252. package/test-export/bird-point-count-spec.d.ts +1 -0
  253. package/test-export/bird-point-count-spec.js +62 -0
  254. package/test-export/collection-contest-form-spec.d.ts +1 -0
  255. package/test-export/collection-contest-form-spec.js +38 -0
  256. package/test-export/dataset-form-spec.d.ts +1 -0
  257. package/test-export/dataset-form-spec.js +50 -0
  258. package/test-export/date-time-widget-spec.d.ts +1 -0
  259. package/test-export/date-time-widget-spec.js +188 -0
  260. package/test-export/geocoder-spec.d.ts +1 -0
  261. package/test-export/geocoder-spec.js +135 -0
  262. package/test-export/image-array-spec.d.ts +1 -0
  263. package/test-export/image-array-spec.js +94 -0
  264. package/test-export/inject-field-spec.d.ts +1 -0
  265. package/test-export/inject-field-spec.js +148 -0
  266. package/test-export/internal-uuids-spec.d.ts +1 -0
  267. package/test-export/internal-uuids-spec.js +157 -0
  268. package/test-export/invasive-species-eradication-np-spec.d.ts +1 -0
  269. package/test-export/invasive-species-eradication-np-spec.js +18 -0
  270. package/test-export/invasive-species-eradication-spec.d.ts +1 -0
  271. package/test-export/invasive-species-eradication-spec.js +25 -0
  272. package/test-export/line-transect-spec.d.ts +1 -0
  273. package/test-export/line-transect-spec.js +121 -0
  274. package/test-export/mobile-form-spec.d.ts +1 -0
  275. package/test-export/mobile-form-spec.js +84 -0
  276. package/test-export/nafi-spec.d.ts +1 -0
  277. package/test-export/nafi-spec.js +85 -0
  278. package/test-export/select-widget-spec.d.ts +1 -0
  279. package/test-export/select-widget-spec.js +68 -0
  280. package/test-export/single-item-array-field-spec.d.ts +1 -0
  281. package/test-export/single-item-array-field-spec.js +92 -0
  282. package/test-export/syke-butterfly-spec.d.ts +1 -0
  283. package/test-export/syke-butterfly-spec.js +163 -0
  284. package/test-export/test-utils.d.ts +184 -0
  285. package/test-export/test-utils.js +354 -0
  286. package/test-export/transaction-form-spec.d.ts +1 -0
  287. package/test-export/transaction-form-spec.js +63 -0
  288. package/test-export/trip-report-autosuggest-spec.d.ts +1 -0
  289. package/test-export/trip-report-autosuggest-spec.js +272 -0
  290. package/test-export/trip-report-spec.d.ts +1 -0
  291. package/test-export/trip-report-spec.js +456 -0
  292. package/test-export/unit-list-shorthand-array-field-spec.d.ts +1 -0
  293. package/test-export/unit-list-shorthand-array-field-spec.js +71 -0
  294. package/test-export/validation-spec.d.ts +1 -0
  295. package/test-export/validation-spec.js +336 -0
  296. package/test-export/water-bird-spec.d.ts +1 -0
  297. package/test-export/water-bird-spec.js +30 -0
  298. package/test-export/wbc-spec.d.ts +1 -0
  299. package/test-export/wbc-spec.js +82 -0
  300. package/tsconfig.json +25 -0
  301. package/tsconfig.lib.json +11 -0
  302. package/tsconfig.test.json +10 -0
@@ -0,0 +1,1127 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __rest = (this && this.__rest) || function (s, e) {
9
+ var t = {};
10
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
11
+ t[p] = s[p];
12
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
13
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
14
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
15
+ t[p[i]] = s[p[i]];
16
+ }
17
+ return t;
18
+ };
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.Autosuggest = void 0;
21
+ const React = require("react");
22
+ const react_dom_1 = require("react-dom");
23
+ const PropTypes = require("prop-types");
24
+ const Spinner = require("react-spinner");
25
+ const utils_1 = require("../../utils");
26
+ const components_1 = require("../components");
27
+ const ReactContext_1 = require("../../ReactContext");
28
+ const InformalTaxonGroupChooserWidget_1 = require("./InformalTaxonGroupChooserWidget");
29
+ function renderFlag(suggestion, prepend) {
30
+ return (suggestion && suggestion.payload || {}).finnish
31
+ ? React.createElement(React.Fragment, null,
32
+ prepend || null,
33
+ React.createElement("img", { src: "https://cdn.laji.fi/images/icons/flag_fi_small.png", width: "16" }))
34
+ : null;
35
+ }
36
+ class _AutosuggestWidget extends React.Component {
37
+ render() {
38
+ if (this.props.options) {
39
+ switch (this.props.options.autosuggestField) {
40
+ case "taxon":
41
+ return React.createElement(TaxonAutosuggestWidget, Object.assign({}, this.props));
42
+ case "unit":
43
+ return React.createElement(UnitAutosuggestWidget, Object.assign({}, this.props));
44
+ case "friends":
45
+ case "person":
46
+ return React.createElement(FriendsAutosuggestWidget, Object.assign({}, this.props));
47
+ case "organization":
48
+ return React.createElement(OrganizationAutosuggestWidget, Object.assign({}, this.props));
49
+ default:
50
+ return React.createElement(RangeAutosuggestWidget, Object.assign({}, this.props));
51
+ }
52
+ }
53
+ return React.createElement(Autosuggest, Object.assign({}, this.props));
54
+ }
55
+ formatValue(value, options, parentProps) {
56
+ if (options) {
57
+ let component = undefined;
58
+ switch (options.autosuggestField) {
59
+ case "taxon":
60
+ component = TaxonAutosuggestWidget;
61
+ break;
62
+ case "unit":
63
+ component = UnitAutosuggestWidget;
64
+ break;
65
+ case "friends":
66
+ case "person":
67
+ component = FriendsAutosuggestWidget;
68
+ break;
69
+ case "organization":
70
+ component = OrganizationAutosuggestWidget;
71
+ break;
72
+ default:
73
+ component = RangeAutosuggestWidget;
74
+ }
75
+ if (component) {
76
+ return React.createElement(SimpleValueRenderer, { component: component, value: value, formContext: parentProps.formContext });
77
+ }
78
+ }
79
+ }
80
+ }
81
+ exports.default = _AutosuggestWidget;
82
+ _AutosuggestWidget.propTypes = {
83
+ schema: PropTypes.shape({
84
+ type: PropTypes.oneOf(["string"])
85
+ }).isRequired,
86
+ value: PropTypes.string
87
+ };
88
+ class SimpleValueRenderer extends React.Component {
89
+ constructor(props) {
90
+ super(props);
91
+ this.state = { inputValue: this.props.value, loading: true };
92
+ }
93
+ componentDidMount() {
94
+ const { getSuggestionFromValue, isValueSuggested } = this.props.component.prototype;
95
+ if (getSuggestionFromValue && isValueSuggested) {
96
+ this.isValueSuggested = isValueSuggested.bind(this);
97
+ getSuggestionFromValue.call(this, this.props.value).then((suggestion) => {
98
+ this.setState({ inputValue: suggestion.value, loading: false });
99
+ }).catch(() => this.setState({ loading: false }));
100
+ }
101
+ }
102
+ render() {
103
+ return this.state.loading ? React.createElement(Spinner, null) : React.createElement("span", null, this.state.inputValue);
104
+ }
105
+ }
106
+ function TaxonAutosuggest(ComposedComponent) {
107
+ var _a;
108
+ return _a = class TaxonAutosuggestWidget extends ComposedComponent {
109
+ constructor(props) {
110
+ super(props);
111
+ this.renderSuccessGlyph = () => {
112
+ const { Glyphicon } = this.context.theme;
113
+ return React.createElement(Glyphicon, { style: { pointerEvents: "none" }, glyph: "ok", className: "form-control-feedback" });
114
+ };
115
+ this.parseChooseImages = (chooseImages) => {
116
+ return chooseImages.map(taxonIDOrObj => typeof taxonIDOrObj === "string" ? { id: taxonIDOrObj } : taxonIDOrObj);
117
+ };
118
+ this.renderChooseImages = () => {
119
+ const chooseImages = this.state && this.state.chooseImages || this.props.options.chooseImages;
120
+ const { orWriteSpeciesNameLabel } = utils_1.getUiOptions(this.props);
121
+ const { or } = this.props.formContext.translations;
122
+ const { Row, Col } = this.context.theme;
123
+ return (React.createElement(Row, null,
124
+ React.createElement(Col, { xs: 12 },
125
+ React.createElement("div", { className: "laji-form-medias" }, this.parseChooseImages(chooseImages).map(taxonIDObj => React.createElement(TaxonImgChooser, { id: taxonIDObj.id, key: taxonIDObj.id, url: taxonIDObj.url, onSelect: this.onTaxonImgSelected, formContext: this.props.formContext })))),
126
+ React.createElement(Col, { xs: 12 },
127
+ React.createElement("label", null,
128
+ or,
129
+ " ",
130
+ orWriteSpeciesNameLabel || this.props.formContext.translations.orWriteSpeciesName))));
131
+ };
132
+ this.onTaxonImgSelected = (taxonID, taxon) => {
133
+ this.autosuggestRef.selectSuggestion({
134
+ key: taxonID,
135
+ value: taxon.vernacularName,
136
+ payload: taxon
137
+ });
138
+ };
139
+ this.setAutosuggestRef = (elem) => {
140
+ this.autosuggestRef = elem;
141
+ };
142
+ this.getSuggestionFromValue = this.getSuggestionFromValue.bind(this);
143
+ this.isValueSuggested = this.isValueSuggested.bind(this);
144
+ if (super.renderSuggestion) {
145
+ this.renderSuggestion = super.renderSuggestion.bind(this);
146
+ }
147
+ else {
148
+ this.renderSuggestion = this.renderSuggestion.bind(this);
149
+ }
150
+ }
151
+ componentDidMount() {
152
+ this.mounted = true;
153
+ }
154
+ componentWillUnmount() {
155
+ this.mounted = false;
156
+ }
157
+ componentDidUpdate(prevProps) {
158
+ const { value, options = {} } = this.props;
159
+ if (value !== prevProps.value && options.getSuggestionFromValue && options.chooseImages) {
160
+ options.getSuggestionFromValue(value).then(suggestion => {
161
+ if (!this.mounted)
162
+ return;
163
+ const found = this.parseChooseImages(options.chooseImages).find(({ id }) => suggestion.key === id);
164
+ this.setState({ chooseImages: found ? [found] : undefined });
165
+ });
166
+ }
167
+ }
168
+ getSuggestionFromValue(value) {
169
+ if (this.isValueSuggested(value)) {
170
+ return this.props.formContext.apiClient.fetchCached(`/taxa/${value}`).then(({ vernacularName, scientificName }) => {
171
+ if (vernacularName !== undefined) {
172
+ return { value: vernacularName, key: value };
173
+ }
174
+ if (scientificName !== undefined) {
175
+ return { value: scientificName, key: value };
176
+ }
177
+ });
178
+ }
179
+ else {
180
+ return Promise.reject();
181
+ }
182
+ }
183
+ isValueSuggested(value) {
184
+ return !utils_1.isEmptyString(value) && !!value.match(/MX\.\d+/);
185
+ }
186
+ parseInputValue(inputValue) {
187
+ return inputValue.replace(/ sp(\.|p)?\.?$/, "");
188
+ }
189
+ renderSuggestion(suggestion) {
190
+ const renderedSuggestion = "autocompleteDisplayName" in suggestion
191
+ && React.createElement("span", { dangerouslySetInnerHTML: { __html: suggestion.autocompleteDisplayName } })
192
+ || React.createElement(React.Fragment, null,
193
+ suggestion.value,
194
+ renderFlag(suggestion));
195
+ return React.createElement("span", { className: "simple-option" }, renderedSuggestion);
196
+ }
197
+ render() {
198
+ const { props } = this;
199
+ const { options: propsOptions } = props, propsWithoutOptions = __rest(props, ["options"]);
200
+ const options = {
201
+ getSuggestionFromValue: this.getSuggestionFromValue,
202
+ isValueSuggested: this.isValueSuggested,
203
+ Wrapper: TaxonWrapper,
204
+ renderSuccessGlyph: this.renderSuccessGlyph,
205
+ renderSuggestion: this.renderSuggestion,
206
+ parseInputValue: this.parseInputValue
207
+ };
208
+ const _options = Object.assign(Object.assign(Object.assign(Object.assign({}, options), propsWithoutOptions), (propsOptions || {})), { query: Object.assign(Object.assign(Object.assign({}, (options.query || {})), (propsWithoutOptions.query || {})), (propsOptions.query || {})) });
209
+ if (propsOptions.chooseImages && !(props.value && props.formContext.uiSchemaContext.isEdit)) {
210
+ _options.renderExtra = this.renderChooseImages;
211
+ }
212
+ return React.createElement(Autosuggest, Object.assign({ ref: this.setAutosuggestRef }, _options));
213
+ }
214
+ },
215
+ _a.contextType = ReactContext_1.default,
216
+ _a;
217
+ }
218
+ let TaxonAutosuggestWidget = class TaxonAutosuggestWidget extends React.Component {
219
+ };
220
+ TaxonAutosuggestWidget = __decorate([
221
+ TaxonAutosuggest
222
+ ], TaxonAutosuggestWidget);
223
+ let UnitAutosuggestWidget = class UnitAutosuggestWidget extends React.Component {
224
+ constructor(props) {
225
+ super(props);
226
+ this.renderSuggestion = this.renderSuggestion.bind(this);
227
+ }
228
+ renderSuggestion(suggestion) {
229
+ const { count, maleIndividualCount, femaleIndividualCount } = suggestion.payload.interpretedFrom;
230
+ const [countElem, maleElem, femaleElem] = [count, maleIndividualCount, femaleIndividualCount].map(val => val && React.createElement("span", { className: "text-muted" }, val));
231
+ const taxonName = suggestion.payload.unit.identifications[0].taxon;
232
+ const name = suggestion.payload.isNonMatching
233
+ ? React.createElement("span", { className: "text-muted" },
234
+ taxonName,
235
+ " ",
236
+ React.createElement("i", null,
237
+ "(",
238
+ this.props.formContext.translations.unknownSpeciesName,
239
+ ")"))
240
+ : taxonName;
241
+ return React.createElement("span", null,
242
+ countElem,
243
+ countElem && " ",
244
+ name,
245
+ maleElem && " ",
246
+ maleElem,
247
+ femaleElem && " ",
248
+ femaleElem,
249
+ renderFlag(suggestion));
250
+ }
251
+ };
252
+ UnitAutosuggestWidget = __decorate([
253
+ TaxonAutosuggest
254
+ ], UnitAutosuggestWidget);
255
+ class FriendsAutosuggestWidget extends React.Component {
256
+ constructor(props) {
257
+ super(props);
258
+ this.prepareSuggestion = (suggestion) => {
259
+ const { isAdmin } = this.props.formContext.uiSchemaContext;
260
+ const { showID } = utils_1.getUiOptions(this.props);
261
+ return isAdmin && showID
262
+ ? Object.assign(Object.assign({}, suggestion), { value: `${suggestion.value} (${suggestion.key})` }) : suggestion;
263
+ };
264
+ this.findExactMatch = (suggestions, inputValue) => {
265
+ return suggestions.find(suggestion => (suggestion && suggestion.value.toLowerCase() === inputValue.trim().toLowerCase()));
266
+ };
267
+ this.renderSuccessGlyph = () => {
268
+ const { Glyphicon } = this.context.theme;
269
+ return (React.createElement(Glyphicon, { style: { pointerEvents: "none" }, glyph: "user", className: "form-control-feedback" }));
270
+ };
271
+ this.getSuggestionFromValue = this.getSuggestionFromValue.bind(this);
272
+ this.isValueSuggested = this.isValueSuggested.bind(this);
273
+ }
274
+ getSuggestionFromValue(value) {
275
+ const { showID } = utils_1.getUiOptions(this.props);
276
+ const { isAdmin } = this.props.formContext.uiSchemaContext;
277
+ if (this.isValueSuggested(value)) {
278
+ return this.props.formContext.apiClient.fetchCached(`/person/by-id/${value}`).then(({ fullName, group, id }) => {
279
+ if (fullName) {
280
+ const addGroup = str => group ? `${str} (${group})` : str;
281
+ const addID = str => isAdmin && showID ? `${str} (${id})` : str;
282
+ return {
283
+ value: addID(addGroup(fullName)),
284
+ key: value
285
+ };
286
+ }
287
+ });
288
+ }
289
+ else {
290
+ return Promise.reject();
291
+ }
292
+ }
293
+ isValueSuggested(value) {
294
+ return !utils_1.isEmptyString(value) && value.match(/MA\.\d+/);
295
+ }
296
+ render() {
297
+ const _a = this.props, { options: propsOptions } = _a, propsWithoutOptions = __rest(_a, ["options"]);
298
+ const options = {
299
+ query: Object.assign({ includeSelf: true }, propsOptions.queryOptions),
300
+ getSuggestionFromValue: this.getSuggestionFromValue,
301
+ isValueSuggested: this.isValueSuggested,
302
+ Wrapper: FriendsWrapper,
303
+ renderSuccessGlyph: this.renderSuccessGlyph,
304
+ findExactMatch: this.findExactMatch,
305
+ prepareSuggestion: this.prepareSuggestion
306
+ };
307
+ return React.createElement(Autosuggest, Object.assign({}, options, propsWithoutOptions, propsOptions));
308
+ }
309
+ }
310
+ FriendsAutosuggestWidget.contextType = ReactContext_1.default;
311
+ class OrganizationAutosuggestWidget extends React.Component {
312
+ constructor(props) {
313
+ super(props);
314
+ this.findExactMatch = (suggestions, inputValue) => {
315
+ return suggestions.find(suggestion => (suggestion && suggestion.value.toLowerCase() === inputValue.trim().toLowerCase()));
316
+ };
317
+ this.getSuggestionFromValue = this.getSuggestionFromValue.bind(this);
318
+ this.isValueSuggested = this.isValueSuggested.bind(this);
319
+ }
320
+ getSuggestionFromValue(value) {
321
+ if (this.isValueSuggested(value)) {
322
+ return this.props.formContext.apiClient.fetchCached(`/organization/by-id/${value}`).then(({ fullName }) => {
323
+ if (fullName) {
324
+ return {
325
+ value: fullName,
326
+ key: value
327
+ };
328
+ }
329
+ });
330
+ }
331
+ else {
332
+ return Promise.reject();
333
+ }
334
+ }
335
+ isValueSuggested(value) {
336
+ return !utils_1.isEmptyString(value) && value.match(/MOS\.\d+/);
337
+ }
338
+ render() {
339
+ const _a = this.props, { options: propsOptions } = _a, propsWithoutOptions = __rest(_a, ["options"]);
340
+ const options = {
341
+ query: Object.assign({ includeSelf: true }, propsOptions.queryOptions),
342
+ getSuggestionFromValue: this.getSuggestionFromValue,
343
+ isValueSuggested: this.isValueSuggested,
344
+ Wrapper: OrganizationWrapper,
345
+ findExactMatch: this.findExactMatch
346
+ };
347
+ return React.createElement(Autosuggest, Object.assign({}, options, propsWithoutOptions, propsOptions));
348
+ }
349
+ }
350
+ OrganizationAutosuggestWidget.contextType = ReactContext_1.default;
351
+ class RangeAutosuggestWidget extends React.Component {
352
+ render() {
353
+ const _a = this.props, { options: propsOptions } = _a, propsWithoutOptions = __rest(_a, ["options"]);
354
+ return React.createElement(Autosuggest, Object.assign({ highlightFirstSuggestion: true }, propsWithoutOptions, propsOptions));
355
+ }
356
+ }
357
+ class Autosuggest extends React.Component {
358
+ constructor(props) {
359
+ super(props);
360
+ this.isValueSuggested = (props) => {
361
+ const { isValueSuggested, suggestionReceive, onSuggestionSelected } = props;
362
+ if (!onSuggestionSelected && suggestionReceive !== "key")
363
+ return undefined;
364
+ return isValueSuggested ? isValueSuggested(props.value) : undefined;
365
+ };
366
+ this.wrapperRef = React.createRef();
367
+ this.keyFunctions = {
368
+ autosuggestToggle: () => {
369
+ if (this.props.onToggle) {
370
+ this.onToggle();
371
+ return true;
372
+ }
373
+ return false;
374
+ }
375
+ };
376
+ this.triggerConvert = (props) => {
377
+ const { value, getSuggestionFromValue } = props;
378
+ if (utils_1.isEmptyString(value) || !getSuggestionFromValue) {
379
+ if (this.state.suggestion && Object.keys(this.state.suggestion).length > 0) {
380
+ this.setState({ suggestion: undefined, inputValue: value, suggestionForValue: value });
381
+ }
382
+ return;
383
+ }
384
+ this.setState({ isLoading: true });
385
+ getSuggestionFromValue(value).then(suggestion => {
386
+ if (!this.mounted)
387
+ return;
388
+ this.setState({ suggestion, inputValue: this.getSuggestionValue(suggestion), isLoading: false, suggestionForValue: value });
389
+ }).catch(() => {
390
+ if (!this.mounted)
391
+ return;
392
+ this.setState({ isLoading: false });
393
+ });
394
+ };
395
+ this.getSuggestionValue = (suggestion) => {
396
+ const { getSuggestionValue } = this.props;
397
+ const def = suggestion.value;
398
+ return getSuggestionValue
399
+ ? getSuggestionValue(suggestion, def)
400
+ : def;
401
+ };
402
+ this.renderSuggestion = (suggestion) => {
403
+ let { renderSuggestion } = this.props;
404
+ if (!renderSuggestion)
405
+ renderSuggestion = suggestion => suggestion.value;
406
+ return (React.createElement("span", null, renderSuggestion(suggestion)));
407
+ };
408
+ this.selectSuggestion = (suggestion) => {
409
+ const { onSuggestionSelected, onChange, suggestionReceive } = this.props;
410
+ const afterStateChange = () => {
411
+ if (onSuggestionSelected) {
412
+ onSuggestionSelected(suggestion, this.mounted);
413
+ }
414
+ else {
415
+ if (this.mounted) {
416
+ this.setState({ suggestionForValue: suggestion[suggestionReceive] }, () => onChange(suggestion[suggestionReceive]));
417
+ }
418
+ else {
419
+ onChange(suggestion[suggestionReceive]);
420
+ }
421
+ }
422
+ };
423
+ const state = { suggestion, inputValue: this.getSuggestionValue(suggestion) };
424
+ this.mounted
425
+ ? this.setState(state, afterStateChange)
426
+ : afterStateChange();
427
+ };
428
+ this.selectUnsuggested = (value) => {
429
+ if (utils_1.isEmptyString(value) && utils_1.isEmptyString(this.props.value))
430
+ return;
431
+ const { onUnsuggestedSelected, onChange } = this.props;
432
+ const afterStateChange = () => {
433
+ onUnsuggestedSelected ?
434
+ onUnsuggestedSelected(value) :
435
+ onChange(value);
436
+ };
437
+ const state = { inputValue: value, suggestion: undefined, suggestionForValue: value };
438
+ this.mounted
439
+ ? this.setState(state, afterStateChange)
440
+ : afterStateChange();
441
+ };
442
+ this.onSuggestionSelected = (suggestion) => {
443
+ this.selectSuggestion(suggestion);
444
+ };
445
+ this.onUnsuggestedSelected = (inputValue) => {
446
+ this.selectUnsuggested(inputValue);
447
+ };
448
+ this.findExactMatch = (suggestions, inputValue = "") => {
449
+ if (!Array.isArray(suggestions))
450
+ suggestions = [suggestions];
451
+ const { findExactMatch } = this.props;
452
+ return findExactMatch
453
+ ? findExactMatch(suggestions, inputValue)
454
+ : suggestions.find(suggestion => (suggestion && suggestion.value.toLowerCase() === inputValue.trim().toLowerCase() && (!suggestion.payload || !suggestion.payload.isNonMatching)));
455
+ };
456
+ this.findTheOnlyOneMatch = (suggestions) => {
457
+ if (!Array.isArray(suggestions))
458
+ suggestions = [suggestions];
459
+ const filtered = suggestions.filter(suggestion => !suggestion || !suggestion.payload || !suggestion.payload.isNonMatching);
460
+ if (filtered.length === 1) {
461
+ return filtered[0];
462
+ }
463
+ };
464
+ this.findNonMatching = (suggestions) => {
465
+ if (!Array.isArray(suggestions))
466
+ suggestions = [suggestions];
467
+ const filtered = suggestions.filter(suggestion => suggestion && suggestion.payload && suggestion.payload.isNonMatching);
468
+ if (filtered.length === 1) {
469
+ return filtered[0];
470
+ }
471
+ };
472
+ this.onInputChange = (e, reason, callback) => {
473
+ let { value } = e.target;
474
+ if (this.props.inputProps && this.props.inputProps.onChange) {
475
+ e.persist && e.persist();
476
+ value = this.props.inputProps.onChange(e, reason, callback);
477
+ }
478
+ this.setState({ inputValue: value }, callback);
479
+ };
480
+ this.onSuggestionsFetchRequested = ({ value }, debounce = true) => {
481
+ if (value === undefined || value === null)
482
+ value = "";
483
+ value = this.props.parseInputValue ? this.props.parseInputValue(value) : value;
484
+ if (value.length < (this.props.minFetchLength !== undefined ? this.props.minFetchLength : 2)) {
485
+ this.setState({ suggestions: [] });
486
+ return;
487
+ }
488
+ const { autosuggestField, query = {} } = this.props;
489
+ this.setState({ isLoading: true });
490
+ const request = () => {
491
+ let timestamp = Date.now();
492
+ this.promiseTimestamp = timestamp;
493
+ this.apiClient.fetchCached("/autocomplete/" + autosuggestField, Object.assign({ q: value, includePayload: true, matchType: "exact,partial", includeHidden: false }, query)).then(suggestions => {
494
+ if (this.props.prepareSuggestion) {
495
+ suggestions = suggestions.map(s => this.props.prepareSuggestion(s));
496
+ }
497
+ if (timestamp !== this.promiseTimestamp) {
498
+ return;
499
+ }
500
+ this.mounted
501
+ ? this.setState({ isLoading: false, suggestions }, () => this.afterBlurAndFetch(suggestions))
502
+ : this.afterBlurAndFetch(suggestions);
503
+ }).catch(() => {
504
+ this.mounted
505
+ ? this.setState({ isLoading: false }, this.afterBlurAndFetch)
506
+ : this.afterBlurAndFetch();
507
+ });
508
+ };
509
+ if (this.timeout) {
510
+ clearTimeout(this.timeout);
511
+ }
512
+ if (debounce) {
513
+ this.timeout = this.props.formContext.setTimeout(request, 100);
514
+ }
515
+ else {
516
+ request();
517
+ }
518
+ };
519
+ this.onFocus = (e) => {
520
+ this.setState({ focused: true });
521
+ utils_1.triggerParentComponent("onFocus", e, this.props.inputProps);
522
+ };
523
+ this.onBlur = (e) => {
524
+ this.setState({ focused: false }, () => {
525
+ this._valueForBlurAndFetch = this.state.inputValue;
526
+ this.afterBlurAndFetch(this.state.suggestions);
527
+ utils_1.triggerParentComponent("onBlur", e, this.props.inputProps);
528
+ const overlay = this.wrapperRef.current;
529
+ if (overlay && overlay.overlayTriggerRef && overlay.overlayTriggerRef.hide) {
530
+ setTimeout(() => {
531
+ overlay && overlay.overlayTriggerRef && overlay.overlayTriggerRef.hide();
532
+ }, 1);
533
+ }
534
+ });
535
+ };
536
+ this.afterBlurAndFetch = (suggestions, callback) => {
537
+ const { inputValue = "" } = this.state;
538
+ const { _valueForBlurAndFetch = "" } = this;
539
+ if (this.mounted
540
+ && (this.state.focused || this._valueForBlurAndFetch === undefined || this.state.isLoading)
541
+ || (this.props.controlledValue && _valueForBlurAndFetch !== this.state.inputValue)) {
542
+ return;
543
+ }
544
+ const parsedInputValue = this.props.parseInputValue ? this.props.parseInputValue(inputValue) : inputValue;
545
+ const { selectOnlyOne, selectOnlyNonMatchingBeforeUnsuggested = true, informalTaxonGroups, informalTaxonGroupsValue, allowNonsuggestedValue } = this.props;
546
+ const exactMatch = this.findExactMatch(suggestions, parsedInputValue);
547
+ const onlyOneMatch = selectOnlyOne ? this.findTheOnlyOneMatch(suggestions) : undefined;
548
+ const nonMatching = selectOnlyNonMatchingBeforeUnsuggested ? this.findNonMatching(suggestions) : undefined;
549
+ const valueDidntChangeAndHasInformalTaxonGroup = this.props.value === inputValue && informalTaxonGroups && informalTaxonGroupsValue && informalTaxonGroupsValue.length;
550
+ if (this.highlightedSuggestionOnBlur) {
551
+ this.selectSuggestion(this.highlightedSuggestionOnBlur);
552
+ }
553
+ else if (onlyOneMatch) {
554
+ this.selectSuggestion(onlyOneMatch);
555
+ }
556
+ else if (exactMatch) {
557
+ this.selectSuggestion(Object.assign(Object.assign({}, exactMatch), { value: inputValue }));
558
+ }
559
+ else if (nonMatching && !valueDidntChangeAndHasInformalTaxonGroup) {
560
+ this.selectSuggestion(nonMatching);
561
+ }
562
+ else if (!valueDidntChangeAndHasInformalTaxonGroup && allowNonsuggestedValue) {
563
+ this.selectUnsuggested(parsedInputValue);
564
+ }
565
+ else if (!allowNonsuggestedValue) {
566
+ this.setState({ inputValue: "" }, () => this.props.onChange && this.props.onChange(""));
567
+ }
568
+ callback && callback();
569
+ };
570
+ this.setRef = (elem) => {
571
+ this.autosuggestRef = elem;
572
+ };
573
+ this.onInformalTaxonGroupsOpened = (open) => {
574
+ this.setState({ informalTaxonGroupsOpen: open });
575
+ };
576
+ this.onInformalTaxonGroupSelected = (id) => {
577
+ this.setState({ informalTaxonGroupsOpen: false });
578
+ this.props.onInformalTaxonGroupSelected && this.props.onInformalTaxonGroupSelected(id);
579
+ };
580
+ this.onInformalTaxonGroupHide = () => {
581
+ this.setState({ informalTaxonGroupsOpen: false });
582
+ };
583
+ this.onToggle = () => {
584
+ if (!this.mounted)
585
+ return;
586
+ this.props.onToggle(!this.props.toggled);
587
+ setTimeout(() => this.props.formContext.utils.focusById(this.props.id), 1); // Refocus input
588
+ };
589
+ this.isSuggested = () => {
590
+ const { suggestion } = this.state;
591
+ return !!suggestion && this.isValueSuggested(this.props);
592
+ };
593
+ this.renderInput = (inputProps) => {
594
+ let { value, renderSuccessGlyph, informalTaxonGroups, renderInformalTaxonGroupSelector = true, taxonGroupID, onToggle, displayValidationState = true, Wrapper } = this.props;
595
+ let validationState = null;
596
+ const { translations, lang } = this.props.formContext;
597
+ const { suggestion } = this.state;
598
+ const { Glyphicon } = this.context.theme;
599
+ const isSuggested = this.isSuggested();
600
+ if (displayValidationState && !utils_1.isEmptyString(value) && isSuggested !== undefined) {
601
+ validationState = isSuggested ? "success" : "warning";
602
+ }
603
+ const getGlyphNameFromState = (state) => {
604
+ switch (state) {
605
+ case "success":
606
+ return "ok";
607
+ case "warning":
608
+ return "warning-sign";
609
+ case "error":
610
+ return "remove";
611
+ default:
612
+ return "";
613
+ }
614
+ };
615
+ const getGlyph = (state) => {
616
+ if (!displayValidationState) {
617
+ return null;
618
+ }
619
+ const glyph = getGlyphNameFromState(state);
620
+ return glyph ? (React.createElement(Glyphicon, { key: glyph, style: { pointerEvents: "none" }, glyph: glyph, className: "form-control-feedback" })) : null;
621
+ };
622
+ let glyph = undefined;
623
+ if (!this.state.focused && !this.state.isLoading && (!onToggle || !this.state.focused)) {
624
+ glyph = (validationState === "success" && renderSuccessGlyph) ?
625
+ renderSuccessGlyph(value) : getGlyph(validationState);
626
+ }
627
+ const addon = informalTaxonGroups && renderInformalTaxonGroupSelector
628
+ ? React.createElement(InformalTaxonGroupsAddon, { key: "informal", taxonGroupID: taxonGroupID, onClear: this.onInformalTaxonGroupSelected, open: this.state.informalTaxonGroupsOpen, onOpen: this.onInformalTaxonGroupsOpened, onToggle: onToggle, formContext: this.props.formContext })
629
+ : null;
630
+ const getTogglerTooltip = () => {
631
+ const { toggleable } = utils_1.getUiOptions(this.props.uiSchema);
632
+ let tooltip = typeof toggleable.tooltip === "string"
633
+ ? toggleable.tooltip
634
+ : `${translations[this.props.toggled ? "StopShorthand" : "StartShorthand"]}. ${translations.ShorthandHelp}`;
635
+ if (tooltip === "") {
636
+ return tooltip;
637
+ }
638
+ const { shortcuts } = this.props.formContext.services.keyHandler;
639
+ Object.keys(shortcuts).some(keyCombo => {
640
+ if (shortcuts[keyCombo].fn == "autosuggestToggle") {
641
+ tooltip = `[${utils_1.stringifyKeyCombo(keyCombo)}]: ${tooltip}`;
642
+ return true;
643
+ }
644
+ });
645
+ return tooltip;
646
+ };
647
+ const getToggleGlyph = () => {
648
+ const { toggleable } = utils_1.getUiOptions(this.props.uiSchema);
649
+ const props = {
650
+ className: utils_1.classNames("autosuggest-input-addon", "power-user-addon", this.props.toggled && "active"),
651
+ onMouseDown: this.onToggle,
652
+ onKeyDown: this.onToggleByKeyboard
653
+ };
654
+ if (toggleable && toggleable.glyphClass) {
655
+ return (React.createElement(components_1.Button, Object.assign({}, props),
656
+ React.createElement("span", { className: toggleable.glyphClass })));
657
+ }
658
+ return React.createElement(components_1.GlyphButton, Object.assign({ glyph: "flash" }, props));
659
+ };
660
+ const toggler = onToggle
661
+ ? (React.createElement(components_1.TooltipComponent, { tooltip: getTogglerTooltip(), key: "toggler" }, getToggleGlyph())) : null;
662
+ const { inputValue = "" } = this.state;
663
+ const input = (React.createElement(components_1.FetcherInput, Object.assign({ value: inputValue, glyph: glyph, loading: this.state.isLoading, validationState: validationState, extra: [addon, toggler] }, inputProps)));
664
+ let component = input;
665
+ if (displayValidationState && Wrapper) {
666
+ component = (React.createElement(Wrapper, { isSuggested: isSuggested, suggestion: suggestion, options: utils_1.getUiOptions(this.props), id: this.props.id, value: suggestion && suggestion.key, inputValue: value, ref: this.wrapperRef, formContext: this.props.formContext }, component));
667
+ }
668
+ if (informalTaxonGroups) {
669
+ component = (React.createElement(React.Fragment, null,
670
+ component,
671
+ this.state.informalTaxonGroupsOpen && React.createElement(InformalTaxonGroupChooserWidget_1.InformalTaxonGroupChooser, { modal: true, onHide: this.onInformalTaxonGroupHide, onSelected: this.onInformalTaxonGroupSelected, formContext: this.props.formContext, lang: lang })));
672
+ }
673
+ return component;
674
+ };
675
+ const isSuggested = this.isValueSuggested(props);
676
+ this.state = {
677
+ isLoading: false,
678
+ suggestions: [],
679
+ focused: false,
680
+ inputValue: props.value !== undefined ? props.value : "",
681
+ suggestion: isSuggested ? {} : undefined,
682
+ };
683
+ this.apiClient = this.props.formContext.apiClient;
684
+ }
685
+ componentDidMount() {
686
+ this.mounted = true;
687
+ this.triggerConvert(this.props);
688
+ this.props.formContext.services.keyHandler.addKeyHandler(this.props.id, this.keyFunctions);
689
+ }
690
+ componentWillUnmount() {
691
+ this.mounted = false;
692
+ this.props.formContext.services.keyHandler.removeKeyHandler(this.props.id, this.keyFunctions);
693
+ }
694
+ componentDidUpdate(prevProps) {
695
+ if (!this.props.controlledValue && this.state.suggestion && this.props && prevProps.value !== this.props.value && this.props.value !== this.state.suggestionForValue) {
696
+ this.props.getSuggestionFromValue(this.props.value).then(suggestion => {
697
+ this.setState({ inputValue: this.getSuggestionValue(suggestion), suggestion });
698
+ }, () => {
699
+ this.setState({ inputValue: "", suggestion: undefined });
700
+ });
701
+ }
702
+ }
703
+ render() {
704
+ const { props } = this;
705
+ let { suggestions, inputValue = "" } = this.state;
706
+ const inputProps = Object.assign(Object.assign({ id: this.props.id, value: inputValue, readonly: props.readonly, disabled: props.disabled, placeholder: props.placeholder }, (this.props.inputProps || {})), { onChange: this.onInputChange, onBlur: this.onBlur, onFocus: this.onFocus });
707
+ let cssClasses = {
708
+ suggestionsContainer: "rw-popup-container rw-popup-transition",
709
+ suggestionsContainerOpen: "rw-popup",
710
+ suggestionsList: "rw-list",
711
+ suggestion: "rw-list-option",
712
+ suggestionHighlighted: "rw-list-option rw-state-focus rw-state-selected"
713
+ };
714
+ const highlightFirstSuggestion = "highlightFirstSuggestion" in this.props
715
+ ? this.props.highlightFirstSuggestion
716
+ : !this.props.allowNonsuggestedValue;
717
+ const { renderExtra } = props;
718
+ return (React.createElement(React.Fragment, null,
719
+ renderExtra && renderExtra(),
720
+ React.createElement("div", { className: utils_1.classNames("autosuggest-wrapper", props.wrapperClassName) },
721
+ React.createElement(ReactAutosuggest, { id: `${this.props.id}-autosuggest`, inputProps: inputProps, renderInputComponent: this.renderInput, suggestions: suggestions, renderSuggestion: this.renderSuggestion, onSuggestionsFetchRequested: this.onSuggestionsFetchRequested, onSuggestionsClearRequested: this.onSuggestionsClearRequested, onSuggestionSelected: this.onSuggestionSelected, onUnsuggestedSelected: this.onUnsuggestedSelected, highlightFirstSuggestion: highlightFirstSuggestion, suggestionsOpenOnFocus: !this.isSuggested(), theme: cssClasses, formContext: this.props.formContext, ref: this.setRef }))));
722
+ }
723
+ }
724
+ exports.Autosuggest = Autosuggest;
725
+ Autosuggest.contextType = ReactContext_1.default;
726
+ Autosuggest.propTypes = {
727
+ autosuggestField: PropTypes.string,
728
+ allowNonsuggestedValue: PropTypes.bool,
729
+ onSuggestionSelected: PropTypes.func,
730
+ onUnsuggestedSelected: PropTypes.func,
731
+ onInputChange: PropTypes.func,
732
+ uiSchema: PropTypes.object,
733
+ informalTaxonGroups: PropTypes.string,
734
+ onInformalTaxonGroupSelected: PropTypes.func
735
+ };
736
+ Autosuggest.defaultProps = {
737
+ allowNonsuggestedValue: true,
738
+ suggestionReceive: "key"
739
+ };
740
+ class _TaxonWrapper extends React.Component {
741
+ constructor(props) {
742
+ super(props);
743
+ this.state = { converted: false };
744
+ }
745
+ componentDidMount() {
746
+ this.mounted = true;
747
+ this.fetch(this.props.value);
748
+ }
749
+ componentWillUnmount() {
750
+ this.mounted = false;
751
+ }
752
+ UNSAFE_componentWillReceiveProps({ value }) {
753
+ this.fetch(value);
754
+ }
755
+ fetch(value) {
756
+ if (!value) {
757
+ this.setState({ scientificName: "", cursiveName: false });
758
+ }
759
+ else {
760
+ this.props.formContext.apiClient.fetchCached(`/taxa/${value}`).then(({ scientificName, cursiveName, vernacularName, taxonRank, informalTaxonGroups, finnish }) => {
761
+ if (!this.mounted)
762
+ return;
763
+ this.setState({ value, taxonRank, informalTaxonGroups, taxon: { scientificName, vernacularName, cursiveName, finnish } });
764
+ InformalTaxonGroupChooserWidget_1.getInformalGroups(this.props.formContext.apiClient).then(({ informalTaxonGroupsById }) => {
765
+ if (!this.mounted)
766
+ return;
767
+ this.setState({ informalTaxonGroupsById });
768
+ });
769
+ });
770
+ this.props.formContext.apiClient.fetchCached(`/taxa/${value}/parents`).then(parents => {
771
+ if (!this.mounted)
772
+ return;
773
+ const state = { order: undefined, family: undefined };
774
+ for (let parent of parents) {
775
+ const { vernacularName, scientificName, cursiveName } = parent;
776
+ if (parent.taxonRank === "MX.order") {
777
+ state.order = { vernacularName, scientificName, cursiveName };
778
+ }
779
+ else if (parent.taxonRank === "MX.family") {
780
+ state.family = { vernacularName, scientificName, cursiveName };
781
+ }
782
+ if (state.order && state.family) {
783
+ this.setState(state);
784
+ break;
785
+ }
786
+ }
787
+ this.setState(Object.assign(Object.assign({}, state), { higherThanOrder: !state.order && !state.family }));
788
+ });
789
+ this.props.formContext.apiClient.fetchCached("/metadata/ranges/MX.taxonRankEnum").then(taxonRanks => {
790
+ if (!this.mounted)
791
+ return;
792
+ this.setState({ taxonRanks: utils_1.dictionarify(taxonRanks, function getKey(rank) { return rank.id; }, function getValue(rank) { return rank.value; }) });
793
+ });
794
+ }
795
+ }
796
+ render() {
797
+ const { id, formContext, value, children, placement, inputValue, isSuggested } = this.props;
798
+ const { taxon = {}, taxonRanks, taxonRank, order, family, higherThanOrder, informalTaxonGroupsById = {}, informalTaxonGroups = [] } = this.state;
799
+ const { Popover, Tooltip } = this.context.theme;
800
+ const tooltipElem = (React.createElement(Tooltip, { id: `${id}-popover-tooltip` }, formContext.translations.OpenSpeciedCard));
801
+ let imageID = informalTaxonGroups[0];
802
+ if (informalTaxonGroupsById[imageID] && informalTaxonGroupsById[imageID].parent) {
803
+ imageID = informalTaxonGroupsById[imageID].parent.id;
804
+ }
805
+ const loading = !taxonRank || !(order || family || higherThanOrder) || !taxonRanks;
806
+ const popover = utils_1.isEmptyString(inputValue)
807
+ ? React.createElement(React.Fragment, null)
808
+ : inputValue && isSuggested === false
809
+ ? React.createElement(Tooltip, { id: `${this.props.id}-tooltip` }, this.props.formContext.translations.UnknownName)
810
+ : (React.createElement(Popover, { id: `${id}-popover` },
811
+ React.createElement("div", { className: `laji-form taxon-popover informal-group-image ${imageID}` },
812
+ React.createElement("div", null,
813
+ React.createElement(ReactContext_1.default.Provider, { value: this.context },
814
+ React.createElement(components_1.OverlayTrigger, { overlay: tooltipElem },
815
+ React.createElement("a", { href: `http://tun.fi/${value}`, target: "_blank", rel: "noopener noreferrer" },
816
+ React.createElement(TaxonName, Object.assign({}, taxon)),
817
+ React.createElement("br", null)))),
818
+ React.createElement("strong", null,
819
+ formContext.translations.taxonomicRank,
820
+ ":"),
821
+ " ",
822
+ taxonRanks && taxonRank ? taxonRanks[taxonRank] : "",
823
+ React.createElement("br", null),
824
+ !higherThanOrder ? (React.createElement(React.Fragment, null,
825
+ React.createElement("strong", null,
826
+ formContext.translations.taxonGroups,
827
+ ":"),
828
+ React.createElement("ul", null,
829
+ order && React.createElement("li", null,
830
+ React.createElement(TaxonName, Object.assign({}, order))),
831
+ family && React.createElement("li", null,
832
+ React.createElement(TaxonName, Object.assign({}, family)))))) : React.createElement(React.Fragment, null,
833
+ React.createElement("br", null),
834
+ React.createElement("br", null))),
835
+ loading && React.createElement(Spinner, null))));
836
+ return (React.createElement(components_1.OverlayTrigger, { hoverable: true, placement: placement, contextId: this.props.formContext.contextId, overlay: popover, ref: this.props.overlayRef, formContext: this.props.formContext }, children));
837
+ }
838
+ }
839
+ _TaxonWrapper.contextType = ReactContext_1.default;
840
+ const TaxonWrapper = React.forwardRef((props, ref) => React.createElement(_TaxonWrapper, Object.assign({}, props, { overlayRef: ref })));
841
+ class InformalTaxonGroupsAddon extends React.Component {
842
+ constructor(props) {
843
+ super(props);
844
+ this.onClear = (e) => {
845
+ e.stopPropagation();
846
+ if (this.props.onClear)
847
+ this.props.onClear(undefined);
848
+ };
849
+ this.toggle = () => {
850
+ if (this.props.onOpen)
851
+ this.props.onOpen(!this.props.open);
852
+ };
853
+ this.onKeyDown = this.props.formContext.utils.keyboardClick(this.toggle);
854
+ this.renderGlyph = () => {
855
+ const { taxonGroupID } = this.props;
856
+ let imageID = taxonGroupID;
857
+ const { informalTaxonGroupsById = {} } = this.state;
858
+ if (informalTaxonGroupsById[taxonGroupID] && informalTaxonGroupsById[taxonGroupID].parent) {
859
+ imageID = informalTaxonGroupsById[taxonGroupID].parent.id;
860
+ }
861
+ const buttonProps = {
862
+ onClick: this.toggle,
863
+ onKeyDown: this.onKeyDown
864
+ };
865
+ return taxonGroupID
866
+ ? (React.createElement("span", { className: "btn btn-default informal-taxon-group-chooser-addon active" },
867
+ React.createElement("div", null,
868
+ React.createElement("span", Object.assign({}, buttonProps, { className: `informal-group-image ${imageID}` })),
869
+ React.createElement("button", { className: "close", onClick: this.onClear }, "\u00D7")))) : (React.createElement(components_1.GlyphButton, Object.assign({}, buttonProps, { glyph: "menu-hamburger", className: "autosuggest-input-addon informal-taxon-group-chooser" })));
870
+ };
871
+ this.state = {};
872
+ }
873
+ componentDidMount() {
874
+ this.mounted = true;
875
+ InformalTaxonGroupChooserWidget_1.getInformalGroups(this.props.formContext.apiClient).then(({ informalTaxonGroupsById }) => {
876
+ if (!this.mounted)
877
+ return;
878
+ this.setState({ informalTaxonGroupsById });
879
+ });
880
+ }
881
+ componentWillUnmount() {
882
+ this.mounted = false;
883
+ }
884
+ render() {
885
+ if (!this.onKeyDown) { // Context not available before first render, so we initialize the key handler here.
886
+ this.onKeyDown = this.context.utils.keyboardClick(this.toggle);
887
+ }
888
+ return (React.createElement(components_1.TooltipComponent, { tooltip: this.props.taxonGroupID && this.state.informalTaxonGroupsById ? this.state.informalTaxonGroupsById[this.props.taxonGroupID].name : this.props.formContext.translations.PickInformalTaxonGroup }, this.renderGlyph()));
889
+ }
890
+ }
891
+ InformalTaxonGroupsAddon.contextType = ReactContext_1.default;
892
+ class TaxonImgChooser extends React.Component {
893
+ constructor(props) {
894
+ super(props);
895
+ this.showModal = () => {
896
+ this.setState({ modal: true });
897
+ };
898
+ this.hideModal = () => {
899
+ this.setState({ modal: false });
900
+ };
901
+ this.onSelected = () => {
902
+ this.props.onSelect(this.props.id, this.state.taxon);
903
+ this.hideModal();
904
+ };
905
+ this.state = {};
906
+ }
907
+ componentDidMount() {
908
+ this.mounted = true;
909
+ this.props.formContext.apiClient.fetchCached(`/taxa/${this.props.id}`, { includeMedia: true }).then(taxon => {
910
+ if (!this.mounted)
911
+ return;
912
+ if (taxon.multimedia && taxon.multimedia.length) {
913
+ const [media] = taxon.multimedia;
914
+ this.setState({
915
+ taxon: taxon,
916
+ thumbnail: this.props.url || media.squareThumbnailURL || media.thumbnailURL,
917
+ large: this.props.url || media.largeURL
918
+ });
919
+ }
920
+ else {
921
+ this.setState({ taxon });
922
+ }
923
+ });
924
+ }
925
+ componentWillUnmount() {
926
+ this.mounted = false;
927
+ }
928
+ render() {
929
+ const { thumbnail, taxon, modal } = this.state;
930
+ const { translations } = this.props.formContext;
931
+ const { Modal } = this.context.theme;
932
+ return (React.createElement("div", { className: "laji-form-medias" },
933
+ React.createElement("div", { className: "taxon-img media-container interactive", style: { backgroundImage: `url(${thumbnail})` }, onClick: this.showModal, tabIndex: 0 },
934
+ !taxon && React.createElement("div", { className: "media-loading" },
935
+ React.createElement(Spinner, null)),
936
+ React.createElement("span", null, taxon && taxon.vernacularName || "")),
937
+ modal &&
938
+ React.createElement(Modal, { dialogClassName: "laji-form media-modal", show: true, onHide: this.hideModal },
939
+ React.createElement(Modal.Body, null,
940
+ React.createElement("img", { src: this.state.large }),
941
+ React.createElement("div", null,
942
+ React.createElement("h3", { className: "text-center" },
943
+ React.createElement(TaxonName, Object.assign({}, this.state.taxon, { finnish: false }))),
944
+ React.createElement(components_1.Button, { block: true, onClick: this.onSelected }, translations.Select),
945
+ React.createElement(components_1.Button, { block: true, onClick: this.hideModal }, translations.Cancel))))));
946
+ }
947
+ }
948
+ TaxonImgChooser.contextType = ReactContext_1.default;
949
+ const TaxonName = ({ scientificName, vernacularName = "", cursiveName, finnish }) => {
950
+ const _scientificName = vernacularName && scientificName
951
+ ? `(${scientificName})`
952
+ : (scientificName || "");
953
+ return (React.createElement(React.Fragment, null,
954
+ `${vernacularName}${vernacularName ? " " : ""}`,
955
+ cursiveName ? React.createElement("i", null, _scientificName) : _scientificName,
956
+ renderFlag({ payload: { finnish } }, " ")));
957
+ };
958
+ class ReactAutosuggest extends React.Component {
959
+ constructor(props) {
960
+ super(props);
961
+ this.onInputFocus = (e) => {
962
+ this.setState({ focused: true, hideSuggestions: false });
963
+ this.requestFetch(this.state.inputValue);
964
+ this.props.inputProps && this.props.inputProps.onFocus && this.props.inputProps.onFocus(e);
965
+ };
966
+ this.onInputTryBlur = (e) => {
967
+ if (this.suggestionMouseDownFlag) {
968
+ return;
969
+ }
970
+ this.onBlur(e);
971
+ };
972
+ this.onListBlur = (e) => {
973
+ this.onBlur(e);
974
+ };
975
+ this.onInputKeyDown = (e) => {
976
+ let state, suggestion;
977
+ const { shortcuts } = this.props.formContext.services.keyHandler;
978
+ switch (e.key) {
979
+ case "ArrowDown":
980
+ e.preventDefault();
981
+ if (this.state.focusedIdx >= (this.props.suggestions || []).length - 1) {
982
+ break;
983
+ }
984
+ state = {
985
+ focusedIdx: typeof this.state.focusedIdx === "number"
986
+ ? this.state.focusedIdx + 1
987
+ : (this.props.suggestions || []).length
988
+ ? 0
989
+ : undefined,
990
+ touched: true
991
+ };
992
+ if (state.focusedIdx !== undefined) {
993
+ state.inputValue = this.props.suggestions[state.focusedIdx].value;
994
+ }
995
+ this.setState(state);
996
+ break;
997
+ case "ArrowUp":
998
+ e.preventDefault();
999
+ state = { focusedIdx: this.state.focusedIdx > 0 ? this.state.focusedIdx - 1 : undefined, touched: true };
1000
+ if (state.focusedIdx !== undefined) {
1001
+ state.inputValue = this.props.suggestions[state.focusedIdx].value;
1002
+ }
1003
+ this.setState(state);
1004
+ break;
1005
+ case "Enter":
1006
+ e.preventDefault();
1007
+ suggestion = (this.props.suggestions || [])[this.state.focusedIdx];
1008
+ if (shortcuts.Enter) {
1009
+ this.props.formContext.setTimeout(() => {
1010
+ suggestion && this.onSuggestionSelected(suggestion);
1011
+ }, 0);
1012
+ }
1013
+ else {
1014
+ this.inputElem.blur();
1015
+ }
1016
+ break;
1017
+ case "Control":
1018
+ case "Meta":
1019
+ case "Alt":
1020
+ case "Shift":
1021
+ case "CapsLock":
1022
+ break;
1023
+ default:
1024
+ this.setState({ touched: true });
1025
+ }
1026
+ this.props.inputProps && this.props.inputProps.onKeyDown && this.props.inputProps.onKeyDown(e);
1027
+ };
1028
+ this.onInputChange = (e) => {
1029
+ this._onInputChange(e.target.value, "keystroke");
1030
+ };
1031
+ this._onInputChange = (value, reason) => {
1032
+ const callback = reason === "click"
1033
+ ? () => { }
1034
+ : () => this.requestFetch(this.state.inputValue);
1035
+ this.props.inputProps && this.props.inputProps.onChange
1036
+ ? this.props.inputProps.onChange({ target: { value } }, reason, callback)
1037
+ : this.setState({ inputValue: value }, callback);
1038
+ };
1039
+ this.setInputRef = (elem) => {
1040
+ this.inputElem = react_dom_1.findDOMNode(elem);
1041
+ };
1042
+ this.onSuggestionMouseDown = () => {
1043
+ this.suggestionMouseDownFlag = true;
1044
+ };
1045
+ this.onSuggestionMouseUp = (e) => {
1046
+ this.suggestionMouseDownFlag = false;
1047
+ const suggestion = this.getSuggestionFromClick(e);
1048
+ this.setState({ inputValue: suggestion.value }, () => {
1049
+ this._onInputChange(suggestion.value, "click");
1050
+ this.onBlur(e);
1051
+ });
1052
+ };
1053
+ this.getSuggestionFromClick = ({ target }) => {
1054
+ let idx;
1055
+ while (typeof idx !== "string") {
1056
+ idx = target.getAttribute("data-idx");
1057
+ target = target.parentElement;
1058
+ }
1059
+ return this.props.suggestions[idx];
1060
+ };
1061
+ this.listRef = React.createRef();
1062
+ this.state = {
1063
+ inputValue: props.inputProps.value
1064
+ };
1065
+ }
1066
+ UNSAFE_componentWillReceiveProps(props) {
1067
+ if ("value" in props.inputProps) {
1068
+ this.setState({ inputValue: props.inputProps.value });
1069
+ }
1070
+ }
1071
+ render() {
1072
+ return (React.createElement("div", { onFocus: this.onContainerFocus, onBlur: this.onContainerBlur },
1073
+ this.renderInput(),
1074
+ this.renderSuggestions()));
1075
+ }
1076
+ onBlur(e) {
1077
+ if (e.relatedTarget && e.relatedTarget === react_dom_1.findDOMNode(this.listRef.current)) {
1078
+ return;
1079
+ }
1080
+ const suggestion = (this.props.suggestions || [])[this.state.focusedIdx];
1081
+ suggestion && this.onSuggestionSelected(this.props.suggestions[this.state.focusedIdx]);
1082
+ this.setState({ focused: false, focusedIdx: undefined, touched: false });
1083
+ this.props.inputProps && this.props.inputProps.onBlur && this.props.inputProps.onBlur(e);
1084
+ }
1085
+ renderInput() {
1086
+ const { inputProps, renderInputComponent = this.renderDefaultInputComponent } = this.props;
1087
+ return renderInputComponent(Object.assign(Object.assign({}, inputProps), { value: this.state.inputValue, onChange: this.onInputChange, onFocus: this.onInputFocus, onBlur: this.onInputTryBlur, onKeyDown: this.onInputKeyDown, ref: this.setInputRef }));
1088
+ }
1089
+ renderDefaultInputComponent(props) {
1090
+ return React.createElement("input", Object.assign({}, props));
1091
+ }
1092
+ renderSuggestions() {
1093
+ if ((!this.props.suggestionsOpenOnFocus && !this.state.touched)
1094
+ || !this.state.focused
1095
+ || this.state.hideSuggestions
1096
+ || !(this.props.suggestions || []).length) {
1097
+ return null;
1098
+ }
1099
+ const { suggestion, suggestionsList, suggestionsContainer, suggestionsContainerOpen, suggestionHighlighted } = this.props.theme || {};
1100
+ return (React.createElement("div", { className: utils_1.classNames(suggestionsContainer, suggestionsContainerOpen) },
1101
+ React.createElement("ul", { className: suggestionsList, tabIndex: -1, ref: this.listRef, onBlur: this.onListBlur }, this.props.suggestions.map((s, i) => React.createElement("li", { key: i, className: utils_1.classNames(suggestion, this.state.focusedIdx === i && suggestionHighlighted), onMouseDown: this.onSuggestionMouseDown, onMouseUp: this.onSuggestionMouseUp, "data-idx": i }, this.props.renderSuggestion(s))))));
1102
+ }
1103
+ onSuggestionSelected(suggestion) {
1104
+ this.setState({ inputValue: suggestion.value, hideSuggestions: true });
1105
+ this.props.onSuggestionSelected && this.props.onSuggestionSelected(suggestion);
1106
+ }
1107
+ requestFetch(value) {
1108
+ this.props.onSuggestionsFetchRequested({ value });
1109
+ }
1110
+ }
1111
+ ReactAutosuggest.contextType = ReactContext_1.default;
1112
+ const FriendsWrapper = React.forwardRef(({ formContext, children, id, inputValue, isSuggested }, ref) => {
1113
+ const { Tooltip } = React.useContext(ReactContext_1.default).theme;
1114
+ if (!inputValue || isSuggested) {
1115
+ return children;
1116
+ }
1117
+ const tooltip = (React.createElement(Tooltip, { id: `${id}-tooltip` }, formContext.translations.UnknownName));
1118
+ return (React.createElement(components_1.OverlayTrigger, { overlay: tooltip, placement: "top", ref: ref }, children));
1119
+ });
1120
+ const OrganizationWrapper = React.forwardRef(({ formContext, children, id, inputValue, isSuggested }, ref) => {
1121
+ const { Tooltip } = React.useContext(ReactContext_1.default).theme;
1122
+ if (!inputValue || isSuggested) {
1123
+ return children;
1124
+ }
1125
+ const tooltip = (React.createElement(Tooltip, { id: `${id}-tooltip` }, formContext.translations.UnknownOrganization));
1126
+ return (React.createElement(components_1.OverlayTrigger, { overlay: tooltip, placement: "top", ref: ref }, children));
1127
+ });