@vertigis/react-ui 9.14.0 → 10.0.0

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 (105) hide show
  1. package/AdapterDateFns/index.d.ts +3 -0
  2. package/AdapterDateFns/index.js +3 -0
  3. package/AdapterLuxon/index.d.ts +3 -0
  4. package/AdapterLuxon/index.js +3 -0
  5. package/AdapterMoment/index.d.ts +3 -0
  6. package/AdapterMoment/index.js +3 -0
  7. package/Checkbox/Checkbox.d.ts +3 -2
  8. package/ColorInput/ColorInput.d.ts +57 -0
  9. package/ColorInput/ColorInput.js +122 -0
  10. package/ColorInput/index.d.ts +2 -0
  11. package/ColorInput/index.js +2 -0
  12. package/CopyableText/CopyableText.d.ts +35 -0
  13. package/CopyableText/CopyableText.js +80 -0
  14. package/CopyableText/index.d.ts +2 -0
  15. package/CopyableText/index.js +2 -0
  16. package/DataGrid/index.d.ts +1 -0
  17. package/DataGrid/index.js +1 -0
  18. package/DatePicker/index.d.ts +3 -0
  19. package/DatePicker/index.js +3 -0
  20. package/DateRangePicker/index.d.ts +3 -0
  21. package/DateRangePicker/index.js +3 -0
  22. package/DateTimePicker/index.d.ts +3 -0
  23. package/DateTimePicker/index.js +3 -0
  24. package/FormControl/FormControl.d.ts +42 -0
  25. package/FormControl/FormControl.js +30 -0
  26. package/FormControl/index.d.ts +2 -2
  27. package/FormControl/index.js +2 -2
  28. package/FormLabel/FormLabel.d.ts +1 -1
  29. package/FormLabel/FormLabel.js +2 -2
  30. package/FormLabelTextField/FormLabelTextField.d.ts +15 -0
  31. package/FormLabelTextField/FormLabelTextField.js +34 -0
  32. package/FormLabelTextField/index.d.ts +2 -0
  33. package/FormLabelTextField/index.js +2 -0
  34. package/IconButton/IconButton.d.ts +1 -1
  35. package/IconMenu/IconMenu.d.ts +37 -0
  36. package/IconMenu/IconMenu.js +21 -0
  37. package/IconMenu/index.d.ts +2 -0
  38. package/IconMenu/index.js +2 -0
  39. package/InlineFormControl/InlineFormControl.d.ts +38 -0
  40. package/InlineFormControl/InlineFormControl.js +44 -0
  41. package/InlineFormControl/index.d.ts +2 -0
  42. package/InlineFormControl/index.js +2 -0
  43. package/InlineHelp/InlineHelp.d.ts +48 -0
  44. package/InlineHelp/InlineHelp.js +41 -0
  45. package/InlineHelp/index.d.ts +2 -0
  46. package/InlineHelp/index.js +2 -0
  47. package/LicenseInfo/index.d.ts +1 -0
  48. package/LicenseInfo/index.js +1 -0
  49. package/LicenseInfo/index.ts +1 -0
  50. package/Link/Link.d.ts +4 -7
  51. package/Link/Link.js +2 -3
  52. package/Loader/Loader.d.ts +33 -0
  53. package/Loader/Loader.js +75 -0
  54. package/Loader/index.d.ts +2 -0
  55. package/Loader/index.js +2 -0
  56. package/LocalizationProvider/index.d.ts +3 -0
  57. package/LocalizationProvider/index.js +3 -0
  58. package/Markdown/Markdown.d.ts +9 -10
  59. package/Markdown/Markdown.js +2 -1
  60. package/MenuItemSecondaryAction/MenuItemSecondaryAction.d.ts +2 -2
  61. package/MenuItemSecondaryAction/MenuItemSecondaryAction.js +4 -5
  62. package/Radio/Radio.d.ts +3 -2
  63. package/Switch/Switch.d.ts +1 -1
  64. package/Tab/Tab.d.ts +3 -3
  65. package/Tab/Tab.js +1 -1
  66. package/TableCell/TableCell.d.ts +1 -1
  67. package/Tabs/Tabs.d.ts +1 -1
  68. package/Tabs/Tabs.js +1 -1
  69. package/TimePicker/index.d.ts +3 -0
  70. package/TimePicker/index.js +3 -0
  71. package/ToggleButton/ToggleButton.d.ts +1 -1
  72. package/colors/blue.d.ts +1 -1
  73. package/colors/burntOrange.d.ts +1 -1
  74. package/colors/darkBurntOrange.d.ts +1 -1
  75. package/colors/darkRed.d.ts +1 -1
  76. package/colors/green.d.ts +1 -1
  77. package/colors/grey.d.ts +1 -1
  78. package/colors/orange.d.ts +1 -1
  79. package/colors/purple.d.ts +1 -1
  80. package/colors/red.d.ts +1 -1
  81. package/colors/teal.d.ts +1 -1
  82. package/colors/woodlandGreen.d.ts +1 -1
  83. package/icons/utils/createSvgIcon.d.ts +5 -4
  84. package/icons/utils/createSvgIcon.js +4 -3
  85. package/package.json +13 -4
  86. package/styles/CacheProvider.d.ts +1 -1
  87. package/styles/createTheme.js +27 -3
  88. package/styles/index.js +1 -1
  89. package/styles/themeAugmentation.d.ts +22 -0
  90. package/utils/color.d.ts +11 -0
  91. package/utils/color.js +39 -0
  92. package/utils/generateId.d.ts +1 -0
  93. package/utils/generateId.js +1 -0
  94. package/utils/html.d.ts +16 -0
  95. package/utils/html.js +105 -0
  96. package/utils/intl.d.ts +9 -6
  97. package/utils/intl.js +9 -6
  98. package/utils/markdown.d.ts +11 -3
  99. package/utils/markdown.js +11 -1
  100. package/utils/react.d.ts +15 -0
  101. package/utils/react.js +42 -0
  102. package/utils/url.d.ts +19 -0
  103. package/utils/url.js +74 -0
  104. package/CircularProgress/CircularProgress.d.ts +0 -2
  105. package/CircularProgress/CircularProgress.js +0 -2
package/Tabs/Tabs.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import MUITabs, { tabsClasses as muiTabsClasses, } from "@mui/material/Tabs";
2
+ import MUITabs, { tabsClasses as muiTabsClasses } from "@mui/material/Tabs";
3
3
  import clsx from "clsx";
4
4
  import { forwardRef } from "react";
5
5
  import { mergeStyles, styled } from "../styles/index.js";
@@ -0,0 +1,3 @@
1
+ export * from "@mui/x-date-pickers/TimePicker";
2
+ import { TimePicker } from "@mui/x-date-pickers/TimePicker";
3
+ export default TimePicker;
@@ -0,0 +1,3 @@
1
+ export * from "@mui/x-date-pickers/TimePicker";
2
+ import { TimePicker } from "@mui/x-date-pickers/TimePicker";
3
+ export default TimePicker;
@@ -1,6 +1,6 @@
1
1
  import type { ButtonBaseClasses } from "@mui/material/ButtonBase";
2
2
  import type { OverridableComponent } from "@mui/material/OverridableComponent";
3
- import { ToggleButtonProps as MUIToggleButtonProps, ToggleButtonClasses as MUIToggleButtonClasses } from "@mui/material/ToggleButton";
3
+ import type { ToggleButtonProps as MUIToggleButtonProps, ToggleButtonClasses as MUIToggleButtonClasses } from "@mui/material/ToggleButton";
4
4
  export * from "@mui/material/ToggleButton";
5
5
  export interface ToggleButtonClasses extends MUIToggleButtonClasses, ButtonBaseClasses {
6
6
  }
package/colors/blue.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import Color from "./Color.js";
1
+ import type Color from "./Color.js";
2
2
  declare const blue: Color;
3
3
  export default blue;
@@ -1,3 +1,3 @@
1
- import Color from "./Color.js";
1
+ import type Color from "./Color.js";
2
2
  declare const burntOrange: Color;
3
3
  export default burntOrange;
@@ -1,3 +1,3 @@
1
- import Color from "./Color.js";
1
+ import type Color from "./Color.js";
2
2
  declare const darkBurntOrange: Color;
3
3
  export default darkBurntOrange;
@@ -1,3 +1,3 @@
1
- import Color from "./Color.js";
1
+ import type Color from "./Color.js";
2
2
  declare const darkRed: Color;
3
3
  export default darkRed;
package/colors/green.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import Color from "./Color.js";
1
+ import type Color from "./Color.js";
2
2
  declare const green: Color;
3
3
  export default green;
package/colors/grey.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import Color from "./Color.js";
1
+ import type Color from "./Color.js";
2
2
  declare const grey: Color;
3
3
  export default grey;
@@ -1,3 +1,3 @@
1
- import Color from "./Color.js";
1
+ import type Color from "./Color.js";
2
2
  declare const orange: Color;
3
3
  export default orange;
@@ -1,3 +1,3 @@
1
- import Color from "./Color.js";
1
+ import type Color from "./Color.js";
2
2
  declare const purple: Color;
3
3
  export default purple;
package/colors/red.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import Color from "./Color.js";
1
+ import type Color from "./Color.js";
2
2
  declare const red: Color;
3
3
  export default red;
package/colors/teal.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import Color from "./Color.js";
1
+ import type Color from "./Color.js";
2
2
  declare const teal: Color;
3
3
  export default teal;
@@ -1,3 +1,3 @@
1
- import Color from "./Color.js";
1
+ import type Color from "./Color.js";
2
2
  declare const woodlandGreen: Color;
3
3
  export default woodlandGreen;
@@ -1,12 +1,13 @@
1
1
  import SvgIcon from "@mui/material/SvgIcon";
2
- import { ReactNode } from "react";
2
+ import type { ReactNode } from "react";
3
3
  /**
4
4
  * Creates an SVG icon component from a <path>.
5
+ *
5
6
  * @param path The React component representing the inner path of the SVG.
6
7
  * @param displayName The display name.
7
8
  * @param mirror Whether or not to mirror the icon in RTL mode. By default it
8
- * will mirror anything with "Left" or "Right" in the display name, as well as
9
- * some built-in icons. See the Material UI guidelines for a discussion of which
10
- * icons should be mirrored.
9
+ * will mirror anything with "Left" or "Right" in the display name, as well as
10
+ * some built-in icons. See the Material UI guidelines for a discussion of
11
+ * which icons should be mirrored.
11
12
  */
12
13
  export default function createSvgIcon(path: ReactNode, displayName: string, mirror?: boolean): typeof SvgIcon;
@@ -10,12 +10,13 @@ const gcxSvgIconClasses = {
10
10
  };
11
11
  /**
12
12
  * Creates an SVG icon component from a <path>.
13
+ *
13
14
  * @param path The React component representing the inner path of the SVG.
14
15
  * @param displayName The display name.
15
16
  * @param mirror Whether or not to mirror the icon in RTL mode. By default it
16
- * will mirror anything with "Left" or "Right" in the display name, as well as
17
- * some built-in icons. See the Material UI guidelines for a discussion of which
18
- * icons should be mirrored.
17
+ * will mirror anything with "Left" or "Right" in the display name, as well as
18
+ * some built-in icons. See the Material UI guidelines for a discussion of
19
+ * which icons should be mirrored.
19
20
  */
20
21
  export default function createSvgIcon(path, displayName, mirror) {
21
22
  const Icon = baseCreateSvgIcon(path, displayName);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vertigis/react-ui",
3
- "version": "9.14.0",
3
+ "version": "10.0.0",
4
4
  "description": "Utilities and React components used in VertiGIS applications.",
5
5
  "keywords": [
6
6
  "vertigis",
@@ -15,24 +15,33 @@
15
15
  "sideEffects": false,
16
16
  "scripts": {},
17
17
  "dependencies": {
18
+ "@esri/arcgis-html-sanitizer": "^2.10.0",
18
19
  "@emotion/cache": "^11.7.1",
19
20
  "@emotion/react": "^11.8.2",
20
21
  "@emotion/styled": "^11.8.1",
21
- "@mui/icons-material": "5.5.1",
22
- "@mui/material": "5.5.2",
22
+ "@mui/icons-material": "5.8.4",
23
+ "@mui/x-date-pickers-pro": "5.0.0-alpha.7",
24
+ "@mui/x-data-grid-pro": "5.13.0",
25
+ "@mui/material": "5.9.0",
23
26
  "clsx": "^1.1.1",
27
+ "color": "^3.1.3",
24
28
  "lodash.escape": "^4.0.1",
25
29
  "lodash.merge": "^4.6.2",
26
30
  "marked": "^4.0.12",
27
- "tslib": "^2.1.0"
31
+ "react-color": "^2.19.3",
32
+ "tslib": "^2.1.0",
33
+ "xss": "^1.0.13"
28
34
  },
29
35
  "devDependencies": {
30
36
  "@geocortex/icons": "5.0.457",
31
37
  "@testing-library/react": "^12.1.2",
32
38
  "@testing-library/user-event": "^13.5.0",
39
+ "@types/color": "^3.0.1",
40
+ "@types/lodash.escape": "^4.0.1",
33
41
  "@types/lodash.merge": "^4.6.7",
34
42
  "@types/marked": "^4.0.2",
35
43
  "@types/react": "^17.0.34",
44
+ "@types/react-color": "^3.0.6",
36
45
  "@types/react-dom": "^17.0.11",
37
46
  "react": "^17.0.2",
38
47
  "react-dom": "^17.0.2"
@@ -1,4 +1,4 @@
1
- import { EmotionCache, Options as CacheOptions } from "@emotion/cache";
1
+ import type { EmotionCache, Options as CacheOptions } from "@emotion/cache";
2
2
  /**
3
3
  * Creates a style cache with the given options.
4
4
  */
@@ -1,4 +1,4 @@
1
- import { alpha, createTheme as createMuiTheme, } from "@mui/material/styles";
1
+ import { alpha, createTheme as createMuiTheme } from "@mui/material/styles";
2
2
  import merge from "lodash.merge";
3
3
  import blue from "../colors/blue.js";
4
4
  import common from "../colors/common.js";
@@ -137,8 +137,8 @@ const getMenuItemStyles = ({ palette, transitions }) => ({
137
137
  },
138
138
  });
139
139
  /**
140
- * The overrides may be based on the theme's palette.
141
- * We must create these separately after the fact.
140
+ * The overrides may be based on the theme's palette. We must create these
141
+ * separately after the fact.
142
142
  */
143
143
  function getOverrides(theme) {
144
144
  const { palette, shape, spacing, transitions, typography } = theme;
@@ -335,6 +335,24 @@ function getOverrides(theme) {
335
335
  },
336
336
  },
337
337
  },
338
+ MuiDatePicker: {
339
+ defaultProps: {
340
+ OpenPickerButtonProps: { size: "small" },
341
+ PopperProps: { dir: theme.direction },
342
+ },
343
+ },
344
+ MuiDateRangePicker: {
345
+ defaultProps: {
346
+ OpenPickerButtonProps: { size: "small" },
347
+ PopperProps: { dir: theme.direction },
348
+ },
349
+ },
350
+ MuiDateTimePicker: {
351
+ defaultProps: {
352
+ OpenPickerButtonProps: { size: "small" },
353
+ PopperProps: { dir: theme.direction },
354
+ },
355
+ },
338
356
  MuiDialogActions: {
339
357
  styleOverrides: {
340
358
  root: {
@@ -782,6 +800,12 @@ function getOverrides(theme) {
782
800
  },
783
801
  },
784
802
  },
803
+ MuiTimePicker: {
804
+ defaultProps: {
805
+ OpenPickerButtonProps: { size: "small" },
806
+ PopperProps: { dir: theme.direction },
807
+ },
808
+ },
785
809
  MuiToggleButton: {
786
810
  defaultProps: {
787
811
  disableFocusRipple: true,
package/styles/index.js CHANGED
@@ -15,7 +15,7 @@ export function mergeStyles(standardClasses, classesProp = {}) {
15
15
  ...classesProp,
16
16
  ...standardClasses,
17
17
  };
18
- for (const key of Object.keys(standardClasses).filter((k) => k in classesProp)) {
18
+ for (const key of Object.keys(standardClasses).filter(k => k in classesProp)) {
19
19
  // The order here is important. The class name(s) passed into the props
20
20
  // for a given class key need to come after the component's own class
21
21
  // name for that key in order to be able to override default styles.
@@ -1,3 +1,8 @@
1
+ import { ComponentsProps, ComponentsOverrides, ComponentsVariants } from "@mui/material/styles";
2
+
3
+ export * from "@mui/x-date-pickers-pro/themeAugmentation";
4
+ export * from "@mui/x-date-pickers/themeAugmentation";
5
+
1
6
  // These are needed to mimic the MUI v4 "default" color for buttons, which was
2
7
  // removed in v5. See https://mui.com/guides/migration-v4/#button for more
3
8
  // details.
@@ -24,3 +29,20 @@ declare module "@mui/material" {
24
29
  }
25
30
 
26
31
  export default {};
32
+
33
+ // TODO: For some reason, MUI's list of x-date-pickers components in the above
34
+ // augmentation is incomplete. Remove these overrides if they ever fix this.
35
+ export interface UndocumentedDatePickersComponents {
36
+ MuiDateRangePicker?: {
37
+ defaultProps?: ComponentsProps["MuiDateRangePicker"];
38
+ styleOverrides?: ComponentsOverrides["MuiDateRangePicker"];
39
+ };
40
+ MuiTimePicker?: {
41
+ defaultProps?: ComponentsProps["MuiTimePicker"];
42
+ styleOverrides?: ComponentsOverrides["MuiTimePicker"];
43
+ };
44
+ }
45
+
46
+ declare module "@mui/material/styles" {
47
+ interface Components extends UndocumentedDatePickersComponents {}
48
+ }
@@ -0,0 +1,11 @@
1
+ import Color from "color";
2
+ /**
3
+ * Returns a Color object if valid. Undefined if invalid
4
+ */
5
+ export declare function parse(color: string | {
6
+ r: string | number;
7
+ g: string | number;
8
+ b: string | number;
9
+ a?: string | number;
10
+ alpha?: string | number;
11
+ } | undefined): Color | undefined;
package/utils/color.js ADDED
@@ -0,0 +1,39 @@
1
+ import Color from "color";
2
+ /**
3
+ * Returns a Color object if valid. Undefined if invalid
4
+ */
5
+ export function parse(color) {
6
+ try {
7
+ if (!color) {
8
+ return undefined;
9
+ }
10
+ // Likely testing a value from the input element
11
+ if (typeof color === "string") {
12
+ return Color(color);
13
+ }
14
+ if (typeof color.r !== "undefined" &&
15
+ typeof color.g !== "undefined" &&
16
+ typeof color.b !== "undefined") {
17
+ const rgb = [
18
+ parseInt(color.r),
19
+ parseInt(color.g),
20
+ parseInt(color.b),
21
+ ];
22
+ let alpha = undefined;
23
+ if (color.a !== undefined) {
24
+ alpha = color.a;
25
+ }
26
+ else if (color.alpha !== undefined) {
27
+ alpha = color.alpha;
28
+ }
29
+ if (alpha !== undefined) {
30
+ rgb.push(parseFloat(alpha));
31
+ }
32
+ return Color(rgb);
33
+ }
34
+ }
35
+ catch {
36
+ // Didn't validate. Let's ignore.
37
+ }
38
+ return undefined;
39
+ }
@@ -1,5 +1,6 @@
1
1
  /**
2
2
  * Generate a random 10 digit id.
3
+ *
3
4
  * @param prefix An optional prefix to prepend to the generated id.
4
5
  */
5
6
  export default function generateId(prefix?: string): string;
@@ -1,5 +1,6 @@
1
1
  /**
2
2
  * Generate a random 10 digit id.
3
+ *
3
4
  * @param prefix An optional prefix to prepend to the generated id.
4
5
  */
5
6
  export default function generateId(prefix) {
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Sanitize a string of unsafe HTML to eliminate XSS (cross-site scripting)
3
+ * security risks. This method allows tags and standard attributes, however
4
+ * `data-` attributes are not allowed. Script tags are not allowed either.
5
+ *
6
+ * @param unsafeHtml String of HTML to be scrubbed clean.
7
+ * @returns Safe HTML that has been sanitized.
8
+ */
9
+ export declare function sanitizeHtml(unsafeHtml: string): string;
10
+ /**
11
+ * Strip all HTML out of a string.
12
+ *
13
+ * @param html String of text which will have its HTML stripped away.
14
+ * @returns A plain text string without any HTML markup.
15
+ */
16
+ export declare function stripHtml(html: string | undefined): string | undefined;
package/utils/html.js ADDED
@@ -0,0 +1,105 @@
1
+ import { Sanitizer } from "@esri/arcgis-html-sanitizer";
2
+ import { escapeAttrValue, safeAttrValue, friendlyAttrValue } from "xss";
3
+ /**
4
+ * Sanitize a string of unsafe HTML to eliminate XSS (cross-site scripting)
5
+ * security risks. This method allows tags and standard attributes, however
6
+ * `data-` attributes are not allowed. Script tags are not allowed either.
7
+ *
8
+ * @param unsafeHtml String of HTML to be scrubbed clean.
9
+ * @returns Safe HTML that has been sanitized.
10
+ */
11
+ export function sanitizeHtml(unsafeHtml) {
12
+ const checkUris = (tag, attr, value, cssFilter) => {
13
+ if (attr === "href" || attr === "src") {
14
+ // Override the default implementation to allow relative URLs.
15
+ if (!value) {
16
+ return "";
17
+ }
18
+ try {
19
+ // Unescape attribute value first.
20
+ let href = friendlyAttrValue(value);
21
+ // Remove any surrounding grave accents and embedded whitespace
22
+ // that can fool the parsing in the URL class, potentially
23
+ // allowing unsafe URLs through.
24
+ href = href.replace(/^`|`$|\s+/g, "");
25
+ // The base URL can be anything -- it's just there to set the
26
+ // protocol to "https" for all relative URLs.
27
+ const url = new URL(href, "https://vertigis.com/");
28
+ if (url.protocol === "http:" ||
29
+ url.protocol === "https:" ||
30
+ url.protocol === "mailto:") {
31
+ return escapeAttrValue(value);
32
+ }
33
+ }
34
+ catch {
35
+ // Ignore and let it be stripped out below. It's probably
36
+ // safest to err on the side of disallowing URLs that cannot be
37
+ // parsed.
38
+ }
39
+ return "";
40
+ }
41
+ return safeAttrValue(tag, attr, value, cssFilter);
42
+ };
43
+ const options = {
44
+ safeAttrValue: checkUris,
45
+ // This list builds on the default list in Esri's sanitization
46
+ // library (since we are passing `true` as the second parameter).
47
+ // See here for the default rules:
48
+ // https://github.com/Esri/arcgis-html-sanitizer/blob/master/src/index.ts
49
+ // In addition to what they support, we also need to support benign
50
+ // tags generated by the markdown library.
51
+ whiteList: {
52
+ a: ["href", "style", "target", "title"],
53
+ code: [],
54
+ blockquote: [],
55
+ del: [],
56
+ h1: [],
57
+ h2: [],
58
+ h3: [],
59
+ h4: [],
60
+ h5: [],
61
+ h6: [],
62
+ img: ["alt", "border", "height", "src", "style", "title", "width"],
63
+ ol: ["start"],
64
+ p: ["style"],
65
+ pre: [],
66
+ span: ["style"],
67
+ thead: [],
68
+ },
69
+ stripIgnoreTag: true,
70
+ stripIgnoreTagBody: true,
71
+ allowCommentTag: false,
72
+ css: {
73
+ // Allow properties that are configurable on PopupTemplate
74
+ // content, via AGOL Map Viewer's rich text editor; they are
75
+ // injected as span elements with style attributes.
76
+ whiteList: {
77
+ "background-color": true,
78
+ color: true,
79
+ "font-size": true,
80
+ "font-family": true,
81
+ "font-weight": true,
82
+ "text-align": true,
83
+ "text-decoration": true,
84
+ },
85
+ },
86
+ };
87
+ return new Sanitizer(options, true).sanitize(unsafeHtml);
88
+ }
89
+ /**
90
+ * Strip all HTML out of a string.
91
+ *
92
+ * @param html String of text which will have its HTML stripped away.
93
+ * @returns A plain text string without any HTML markup.
94
+ */
95
+ export function stripHtml(html) {
96
+ if (!html) {
97
+ return html;
98
+ }
99
+ // Sanitize any HTML that is present, to make it safe (from XSS risks).
100
+ const safe = sanitizeHtml(html);
101
+ // Create a temporary div (using the browser to strip away HTML content).
102
+ const div = document.createElement("div");
103
+ div.innerHTML = safe;
104
+ return div.innerText;
105
+ }
package/utils/intl.d.ts CHANGED
@@ -1,33 +1,36 @@
1
1
  /**
2
2
  * Formats a date for display. The time portion will not appear in the output.
3
+ *
3
4
  * @param date The Date value to format.
4
5
  * @param locale An optional locale to use. If not specified, the browser's
5
- * locale will be used.
6
+ * locale will be used.
6
7
  * @param options Additional options that control how the date is formatted.
7
8
  */
8
9
  export declare function formatDate(date: Date | undefined, options?: Intl.DateTimeFormatOptions, locale?: string): string;
9
10
  /**
10
11
  * Formats a time for display. The date portion will not appear in the output.
12
+ *
11
13
  * @param date The Date value to format.
12
14
  * @param locale An optional locale to use. If not specified, the browser's
13
- * locale will be used.
15
+ * locale will be used.
14
16
  * @param options Additional options that control how the time is formatted.
15
17
  */
16
18
  export declare function formatTime(date: Date | undefined, options?: Intl.DateTimeFormatOptions, locale?: string): string;
17
19
  /**
18
20
  * Formats a date and time for display.
21
+ *
19
22
  * @param date The Date value to format.
20
23
  * @param locale An optional locale to use. If not specified, the browser's
21
- * locale will be used.
22
- * @param options Additional options that control how the date & time are
23
- * formatted.
24
+ * locale will be used.
25
+ * @param options Additional options that control how the date & time are formatted.
24
26
  */
25
27
  export declare function formatDateTime(date: Date | undefined, options?: Intl.DateTimeFormatOptions, locale?: string): string;
26
28
  /**
27
29
  * Formats a number for display.
30
+ *
28
31
  * @param number The number to format.
29
32
  * @param locale An optional locale to use. If not specified, the browser's
30
- * locale will be used.
33
+ * locale will be used.
31
34
  * @param options Additional options that control how the number is formatted.
32
35
  */
33
36
  export declare function formatNumber(number: number | undefined, options?: Intl.NumberFormatOptions, locale?: string): string;
package/utils/intl.js CHANGED
@@ -7,9 +7,10 @@
7
7
  // functions.
8
8
  /**
9
9
  * Formats a date for display. The time portion will not appear in the output.
10
+ *
10
11
  * @param date The Date value to format.
11
12
  * @param locale An optional locale to use. If not specified, the browser's
12
- * locale will be used.
13
+ * locale will be used.
13
14
  * @param options Additional options that control how the date is formatted.
14
15
  */
15
16
  export function formatDate(date, options, locale = navigator.language) {
@@ -17,9 +18,10 @@ export function formatDate(date, options, locale = navigator.language) {
17
18
  }
18
19
  /**
19
20
  * Formats a time for display. The date portion will not appear in the output.
21
+ *
20
22
  * @param date The Date value to format.
21
23
  * @param locale An optional locale to use. If not specified, the browser's
22
- * locale will be used.
24
+ * locale will be used.
23
25
  * @param options Additional options that control how the time is formatted.
24
26
  */
25
27
  export function formatTime(date, options, locale = navigator.language) {
@@ -27,20 +29,21 @@ export function formatTime(date, options, locale = navigator.language) {
27
29
  }
28
30
  /**
29
31
  * Formats a date and time for display.
32
+ *
30
33
  * @param date The Date value to format.
31
34
  * @param locale An optional locale to use. If not specified, the browser's
32
- * locale will be used.
33
- * @param options Additional options that control how the date & time are
34
- * formatted.
35
+ * locale will be used.
36
+ * @param options Additional options that control how the date & time are formatted.
35
37
  */
36
38
  export function formatDateTime(date, options, locale = navigator.language) {
37
39
  return date ? date.toLocaleString(locale, options) : "";
38
40
  }
39
41
  /**
40
42
  * Formats a number for display.
43
+ *
41
44
  * @param number The number to format.
42
45
  * @param locale An optional locale to use. If not specified, the browser's
43
- * locale will be used.
46
+ * locale will be used.
44
47
  * @param options Additional options that control how the number is formatted.
45
48
  */
46
49
  export function formatNumber(number, options, locale = navigator.language) {
@@ -5,9 +5,9 @@ export interface MarkdownToHtmlOptions {
5
5
  /**
6
6
  * If specified, produces HTML that is valid to place within an HTML element
7
7
  * that only supports inline content (called "phrasing content" in the HTML5
8
- * spec). Example elements that only support phrasing content are <span> and
9
- * <h2>. In this mode, any block-level elements resulting from the Markdown
10
- * conversion will be stripped. The default is `false`.
8
+ * spec). Example elements that only support phrasing content are <span>
9
+ * and<h2>. In this mode, any block-level elements resulting from the
10
+ * Markdown conversion will be stripped. The default is `false`.
11
11
  */
12
12
  inline?: boolean;
13
13
  /**
@@ -21,6 +21,14 @@ export interface MarkdownToHtmlOptions {
21
21
  */
22
22
  escapeHtml?: boolean;
23
23
  }
24
+ /**
25
+ * Converts markdown text into HTML. The resulting HTML is sanitized and safe to
26
+ * insert into the DOM.
27
+ *
28
+ * @param markdown The markdown text to convert.
29
+ * @param options Options that affect how the text is converted.
30
+ */
31
+ export declare function markdownToSafeHtml(markdown: string, options?: MarkdownToHtmlOptions): string;
24
32
  /**
25
33
  * Converts markdown text into HTML.
26
34
  *
package/utils/markdown.js CHANGED
@@ -1,15 +1,25 @@
1
1
  import escapeHtml from "lodash.escape";
2
2
  import { marked } from "marked";
3
+ import { sanitizeHtml } from "./html.js";
3
4
  /**
4
5
  * A custom marked renderer that escapes HTML in the original markdown.
5
6
  */
6
7
  class EscapeHtmlRenderer extends marked.Renderer {
7
8
  html(html) {
8
- /* eslint-disable @typescript-eslint/no-unsafe-call */
9
9
  return escapeHtml(html);
10
10
  }
11
11
  }
12
12
  EscapeHtmlRenderer.instance = new EscapeHtmlRenderer();
13
+ /**
14
+ * Converts markdown text into HTML. The resulting HTML is sanitized and safe to
15
+ * insert into the DOM.
16
+ *
17
+ * @param markdown The markdown text to convert.
18
+ * @param options Options that affect how the text is converted.
19
+ */
20
+ export function markdownToSafeHtml(markdown, options) {
21
+ return sanitizeHtml(markdownToHtml(markdown, options));
22
+ }
13
23
  /**
14
24
  * Converts markdown text into HTML.
15
25
  *
@@ -0,0 +1,15 @@
1
+ import type { MutableRefObject, Ref, RefCallback } from "react";
2
+ /**
3
+ * Produces a unique ID that can be used for the HTML `id` attribute. Will use
4
+ * the provided value if defined (typically obtained from the calling
5
+ * component's `id` prop), otherwise one will be generated. The ID will remain
6
+ * the same between renders (even if `idProp` changes).
7
+ */
8
+ export declare function useId(idProp?: string): string;
9
+ /**
10
+ * Combines multiple refs into a single ref.
11
+ *
12
+ * Useful when a component needs a ref to one of its own elements, but also
13
+ * supports forwarding a ref from its parent component.
14
+ */
15
+ export declare function mergeRefs<T>(...refs: (RefCallback<T> | MutableRefObject<T | null> | null)[]): Ref<T>;