@longline/aqua-ui 1.0.338 → 1.0.340

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 (258) hide show
  1. package/containers/Anchor/Anchor.d.ts +5 -0
  2. package/containers/Anchor/Anchor.js +20 -8
  3. package/containers/Dock/Dock.d.ts +5 -0
  4. package/containers/Dock/Dock.js +1 -1
  5. package/containers/Dock/Dockable.d.ts +5 -0
  6. package/containers/Dock/Dockable.js +20 -12
  7. package/containers/DragBar/DragBar.d.ts +5 -0
  8. package/containers/DragBar/DragBar.js +16 -5
  9. package/containers/Form/Field.d.ts +0 -3
  10. package/containers/Form/Field.js +3 -6
  11. package/containers/Form/Form.js +5 -36
  12. package/containers/Form/Validation.d.ts +1 -1
  13. package/containers/Form/Validation.js +6 -6
  14. package/containers/Form/context/FormContext.d.ts +1 -2
  15. package/containers/Form/context/useForm.d.ts +1 -1
  16. package/containers/Form/elements/BoxWrapper.js +2 -0
  17. package/containers/GlassPane/GlassPane.d.ts +7 -2
  18. package/containers/GlassPane/GlassPane.js +3 -3
  19. package/containers/InfoBox/InfoBox.d.ts +5 -0
  20. package/containers/InfoBox/InfoBox.js +1 -1
  21. package/containers/List/List.d.ts +5 -0
  22. package/containers/List/List.js +1 -1
  23. package/containers/List/ListCell.d.ts +5 -0
  24. package/containers/List/ListCell.js +1 -1
  25. package/containers/List/ListRow.d.ts +7 -2
  26. package/containers/List/ListRow.js +1 -1
  27. package/containers/Message/Error.d.ts +2 -0
  28. package/containers/Message/Error.js +1 -1
  29. package/containers/Message/Message.d.ts +5 -0
  30. package/containers/Message/Message.js +1 -1
  31. package/containers/Message/NoData.d.ts +2 -0
  32. package/containers/Message/NoData.js +1 -1
  33. package/containers/Message/NoFilteredData.d.ts +2 -0
  34. package/containers/Message/NoFilteredData.js +1 -1
  35. package/containers/Openable/Openable.d.ts +5 -0
  36. package/containers/Openable/Openable.js +8 -8
  37. package/containers/PublicRoute/PublicRoute.d.ts +9 -1
  38. package/containers/PublicRoute/PublicRoute.js +3 -7
  39. package/containers/Tabs/Pane.d.ts +5 -0
  40. package/containers/Tabs/Pane.js +3 -3
  41. package/containers/Tabs/Tabs.d.ts +5 -0
  42. package/containers/Tabs/Tabs.js +3 -3
  43. package/controls/Chip/Chip.d.ts +15 -3
  44. package/controls/Chip/Chip.js +7 -6
  45. package/controls/CircularProgress/CircularProgress.d.ts +11 -0
  46. package/controls/CircularProgress/CircularProgress.js +19 -11
  47. package/controls/Dropzone/Dropzone.d.ts +11 -1
  48. package/controls/Dropzone/Dropzone.js +18 -7
  49. package/controls/Fab/Fab.d.ts +14 -6
  50. package/controls/Fab/Fab.js +7 -20
  51. package/controls/Ghost/Ghost.js +3 -3
  52. package/controls/Gradient/Gradient.d.ts +5 -0
  53. package/controls/Gradient/Gradient.js +7 -4
  54. package/controls/Histogram/Histogram.d.ts +8 -2
  55. package/controls/Histogram/Histogram.js +9 -9
  56. package/controls/Histogram/HistogramBar.d.ts +2 -2
  57. package/controls/Icon/Icon.d.ts +10 -4
  58. package/controls/Icon/Icon.js +23 -6
  59. package/controls/Key/Key.d.ts +5 -0
  60. package/controls/Key/Key.js +2 -5
  61. package/controls/LinearChart/LinearChart.d.ts +9 -0
  62. package/controls/LinearChart/LinearChart.js +11 -6
  63. package/controls/ListButton/ListButton.d.ts +46 -3
  64. package/controls/ListButton/ListButton.js +70 -9
  65. package/controls/ListView/ColumnsManager/ColumnDraggable.js +11 -5
  66. package/controls/ListView/ColumnsManager/SourceColumns.js +1 -1
  67. package/controls/ListView/IListViewProps.d.ts +9 -2
  68. package/controls/ListView/ListView.js +13 -12
  69. package/controls/ListView/defaults.d.ts +3 -0
  70. package/controls/ListView/defaults.js +6 -0
  71. package/controls/ListView/elements/Body.d.ts +1 -1
  72. package/controls/ListView/elements/Body.js +23 -12
  73. package/controls/ListView/elements/Ghost.js +3 -2
  74. package/controls/ListView/elements/Header.js +3 -2
  75. package/controls/ListView/elements/HeaderCell.js +3 -3
  76. package/controls/ListView/elements/Table.js +16 -10
  77. package/controls/Mouse/Mouse.d.ts +6 -4
  78. package/controls/Mouse/Mouse.js +15 -8
  79. package/controls/PrimaryButton/PrimaryButton.d.ts +9 -3
  80. package/controls/PrimaryButton/PrimaryButton.js +5 -5
  81. package/controls/Progress/Progress.d.ts +9 -0
  82. package/controls/Progress/Progress.js +12 -8
  83. package/controls/SecondaryButton/SecondaryButton.d.ts +8 -3
  84. package/controls/SecondaryButton/SecondaryButton.js +1 -1
  85. package/controls/SpeechRecognizer/EditorRegistry.js +1 -2
  86. package/controls/SpeechRecognizer/SpeechRecognizer.d.ts +9 -1
  87. package/controls/SpeechRecognizer/SpeechRecognizer.js +16 -9
  88. package/controls/TabBar/TabBar.d.ts +5 -0
  89. package/controls/TabBar/TabBar.js +14 -6
  90. package/controls/TabBar/Underliner.js +1 -1
  91. package/controls/TertiaryButton/TertiaryButton.d.ts +9 -3
  92. package/controls/TertiaryButton/TertiaryButton.js +5 -3
  93. package/controls/ToggleButton/ToggleButton.d.ts +8 -2
  94. package/controls/ToggleButton/ToggleButton.js +1 -1
  95. package/controls/View/View.d.ts +5 -0
  96. package/controls/View/View.js +1 -1
  97. package/formatters/CountryFormatter/CountryFormatter.d.ts +3 -2
  98. package/formatters/CountryFormatter/CountryUtil.d.ts +3 -3
  99. package/formatters/DateTimeFormatter/DateTimeFormatter.d.ts +11 -10
  100. package/formatters/DateTimeFormatter/elements/Custom.d.ts +1 -1
  101. package/formatters/DateTimeFormatter/elements/DistanceDate.d.ts +1 -1
  102. package/formatters/DateTimeFormatter/elements/LongDate.d.ts +1 -1
  103. package/formatters/DateTimeFormatter/elements/LongDateTime.d.ts +1 -1
  104. package/formatters/DateTimeFormatter/elements/LongTime.d.ts +1 -1
  105. package/formatters/DateTimeFormatter/elements/Month.d.ts +1 -1
  106. package/formatters/DateTimeFormatter/elements/ShortDate.d.ts +1 -1
  107. package/formatters/DateTimeFormatter/elements/ShortDateTime.d.ts +1 -1
  108. package/formatters/DateTimeFormatter/elements/ShortTime.d.ts +1 -1
  109. package/formatters/DivisionFormatter/DivisionFormatter.d.ts +2 -2
  110. package/formatters/DivisionFormatter/DivisionFormatter.js +1 -1
  111. package/formatters/DivisionFormatter/DivisionUtil.d.ts +1 -1
  112. package/formatters/DivisionFormatter/DivisionUtil.js +5 -3
  113. package/formatters/FilesizeFormatter/FilesizeFormatter.d.ts +3 -3
  114. package/formatters/GIS/CoordinateFormatter.d.ts +2 -2
  115. package/formatters/GIS/LatitudeFormatter.d.ts +2 -2
  116. package/formatters/GIS/LongitudeFormatter.d.ts +2 -2
  117. package/formatters/HumanFormatter/HumanFormatter.d.ts +3 -3
  118. package/formatters/NumberFormatter/NumberFormatter.d.ts +3 -3
  119. package/formatters/PhoneFormatter/PhoneFormatter.d.ts +25 -0
  120. package/formatters/PhoneFormatter/PhoneFormatter.js +34 -0
  121. package/formatters/PhoneFormatter/index.d.ts +1 -0
  122. package/formatters/PhoneFormatter/index.js +1 -0
  123. package/formatters/StringFormatter/StringFormatter.d.ts +3 -3
  124. package/formatters/StringFormatter/StringFormatter.js +1 -4
  125. package/helper/DMS.d.ts +1 -1
  126. package/helper/DMS.js +2 -2
  127. package/helper/phoneNumber.d.ts +31 -0
  128. package/helper/phoneNumber.js +142 -0
  129. package/hooks/useOutsideClose/useOutsideClose.js +20 -11
  130. package/hooks/useSpeechAIRecorder/useSpeechAIRecorder.js +10 -7
  131. package/index.js +1 -0
  132. package/inputs/DateInput/Body.d.ts +2 -2
  133. package/inputs/DateInput/Body.js +11 -7
  134. package/inputs/DateInput/Calendar.d.ts +1 -1
  135. package/inputs/DateInput/Calendar.js +3 -5
  136. package/inputs/DateInput/DateInput.d.ts +11 -3
  137. package/inputs/DateInput/DateInput.js +11 -3
  138. package/inputs/DateInput/Day.d.ts +1 -1
  139. package/inputs/DateInput/InfiniteList.js +6 -3
  140. package/inputs/DateInput/Navbar.js +3 -2
  141. package/inputs/DateInput/NumericInput.js +3 -0
  142. package/inputs/DateInput/Selector.d.ts +1 -1
  143. package/inputs/DateInput/Selector.js +9 -6
  144. package/inputs/Dropdown/Body.d.ts +2 -2
  145. package/inputs/Dropdown/Column.d.ts +1 -1
  146. package/inputs/Dropdown/Dropdown.d.ts +5 -0
  147. package/inputs/Dropdown/Dropdown.js +36 -63
  148. package/inputs/Dropdown/Pill.js +1 -1
  149. package/inputs/Dropdown/Selection.js +1 -1
  150. package/inputs/Editor/Editor.d.ts +5 -0
  151. package/inputs/Editor/Editor.js +16 -6
  152. package/inputs/Editor/buttons/SpeechAIButton.js +2 -0
  153. package/inputs/Editor/buttons/TextAIButton.d.ts +0 -13
  154. package/inputs/Editor/buttons/TextAIButton.js +30 -14
  155. package/inputs/Editor/buttons/TextAIMenu.js +1 -1
  156. package/inputs/Editor/menu/MenuBar.d.ts +1 -1
  157. package/inputs/Editor/menu/MenuBar.js +1 -1
  158. package/inputs/Editor/menu/MenuButton.js +1 -1
  159. package/inputs/Input/Clear.js +1 -1
  160. package/inputs/Input/Input.d.ts +5 -0
  161. package/inputs/Input/Input.js +8 -6
  162. package/inputs/Input/InputWrapper.d.ts +2 -0
  163. package/inputs/Input/InputWrapper.js +1 -1
  164. package/inputs/Input/Reveal.js +1 -1
  165. package/inputs/MonthRange/Body.d.ts +1 -1
  166. package/inputs/MonthRange/Calendar.d.ts +2 -2
  167. package/inputs/MonthRange/Calendar.js +6 -9
  168. package/inputs/MonthRange/MonthRange.d.ts +7 -1
  169. package/inputs/MonthRange/MonthRange.js +14 -6
  170. package/inputs/MonthRange/Selector.d.ts +1 -1
  171. package/inputs/MonthRange/Selector.js +12 -11
  172. package/inputs/PhoneInput/PhoneInput.d.ts +97 -0
  173. package/inputs/PhoneInput/PhoneInput.js +113 -0
  174. package/inputs/PhoneInput/index.d.ts +2 -0
  175. package/inputs/PhoneInput/index.js +1 -0
  176. package/inputs/Selector/Selector.d.ts +5 -0
  177. package/inputs/Selector/Selector.js +4 -1
  178. package/inputs/Slider/Slider.d.ts +75 -22
  179. package/inputs/Slider/Slider.js +104 -22
  180. package/inputs/Textarea/Textarea.d.ts +5 -5
  181. package/inputs/Textarea/Textarea.js +3 -2
  182. package/map/Map/Map.d.ts +2 -2
  183. package/map/Map/Map.js +20 -14
  184. package/map/PositionsManager/PositionBox.js +7 -3
  185. package/map/PositionsManager/PositionsManager.js +33 -13
  186. package/map/controls/CompassButton/CompassButton.js +1 -1
  187. package/map/controls/FullscreenButton/FullscreenButton.js +1 -1
  188. package/map/controls/Geocoder/Geocoder.js +28 -14
  189. package/map/controls/Geocoder/GeocoderApi.js +2 -0
  190. package/map/controls/Geocoder/GeocoderSelector.js +1 -1
  191. package/map/controls/Graticule/Graticule.js +1 -5
  192. package/map/controls/MapLoader/MapLoader.js +1 -1
  193. package/map/controls/ScaleControl/ScaleControl.js +1 -1
  194. package/map/controls/ZoomInButton/ZoomInButton.js +1 -1
  195. package/map/controls/ZoomOutButton/ZoomOutButton.d.ts +1 -1
  196. package/map/controls/ZoomOutButton/ZoomOutButton.js +2 -2
  197. package/map/controls/base/MapButton/MapButton.d.ts +8 -2
  198. package/map/controls/base/MapButton/MapButton.js +11 -2
  199. package/map/controls/base/MapControl/MapControl.d.ts +5 -0
  200. package/map/controls/base/MapControl/MapControl.js +10 -7
  201. package/map/layers/ClusterLayer/ClusterLayer.d.ts +1 -1
  202. package/map/layers/ClusterLayer/ClusterLayer.js +7 -3
  203. package/map/layers/HtmlMarkerLayer/HtmlMarkerLayer.js +8 -4
  204. package/map/layers/IdwBlendLayer/IdwBlendLayer.js +9 -4
  205. package/map/layers/IdwLayer/IdwLayer.d.ts +2 -1
  206. package/map/layers/IdwLayer/IdwLayer.js +271 -215
  207. package/map/layers/InterpolationLayer/ContoursFragmentShader.d.ts +1 -1
  208. package/map/layers/InterpolationLayer/ContoursFragmentShader.js +1 -1
  209. package/map/layers/InterpolationLayer/InterpolationLayer.d.ts +4 -3
  210. package/map/layers/InterpolationLayer/InterpolationLayer.js +362 -275
  211. package/map/layers/ParticlesLayer/ParticlesLayer.d.ts +8 -7
  212. package/map/layers/ParticlesLayer/ParticlesLayer.js +528 -404
  213. package/map/markers/ClusterMarker/ClusterMarker.d.ts +6 -1
  214. package/map/markers/ClusterMarker/ClusterMarker.js +15 -6
  215. package/map/markers/RiskMarker/RiskMarker.d.ts +5 -1
  216. package/map/markers/RiskMarker/RiskMarker.js +4 -4
  217. package/modules/CountryDropdown/CountryDropdown.js +10 -1
  218. package/modules/Filter/Filter.d.ts +5 -0
  219. package/modules/Filter/Filter.js +10 -6
  220. package/modules/Globe/Globe.d.ts +5 -0
  221. package/modules/Globe/Globe.js +4 -4
  222. package/modules/MainMenu/Item.d.ts +9 -2
  223. package/modules/MainMenu/Item.js +8 -5
  224. package/modules/MainMenu/MainMenu.d.ts +5 -0
  225. package/modules/MainMenu/MainMenu.js +1 -1
  226. package/modules/ParticleGlobe/GL.d.ts +1 -1
  227. package/modules/ParticleGlobe/ParticleGlobe.d.ts +5 -0
  228. package/modules/ParticleGlobe/ParticleGlobe.js +69 -40
  229. package/modules/Public/Public.d.ts +5 -0
  230. package/modules/Public/Public.js +3 -3
  231. package/package.json +1 -1
  232. package/services/Auth/Auth.js +13 -7
  233. package/services/Auth/AuthContext.js +9 -1
  234. package/services/Dialog/Dialog.d.ts +7 -2
  235. package/services/Dialog/Dialog.js +7 -6
  236. package/services/Dialog/DialogWindow.d.ts +3 -1
  237. package/services/Dialog/DialogWindow.js +1 -1
  238. package/services/Dialog/XhrDialog.d.ts +1 -1
  239. package/services/Toast/Toast.js +5 -3
  240. package/services/Toast/ToastContainer.js +3 -1
  241. package/services/Toast/ToastContext.d.ts +1 -1
  242. package/services/Toast/ToastProvider.js +2 -0
  243. package/map/layers/HtmlMarkerLayer/HtmlMarkerLayer copy.d.ts +0 -35
  244. package/map/layers/HtmlMarkerLayer/HtmlMarkerLayer copy.js +0 -176
  245. package/modules/Root/Content.d.ts +0 -16
  246. package/modules/Root/Content.js +0 -25
  247. package/modules/Root/Overlay.d.ts +0 -23
  248. package/modules/Root/Overlay.js +0 -33
  249. package/modules/Root/Root.d.ts +0 -10
  250. package/modules/Root/Root.js +0 -46
  251. package/modules/Root/Shader.d.ts +0 -15
  252. package/modules/Root/Shader.js +0 -24
  253. package/modules/Root/Sidebar.d.ts +0 -13
  254. package/modules/Root/Sidebar.js +0 -24
  255. package/modules/Root/index.d.ts +0 -1
  256. package/modules/Root/index.js +0 -1
  257. package/modules/Root/stories/SampleContent.d.ts +0 -7
  258. package/modules/Root/stories/SampleContent.js +0 -44
@@ -0,0 +1,25 @@
1
+ import * as React from 'react';
2
+ interface IPhoneFormatterProps {
3
+ /**
4
+ * Phone number in E.164 format, e.g. `"+351910306792"`. `null` renders nothing.
5
+ */
6
+ value: string | null;
7
+ }
8
+ /**
9
+ * Displays a phone number alongside the flag of the country its international
10
+ * dialing prefix belongs to. The country is derived from the number itself
11
+ * (the shared `+1` North American range is disambiguated by area code), so
12
+ * only the number is needed — there is nothing else to store.
13
+ *
14
+ * ## Usage
15
+ *
16
+ * ```tsx
17
+ * <PhoneFormatter value="+351910306792"/>
18
+ * ```
19
+ */
20
+ declare const PhoneFormatter: {
21
+ ({ value }: IPhoneFormatterProps): React.JSX.Element | null;
22
+ displayName: string;
23
+ };
24
+ export { PhoneFormatter };
25
+ export type { IPhoneFormatterProps };
@@ -0,0 +1,34 @@
1
+ var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
2
+ if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
3
+ return cooked;
4
+ };
5
+ import * as React from 'react';
6
+ import styled from 'styled-components';
7
+ import { CountryFormatter } from '../CountryFormatter';
8
+ import { parseE164 } from '../../helper/phoneNumber';
9
+ /**
10
+ * Displays a phone number alongside the flag of the country its international
11
+ * dialing prefix belongs to. The country is derived from the number itself
12
+ * (the shared `+1` North American range is disambiguated by area code), so
13
+ * only the number is needed — there is nothing else to store.
14
+ *
15
+ * ## Usage
16
+ *
17
+ * ```tsx
18
+ * <PhoneFormatter value="+351910306792"/>
19
+ * ```
20
+ */
21
+ var PhoneFormatter = function (_a) {
22
+ var value = _a.value;
23
+ if (!value)
24
+ return null;
25
+ var iso = parseE164(value).iso;
26
+ return (React.createElement(Wrapper, null,
27
+ iso && React.createElement(CountryFormatter, { type: "flag", value: iso }),
28
+ React.createElement(Number, null, value)));
29
+ };
30
+ PhoneFormatter.displayName = 'PhoneFormatter';
31
+ var Wrapper = styled.div(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 6px;\n"], ["\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 6px;\n"])));
32
+ var Number = styled.div(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n text-overflow: ellipsis;\n overflow: hidden;\n"], ["\n text-overflow: ellipsis;\n overflow: hidden;\n"])));
33
+ export { PhoneFormatter };
34
+ var templateObject_1, templateObject_2;
@@ -0,0 +1 @@
1
+ export * from './PhoneFormatter';
@@ -0,0 +1 @@
1
+ export * from './PhoneFormatter';
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  interface IStringFormatterProps {
3
- /** String to format */
4
- value: string;
3
+ /** String to format. `null` renders nothing. */
4
+ value: string | null;
5
5
  /** Type of formatting */
6
6
  type: 'capitalize' | 'capitalizeWords' | 'upper' | 'lower' | 'reverse' | 'snake' | 'kebab';
7
7
  }
@@ -32,7 +32,7 @@ interface IStringFormatterProps {
32
32
  * ```
33
33
  */
34
34
  declare const StringFormatter: {
35
- ({ value, type }: IStringFormatterProps): React.JSX.Element;
35
+ ({ value, type }: IStringFormatterProps): React.JSX.Element | null;
36
36
  displayName: string;
37
37
  };
38
38
  export { StringFormatter, IStringFormatterProps };
@@ -10,10 +10,7 @@ var capitalize = function (str) {
10
10
  var capitalizeWords = function (str) {
11
11
  return str
12
12
  .split(/\s+/)
13
- .map(function (word) {
14
- var _a = Array.from(word), first = _a[0], rest = _a.slice(1);
15
- return first.toLocaleUpperCase() + rest.join('');
16
- })
13
+ .map(capitalize)
17
14
  .join(' ');
18
15
  };
19
16
  /** Formatters map */
package/helper/DMS.d.ts CHANGED
@@ -27,7 +27,7 @@ declare class DMS {
27
27
  * // Returns: "(no coordinates)" (out of range)
28
28
  * ```
29
29
  */
30
- static toDMSString(value: number | string, defaultStr: string, max: number, positive: string, negative: string): string;
30
+ static toDMSString(value: number | string | null, defaultStr: string, max: number, positive: string, negative: string): string;
31
31
  /**
32
32
  * Convert a decimal latitude or longitude value to degrees,
33
33
  * minutes, and seconds.
package/helper/DMS.js CHANGED
@@ -30,8 +30,8 @@ var DMS = /** @class */ (function () {
30
30
  * ```
31
31
  */
32
32
  DMS.toDMSString = function (value, defaultStr, max, positive, negative) {
33
- // Convert value to number if it is a string:
34
- var num = typeof value === 'number' ? value : parseFloat(value);
33
+ // Convert value to number if it is a string; null falls through to NaN.
34
+ var num = typeof value === 'number' ? value : (value == null ? NaN : parseFloat(value));
35
35
  // Return default string if value is not a number or out of range:
36
36
  if (isNaN(num) || num < -max || num > max)
37
37
  return defaultStr;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * ISO 3166-1 alpha-2 country code → ITU country calling code (digits, no '+').
3
+ *
4
+ * Country calling codes are a prefix-free set by ITU design (no code is a
5
+ * prefix of another), so an E.164 number can be split into (code, national)
6
+ * deterministically by longest-prefix match — see parseE164().
7
+ */
8
+ export declare const DIAL_BY_ISO: Record<string, string>;
9
+ /** Calling code (digits) → representative ISO country code. */
10
+ export declare const ISO_BY_DIAL: Record<string, string>;
11
+ export declare const digitsOnly: (s: string | null | undefined) => string;
12
+ export interface IParsedPhone {
13
+ /** Representative ISO country for the matched calling code, or null. */
14
+ iso: string | null;
15
+ /** Calling code digits (e.g. "351"), or null if none matched. */
16
+ code: string | null;
17
+ /** The national part (digits after the calling code). */
18
+ national: string;
19
+ }
20
+ /**
21
+ * Split an E.164 string ("+351123456789") into its calling code and national
22
+ * part. Relies on calling codes being prefix-free, so the first prefix (of
23
+ * length 1–3) that is a known code is the unique correct one.
24
+ */
25
+ export declare const parseE164: (value: string | null | undefined) => IParsedPhone;
26
+ /**
27
+ * Build an E.164 string from a selected country and a national part. Returns
28
+ * '' when there is no national number, so the field stays empty/optional
29
+ * rather than persisting a bare "+44".
30
+ */
31
+ export declare const assembleE164: (iso: string, national: string) => string;
@@ -0,0 +1,142 @@
1
+ /**
2
+ * ISO 3166-1 alpha-2 country code → ITU country calling code (digits, no '+').
3
+ *
4
+ * Country calling codes are a prefix-free set by ITU design (no code is a
5
+ * prefix of another), so an E.164 number can be split into (code, national)
6
+ * deterministically by longest-prefix match — see parseE164().
7
+ */
8
+ export var DIAL_BY_ISO = {
9
+ AC: '247', AD: '376', AE: '971', AF: '93', AG: '1', AI: '1', AL: '355',
10
+ AM: '374', AO: '244', AR: '54', AS: '1', AT: '43', AU: '61', AW: '297',
11
+ AX: '358', AZ: '994',
12
+ BA: '387', BB: '1', BD: '880', BE: '32', BF: '226', BG: '359', BH: '973',
13
+ BI: '257', BJ: '229', BL: '590', BM: '1', BN: '673', BO: '591', BQ: '599',
14
+ BR: '55', BS: '1', BT: '975', BW: '267', BY: '375', BZ: '501',
15
+ CA: '1', CC: '61', CD: '243', CF: '236', CG: '242', CH: '41', CI: '225',
16
+ CK: '682', CL: '56', CM: '237', CN: '86', CO: '57', CR: '506', CU: '53',
17
+ CV: '238', CW: '599', CX: '61', CY: '357', CZ: '420',
18
+ DE: '49', DJ: '253', DK: '45', DM: '1', DO: '1', DZ: '213',
19
+ EC: '593', EE: '372', EG: '20', EH: '212', ER: '291', ES: '34', ET: '251',
20
+ FI: '358', FJ: '679', FK: '500', FM: '691', FO: '298', FR: '33',
21
+ GA: '241', GB: '44', GD: '1', GE: '995', GF: '594', GG: '44', GH: '233',
22
+ GI: '350', GL: '299', GM: '220', GN: '224', GP: '590', GQ: '240', GR: '30',
23
+ GT: '502', GU: '1', GW: '245', GY: '592',
24
+ HK: '852', HN: '504', HR: '385', HT: '509', HU: '36',
25
+ ID: '62', IE: '353', IL: '972', IM: '44', IN: '91', IO: '246', IQ: '964',
26
+ IR: '98', IS: '354', IT: '39',
27
+ JE: '44', JM: '1', JO: '962', JP: '81',
28
+ KE: '254', KG: '996', KH: '855', KI: '686', KM: '269', KN: '1', KP: '850',
29
+ KR: '82', KW: '965', KY: '1', KZ: '7',
30
+ LA: '856', LB: '961', LC: '1', LI: '423', LK: '94', LR: '231', LS: '266',
31
+ LT: '370', LU: '352', LV: '371', LY: '218',
32
+ MA: '212', MC: '377', MD: '373', ME: '382', MF: '590', MG: '261', MH: '692',
33
+ MK: '389', ML: '223', MM: '95', MN: '976', MO: '853', MP: '1', MQ: '596',
34
+ MR: '222', MS: '1', MT: '356', MU: '230', MV: '960', MW: '265', MX: '52',
35
+ MY: '60', MZ: '258',
36
+ NA: '264', NC: '687', NE: '227', NF: '672', NG: '234', NI: '505', NL: '31',
37
+ NO: '47', NP: '977', NR: '674', NU: '683', NZ: '64',
38
+ OM: '968',
39
+ PA: '507', PE: '51', PF: '689', PG: '675', PH: '63', PK: '92', PL: '48',
40
+ PM: '508', PN: '64', PR: '1', PS: '970', PT: '351', PW: '680', PY: '595',
41
+ QA: '974',
42
+ RE: '262', RO: '40', RS: '381', RU: '7', RW: '250',
43
+ SA: '966', SB: '677', SC: '248', SD: '249', SE: '46', SG: '65', SH: '290',
44
+ SI: '386', SJ: '47', SK: '421', SL: '232', SM: '378', SN: '221', SO: '252',
45
+ SR: '597', SS: '211', ST: '239', SV: '503', SX: '1', SY: '963', SZ: '268',
46
+ TC: '1', TD: '235', TG: '228', TH: '66', TJ: '992', TK: '690', TL: '670',
47
+ TM: '993', TN: '216', TO: '676', TR: '90', TT: '1', TV: '688', TW: '886',
48
+ TZ: '255',
49
+ UA: '380', UG: '256', US: '1', UY: '598', UZ: '998',
50
+ VA: '379', VC: '1', VE: '58', VG: '1', VI: '1', VN: '84', VU: '678',
51
+ WF: '681', WS: '685',
52
+ XK: '383',
53
+ YE: '967', YT: '262',
54
+ ZA: '27', ZM: '260', ZW: '263',
55
+ };
56
+ /**
57
+ * Canonical country shown for a calling code when several countries share it
58
+ * (e.g. +1 → US, +44 → GB). We only store the full number, so this affects
59
+ * the displayed flag/name on parse, not what is persisted.
60
+ */
61
+ var PRIMARY_BY_DIAL = {
62
+ '1': 'US', '7': 'RU', '39': 'IT', '44': 'GB', '47': 'NO', '61': 'AU',
63
+ '64': 'NZ', '212': 'MA', '262': 'RE', '290': 'SH', '358': 'FI',
64
+ '500': 'FK', '590': 'GP', '599': 'CW',
65
+ };
66
+ /** Calling code (digits) → representative ISO country code. */
67
+ export var ISO_BY_DIAL = (function () {
68
+ var map = {};
69
+ for (var _i = 0, _a = Object.entries(DIAL_BY_ISO); _i < _a.length; _i++) {
70
+ var _b = _a[_i], iso = _b[0], code = _b[1];
71
+ if (!(code in map))
72
+ map[code] = iso; // first-wins for unique codes
73
+ }
74
+ Object.assign(map, PRIMARY_BY_DIAL); // explicit winners for shared codes
75
+ return map;
76
+ })();
77
+ /**
78
+ * North American Numbering Plan: +1 is shared by ~25 countries, but each
79
+ * 3-digit area code (NPA) belongs to exactly one. Maps the non-US NPAs to their
80
+ * country; any NPA not listed (and short/partial numbers) falls back to the +1
81
+ * representative (US). This lets a stored +1 number resolve back to, e.g.,
82
+ * Canada rather than always showing the US.
83
+ */
84
+ var NANP_BY_NPA = (function () {
85
+ var map = {
86
+ '242': 'BS', '246': 'BB', '264': 'AI', '268': 'AG', '284': 'VG',
87
+ '340': 'VI', '345': 'KY', '441': 'BM', '473': 'GD', '649': 'TC',
88
+ '658': 'JM', '664': 'MS', '670': 'MP', '671': 'GU', '684': 'AS',
89
+ '721': 'SX', '758': 'LC', '767': 'DM', '784': 'VC', '787': 'PR',
90
+ '809': 'DO', '829': 'DO', '849': 'DO', '868': 'TT', '869': 'KN',
91
+ '876': 'JM', '939': 'PR',
92
+ };
93
+ var caNpas = [
94
+ '204', '226', '236', '249', '250', '263', '289', '306', '343', '354',
95
+ '365', '367', '368', '382', '403', '416', '418', '428', '431', '437',
96
+ '438', '450', '468', '474', '506', '514', '519', '548', '579', '581',
97
+ '584', '587', '604', '613', '639', '647', '672', '683', '705', '709',
98
+ '742', '753', '778', '780', '782', '807', '819', '825', '867', '873',
99
+ '879', '902', '905',
100
+ ];
101
+ for (var _i = 0, caNpas_1 = caNpas; _i < caNpas_1.length; _i++) {
102
+ var npa = caNpas_1[_i];
103
+ map[npa] = 'CA';
104
+ }
105
+ return map;
106
+ })();
107
+ export var digitsOnly = function (s) { return (s || '').replace(/\D/g, ''); };
108
+ /**
109
+ * Split an E.164 string ("+351123456789") into its calling code and national
110
+ * part. Relies on calling codes being prefix-free, so the first prefix (of
111
+ * length 1–3) that is a known code is the unique correct one.
112
+ */
113
+ export var parseE164 = function (value) {
114
+ var _a;
115
+ var cleaned = (value || '').replace(/[^\d+]/g, '');
116
+ if (!cleaned.startsWith('+'))
117
+ return { iso: null, code: null, national: '' };
118
+ var rest = cleaned.slice(1);
119
+ for (var len = 1; len <= 3; len++) {
120
+ var code = rest.slice(0, len);
121
+ if (ISO_BY_DIAL[code]) {
122
+ var iso = ISO_BY_DIAL[code];
123
+ // +1 is shared across the NANP; resolve the specific country from the
124
+ // area code (the 3 digits after the country code).
125
+ if (code === '1') {
126
+ iso = (_a = NANP_BY_NPA[rest.slice(len, len + 3)]) !== null && _a !== void 0 ? _a : iso;
127
+ }
128
+ return { iso: iso, code: code, national: rest.slice(len) };
129
+ }
130
+ }
131
+ return { iso: null, code: null, national: rest };
132
+ };
133
+ /**
134
+ * Build an E.164 string from a selected country and a national part. Returns
135
+ * '' when there is no national number, so the field stays empty/optional
136
+ * rather than persisting a bare "+44".
137
+ */
138
+ export var assembleE164 = function (iso, national) {
139
+ var code = DIAL_BY_ISO[iso];
140
+ var digits = digitsOnly(national);
141
+ return code && digits ? "+".concat(code).concat(digits) : '';
142
+ };
@@ -48,6 +48,13 @@ import * as React from "react";
48
48
  */
49
49
  function useOutsideClose(_a) {
50
50
  var open = _a.open, refs = _a.refs, onClose = _a.onClose, _b = _a.escapeToClose, escapeToClose = _b === void 0 ? false : _b, _c = _a.blurToClose, blurToClose = _c === void 0 ? false : _c;
51
+ // Keep the latest refs/onClose in refs so the listener effect doesn't depend
52
+ // on them. Consumers typically pass an inline refs array and inline onClose,
53
+ // which would otherwise re-attach the document listeners on every render.
54
+ var refsRef = React.useRef(refs);
55
+ refsRef.current = refs;
56
+ var onCloseRef = React.useRef(onClose);
57
+ onCloseRef.current = onClose;
51
58
  // Events get added to the component only when it opens, and removed
52
59
  // when it closes. This way, components aren't listening for document-wide
53
60
  // events when they're closed.
@@ -55,30 +62,32 @@ function useOutsideClose(_a) {
55
62
  // If component isn't open, then do nothing:
56
63
  if (!open)
57
64
  return undefined;
58
- // When the HTML document gets clicked, see if the click is inside one of
59
- // the HTML elements that were passed in. If so, do nothing. It outside
60
- // these elements, close the component.
65
+ // When the HTML document gets clicked, see if the click is inside one of
66
+ // the HTML elements that were passed in. If so, do nothing. If outside
67
+ // these elements, close the component.
61
68
  var handleClick = function (e) {
62
69
  var target = e.target;
63
- var clickedInside = refs.some(function (ref) { return ref.current && ref.current.contains(target); });
70
+ var clickedInside = refsRef.current.some(function (ref) { return ref.current && ref.current.contains(target); });
64
71
  if (!clickedInside) {
65
- onClose();
72
+ onCloseRef.current();
66
73
  }
67
74
  };
68
75
  // When the ESC key is pressed (and this feature has been enabled),
69
76
  // close the component.
70
77
  var handleKeyDown = function (e) {
71
78
  if (escapeToClose && e.key === "Escape") {
72
- onClose();
79
+ onCloseRef.current();
73
80
  }
74
81
  };
82
+ // On focusout, relatedTarget is the element receiving focus. Close if focus
83
+ // is moving outside all refs (or is being lost entirely).
75
84
  var handleBlur = function (e) {
76
85
  if (!blurToClose)
77
86
  return;
78
87
  var target = e.relatedTarget; // where focus is going
79
- var focusedInside = refs.some(function (ref) { return ref.current && target && ref.current.contains(target); });
88
+ var focusedInside = refsRef.current.some(function (ref) { return ref.current && target && ref.current.contains(target); });
80
89
  if (!focusedInside) {
81
- onClose();
90
+ onCloseRef.current();
82
91
  }
83
92
  };
84
93
  // Add event listeners:
@@ -87,7 +96,7 @@ function useOutsideClose(_a) {
87
96
  document.addEventListener("keydown", handleKeyDown);
88
97
  }
89
98
  if (blurToClose) {
90
- document.addEventListener("focusin", handleBlur); // focusin bubbles
99
+ document.addEventListener("focusout", handleBlur); // focusout bubbles
91
100
  }
92
101
  // Remove event listeners:
93
102
  return function () {
@@ -96,9 +105,9 @@ function useOutsideClose(_a) {
96
105
  document.removeEventListener("keydown", handleKeyDown);
97
106
  }
98
107
  if (blurToClose) {
99
- document.removeEventListener("focusin", handleBlur);
108
+ document.removeEventListener("focusout", handleBlur);
100
109
  }
101
110
  };
102
- }, [open, refs, onClose, escapeToClose, blurToClose]);
111
+ }, [open, escapeToClose, blurToClose]);
103
112
  }
104
113
  export { useOutsideClose };
@@ -44,7 +44,7 @@ import { SpeechManager } from './SpeechManager';
44
44
  // code in a template string, compile that into a blob, and then use that
45
45
  // instead. This way, no separate JS file needs to be deployed with AquaUI.
46
46
  //
47
- var moduleScript = /* js */ "\nconst MAX_16BIT_INT = 32767\nclass AudioProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n\n // Input is browser sample rate (typically 48000 Hz in Firefox)\n // This variable is globally available inside the AudioWorkletProcessor\n // scope.\n this.inputSampleRate = sampleRate;\n console.log('Detected input sample rate:', sampleRate);\n this.targetSampleRate = 16000;\n this.ratio = this.inputSampleRate / this.targetSampleRate;\n\n // Buffer of input samples for resampling\n this.buffer = [];\n\n // Number of samples per output chunk\n this.chunkSize = 1600; // ~100ms at 16kHz\n }\n\n /**\n * Resample the input buffer to the target sample rate using linear interpolation.\n */\n resample(inputBuffer) {\n const outputLength = Math.floor(inputBuffer.length / this.ratio);\n const output = new Float32Array(outputLength);\n\n for (let i = 0; i < outputLength; i++) {\n const idx = i * this.ratio;\n const idxInt = Math.floor(idx);\n const idxFrac = idx - idxInt;\n\n const sample1 = inputBuffer[idxInt] || 0;\n const sample2 = inputBuffer[idxInt + 1] || 0;\n output[i] = sample1 + (sample2 - sample1) * idxFrac;\n }\n\n return output;\n }\n\n /**\n * Converts Float32 PCM [-1, 1] to 16-bit signed PCM\n */\n floatTo16BitPCM(float32Array) {\n const int16Array = new Int16Array(float32Array.length);\n for (let i = 0; i < float32Array.length; i++) {\n let s = Math.max(-1, Math.min(1, float32Array[i]));\n int16Array[i] = s < 0 ? s * 0x8000 : s * 0x7FFF;\n }\n return int16Array;\n }\n\n /**\n * Called automatically by browser on each audio frame (128 samples per channel).\n */\n process(inputs, outputs, parameters) {\n try {\n const input = inputs[0];\n if (!input || input.length === 0) return true;\n\n // Read from mono channel\n const channelData = input[0];\n this.buffer.push(...channelData);\n\n // Only process if we have enough input to produce a full output chunk\n const neededInputSamples = this.chunkSize * this.ratio;\n if (this.buffer.length >= neededInputSamples) {\n const inputForChunk = this.buffer.slice(0, neededInputSamples);\n const resampled = this.resample(inputForChunk);\n const pcm = this.floatTo16BitPCM(resampled);\n\n this.port.postMessage({ audio_data: pcm }); // Send Int16Array to main thread\n\n // Remove consumed input samples\n this.buffer = this.buffer.slice(neededInputSamples);\n }\n\n return true; // Keep processor alive\n } catch (error) {\n console.error(error)\n return false\n }\n }\n}\n\nregisterProcessor('audio-processor', AudioProcessor);\n";
47
+ var moduleScript = /* js */ "\nconst MAX_16BIT_INT = 32767\nclass AudioProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n\n // Input is browser sample rate (typically 48000 Hz in Firefox)\n // This variable is globally available inside the AudioWorkletProcessor\n // scope.\n this.inputSampleRate = sampleRate;\n this.targetSampleRate = 16000;\n this.ratio = this.inputSampleRate / this.targetSampleRate;\n\n // Buffer of input samples for resampling\n this.buffer = [];\n\n // Number of samples per output chunk\n this.chunkSize = 1600; // ~100ms at 16kHz\n }\n\n /**\n * Resample the input buffer to the target sample rate using linear interpolation.\n */\n resample(inputBuffer) {\n const outputLength = Math.floor(inputBuffer.length / this.ratio);\n const output = new Float32Array(outputLength);\n\n for (let i = 0; i < outputLength; i++) {\n const idx = i * this.ratio;\n const idxInt = Math.floor(idx);\n const idxFrac = idx - idxInt;\n\n const sample1 = inputBuffer[idxInt] || 0;\n const sample2 = inputBuffer[idxInt + 1] || 0;\n output[i] = sample1 + (sample2 - sample1) * idxFrac;\n }\n\n return output;\n }\n\n /**\n * Converts Float32 PCM [-1, 1] to 16-bit signed PCM\n */\n floatTo16BitPCM(float32Array) {\n const int16Array = new Int16Array(float32Array.length);\n for (let i = 0; i < float32Array.length; i++) {\n let s = Math.max(-1, Math.min(1, float32Array[i]));\n int16Array[i] = s < 0 ? s * 0x8000 : s * 0x7FFF;\n }\n return int16Array;\n }\n\n /**\n * Called automatically by browser on each audio frame (128 samples per channel).\n */\n process(inputs, outputs, parameters) {\n try {\n const input = inputs[0];\n if (!input || input.length === 0) return true;\n\n // Read from mono channel\n const channelData = input[0];\n this.buffer.push(...channelData);\n\n // Only process if we have enough input to produce a full output chunk\n const neededInputSamples = this.chunkSize * this.ratio;\n if (this.buffer.length >= neededInputSamples) {\n const inputForChunk = this.buffer.slice(0, neededInputSamples);\n const resampled = this.resample(inputForChunk);\n const pcm = this.floatTo16BitPCM(resampled);\n\n this.port.postMessage({ audio_data: pcm }); // Send Int16Array to main thread\n\n // Remove consumed input samples\n this.buffer = this.buffer.slice(neededInputSamples);\n }\n\n return true; // Keep processor alive\n } catch (error) {\n console.error(error)\n return false\n }\n }\n}\n\nregisterProcessor('audio-processor', AudioProcessor);\n";
48
48
  /**
49
49
  * useSpeechAIRecorder
50
50
  *
@@ -132,6 +132,7 @@ var useSpeechAIRecorder = function (url, onTranscript, authToken) {
132
132
  return [4 /*yield*/, audioContext.audioWorklet.addModule(scriptUrl)];
133
133
  case 2:
134
134
  _a.sent();
135
+ URL.revokeObjectURL(scriptUrl);
135
136
  node = new AudioWorkletNode(audioContext, 'audio-processor');
136
137
  source.connect(node);
137
138
  node.connect(audioContext.destination); // Required to keep node alive in some browsers
@@ -225,7 +226,6 @@ var useSpeechAIRecorder = function (url, onTranscript, authToken) {
225
226
  }
226
227
  // Turn off any other speech recording through the SpeechManager singleton.
227
228
  // Register this stream as the current one.
228
- console.log("START SESSION");
229
229
  SpeechManager.startNewSession(function () {
230
230
  cleanup();
231
231
  });
@@ -246,7 +246,6 @@ var useSpeechAIRecorder = function (url, onTranscript, authToken) {
246
246
  turnsRef.current = {};
247
247
  // WebSocket connection established
248
248
  ws.onopen = function () {
249
- console.log('WebSocket connected.');
250
249
  // Start recording and streaming chunks
251
250
  startRecording(function (audioChunk) {
252
251
  if (ws.readyState === WebSocket.OPEN) {
@@ -261,7 +260,13 @@ var useSpeechAIRecorder = function (url, onTranscript, authToken) {
261
260
  };
262
261
  // Handle messages from AssemblyAI
263
262
  ws.onmessage = function (event) {
264
- var msg = JSON.parse(event.data);
263
+ var msg;
264
+ try {
265
+ msg = JSON.parse(event.data);
266
+ }
267
+ catch (_a) {
268
+ return; // Ignore non-JSON / binary frames.
269
+ }
265
270
  if (msg.type === 'Turn') {
266
271
  var turn_order = msg.turn_order, transcript = msg.transcript;
267
272
  turnsRef.current[turn_order] = transcript;
@@ -276,9 +281,7 @@ var useSpeechAIRecorder = function (url, onTranscript, authToken) {
276
281
  ws.onerror = function (err) {
277
282
  console.error('WebSocket error:', err);
278
283
  };
279
- ws.onclose = function () {
280
- console.log('WebSocket closed.');
281
- };
284
+ ws.onclose = function () { };
282
285
  return [2 /*return*/];
283
286
  }
284
287
  });
package/index.js CHANGED
@@ -0,0 +1 @@
1
+ "use strict";
@@ -5,7 +5,7 @@ interface IProps {
5
5
  /**
6
6
  * Current value.
7
7
  */
8
- value: Date;
8
+ value: Date | null;
9
9
  /**
10
10
  * Is control currently open?
11
11
  */
@@ -27,6 +27,6 @@ interface IProps {
27
27
  attributes: any;
28
28
  }
29
29
  declare const Body: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<Omit<IProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
30
- ref?: React.Ref<HTMLDivElement>;
30
+ ref?: React.RefObject<HTMLDivElement> | ((instance: HTMLDivElement | null) => void | React.DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof React.DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | null | undefined;
31
31
  }, never>> & string & Omit<React.ForwardRefExoticComponent<IProps & React.RefAttributes<HTMLDivElement>>, keyof React.Component<any, {}, any>>;
32
32
  export { Body };
@@ -34,23 +34,27 @@ var BodyBase = React.forwardRef(function (props, ref) {
34
34
  var handleDayClick = function (date) {
35
35
  props.onSelect(date);
36
36
  };
37
- //
37
+ //
38
38
  // Moves current view by specified number of months.
39
- //
39
+ //
40
40
  var handleMove = function (months) {
41
- date.setMonth(date.getMonth() + months);
42
- setDate(new Date(date));
41
+ var d = new Date(date);
42
+ d.setMonth(d.getMonth() + months);
43
+ setDate(d);
43
44
  };
44
45
  var handlePrevYear = function () { return handleMove(-12); };
45
46
  var handleNextYear = function () { return handleMove(12); };
46
47
  var handlePrevMonth = function () { return handleMove(-1); };
47
48
  var handleNextMonth = function () { return handleMove(1); };
48
49
  var handleMonth = function (month) {
49
- date.setMonth(month);
50
- setDate(new Date(date));
50
+ var d = new Date(date);
51
+ d.setMonth(month);
52
+ setDate(d);
51
53
  };
52
54
  var handleYear = function (year) {
53
- date.setFullYear(year);
55
+ var d = new Date(date);
56
+ d.setFullYear(year);
57
+ setDate(d);
54
58
  };
55
59
  return (React.createElement("div", __assign({ style: props.styles.popper }, props.attributes.popper, { className: props.className, tabIndex: -1, ref: ref, onMouseDown: function (e) { return e.stopPropagation(); } }),
56
60
  React.createElement(Navbar, { date: date, onPrevYear: handlePrevYear, onNextYear: handleNextYear, onPrevMonth: handlePrevMonth, onNextMonth: handleNextMonth, onMonth: handleMonth, onYear: handleYear }),
@@ -5,7 +5,7 @@ interface IProps {
5
5
  /** Current date. Will be highlighted. */
6
6
  date: Date;
7
7
  /** Selected date. Will be highlighted. */
8
- selectedDate: Date;
8
+ selectedDate: Date | null;
9
9
  /** If set, don't allow picking days beyond today. */
10
10
  nofuture?: boolean;
11
11
  /** Fired when a date is clicked. */
@@ -7,6 +7,7 @@ import * as React from 'react';
7
7
  import styled from 'styled-components';
8
8
  import { Day } from './Day';
9
9
  var CalendarBase = function (props) {
10
+ var _a;
10
11
  // Returns true if two dates are equal.
11
12
  var isDateEqual = function (d1, d2) {
12
13
  return (d1.getFullYear() === d2.getFullYear() &&
@@ -26,10 +27,7 @@ var CalendarBase = function (props) {
26
27
  start.setDate(start.getDate() - 1);
27
28
  }
28
29
  // Create a date for the last day of the month.
29
- var month = props.date.getMonth() + 1;
30
- if (month > 12)
31
- month = 1;
32
- var end = new Date(props.date.getFullYear(), month, 0);
30
+ var end = new Date(props.date.getFullYear(), props.date.getMonth() + 1, 0);
33
31
  // Move forward until it's a Sunday.
34
32
  while (end.getDay() !== 0) {
35
33
  end.setDate(end.getDate() + 1);
@@ -45,7 +43,7 @@ var CalendarBase = function (props) {
45
43
  // Build array of days.
46
44
  var days = [];
47
45
  while (start.getTime() < end.getTime()) {
48
- days.push(React.createElement(Day, { key: start.getTime(), grey: start.getMonth() != props.date.getMonth() || (props.nofuture && start > today), selected: props.selectedDate && isDateEqual(props.selectedDate, start), today: isDateEqual(today, start), day: start.getDate(), onClick: (!props.nofuture || start <= today) ? handleClick.bind(_this, new Date(start.getTime())) : null }));
46
+ days.push(React.createElement(Day, { key: start.getTime(), grey: start.getMonth() != props.date.getMonth() || (((_a = props.nofuture) !== null && _a !== void 0 ? _a : false) && start > today), selected: !!props.selectedDate && isDateEqual(props.selectedDate, start), today: isDateEqual(today, start), day: start.getDate(), onClick: (!props.nofuture || start <= today) ? handleClick.bind(_this, new Date(start.getTime())) : undefined }));
49
47
  start.setDate(start.getDate() + 1);
50
48
  }
51
49
  return (React.createElement("div", { "data-testid": "Calendar", className: props.className },
@@ -58,13 +58,21 @@ interface IDateInputProps extends ITestable {
58
58
  */
59
59
  noTabIndex?: boolean;
60
60
  /**
61
- * Listeners are notified whenever the user interacts with the Input.
61
+ * Listeners are notified whenever the user interacts with the Input. The new
62
+ * value is passed (a `Date`, or `null` when cleared).
62
63
  */
63
- onChange?: (value: any) => void;
64
+ onChange?: (value: Date | null) => void;
64
65
  /**
65
- * Listeners are notified when the Input receives focus.
66
+ * Listeners are notified when the Input receives focus (from outside the
67
+ * component; internal focus moves between the day/month/year fields do not
68
+ * re-fire it).
66
69
  */
67
70
  onFocus?: () => void;
71
+ /**
72
+ * Optional inline styles applied to the outer element, for one-off overrides
73
+ * of the default styling.
74
+ */
75
+ style?: React.CSSProperties;
68
76
  }
69
77
  declare const DateInput: {
70
78
  ({ direction, noTabIndex, disabled, transparent, fluid, error, clearable, nofuture, ...props }: IDateInputProps): React.JSX.Element;
@@ -41,7 +41,7 @@ var DateInputBase = function (props) {
41
41
  return def;
42
42
  if (str instanceof Date)
43
43
  return str;
44
- var date = new Date(props.value);
44
+ var date = new Date(str);
45
45
  if (isNaN(date.getDate()))
46
46
  return def;
47
47
  return date;
@@ -91,6 +91,14 @@ var DateInputBase = function (props) {
91
91
  if (e.key == 'Escape' && open)
92
92
  setOpen(false);
93
93
  };
94
+ var handleFocus = function (e) {
95
+ if (!props.onFocus)
96
+ return;
97
+ // Only notify when focus enters from outside the component, not when it
98
+ // moves between the internal day/month/year fields.
99
+ if (!e.currentTarget.contains(e.relatedTarget))
100
+ props.onFocus();
101
+ };
94
102
  var _c = usePopper(wrapperRef.current, bodyRef.current, {
95
103
  placement: props.direction == 'down' ? 'bottom-start' : 'top-start',
96
104
  modifiers: [
@@ -102,8 +110,8 @@ var DateInputBase = function (props) {
102
110
  }
103
111
  ]
104
112
  }), styles = _c.styles, attributes = _c.attributes, update = _c.update;
105
- return (React.createElement("div", { "data-testid": props['data-testid'] || "DateInput", tabIndex: -1, className: props.className, onKeyDown: handleKeyDown, ref: wrapperRef },
106
- React.createElement(Selector, { value: value, disabled: props.disabled, ghost: props.ghost, transparent: props.transparent, error: props.error, clearable: props.clearable, noTabIndex: props.noTabIndex, onChange: handleChange, onClear: (!props.disabled && props.clearable && value != null) ? function () { return handleChange(null); } : null, onCalendar: handleToggle }),
113
+ return (React.createElement("div", { "data-testid": props['data-testid'] || "DateInput", tabIndex: -1, className: props.className, style: props.style, onKeyDown: handleKeyDown, onFocus: handleFocus, ref: wrapperRef },
114
+ React.createElement(Selector, { value: value, disabled: props.disabled, ghost: props.ghost, transparent: props.transparent, error: props.error, clearable: props.clearable, noTabIndex: props.noTabIndex, onChange: handleChange, onClear: (!props.disabled && props.clearable && value != null) ? function () { return handleChange(null); } : undefined, onCalendar: handleToggle }),
107
115
  createPortal(React.createElement(Body, { ref: bodyRef, value: value, open: open, transparent: props.transparent, nofuture: props.nofuture, onSelect: handleSelect, styles: styles, attributes: attributes }), document.body)));
108
116
  };
109
117
  var DateInputStyled = styled(DateInputBase)(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n position: relative;\n // DateInput has a minimum width.\n width: 250px;\n // A fluid DateInput occupies full horizontal width.\n ", " \n"], ["\n position: relative;\n // DateInput has a minimum width.\n width: 250px;\n // A fluid DateInput occupies full horizontal width.\n ", " \n"])), function (p) { return p.fluid && css(templateObject_1 || (templateObject_1 = __makeTemplateObject(["width: 100%;"], ["width: 100%;"]))); });
@@ -22,7 +22,7 @@ interface IProps {
22
22
  * Triggered when Day is clicked. If this property is not set,
23
23
  * then the Day will have no hover circle.
24
24
  */
25
- onClick?: () => void;
25
+ onClick?: (e: React.MouseEvent) => void;
26
26
  }
27
27
  /**
28
28
  * A `Day` is a day on the calendar. It is rendered with