roamjs-components 0.86.0-alpha → 0.86.0-alpha.2

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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "roamjs-components",
3
3
  "description": "Expansive toolset, utilities, & components for developing RoamJS extensions.",
4
- "version": "0.86.0-alpha",
4
+ "version": "0.86.0-alpha.2",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
7
7
  "scripts": {
@@ -26,8 +26,8 @@
26
26
  "@types/jsdom": "^20.0.1",
27
27
  "@types/marked": "^4.0.3",
28
28
  "@types/nanoid": "2.0.0",
29
- "@types/react": "^17.0.39 || ^18.2.0",
30
- "@types/react-dom": "^17.0.13 || ^18.2.0",
29
+ "@types/react": "18.2.0",
30
+ "@types/react-dom": "18.2.0",
31
31
  "@types/use-sync-external-store": "^0.0.3",
32
32
  "chrono-node": "2.3.0",
33
33
  "crypto-js": "3.1.9-1",
@@ -40,14 +40,13 @@
40
40
  "marked": "4.0.16",
41
41
  "marked-react": "1.1.2",
42
42
  "nanoid": "2.0.4",
43
- "react": "^17.0.2 || ^18.2.0",
44
- "react-dom": "^17.0.2 || ^18.2.0",
43
+ "react": "18.2.0",
44
+ "react-dom": "18.2.0",
45
45
  "tslib": "2.2.0",
46
46
  "use-sync-external-store": "^1.2.0"
47
47
  },
48
48
  "dependencies": {
49
49
  "@samepage/scripts": "^0.74.2",
50
- "aws-sdk-plus": "^0.5.3",
51
50
  "color": "^4.0.1",
52
51
  "date-fns": "^2.27.0",
53
52
  "edn-data": "^1.0.0",
@@ -68,7 +67,8 @@
68
67
  "http-server": "^14.1.1",
69
68
  "prettier": "^2.3.1",
70
69
  "tslint-config-prettier": "^1.18.0",
71
- "tslint-react-hooks": "^2.2.2"
70
+ "tslint-react-hooks": "^2.2.2",
71
+ "dotenv": "16.3.1"
72
72
  },
73
73
  "engines": {
74
74
  "npm": ">=7.0.0",
@@ -78,9 +78,17 @@
78
78
  "roamjs": "./scripts/index.js"
79
79
  },
80
80
  "overrides": {
81
- "@testing-library/react": {
82
- "react": "17.0.2",
83
- "react-dom": "17.0.2"
81
+ "@blueprintjs/core": {
82
+ "react": "18.2.0",
83
+ "react-dom": "18.2.0"
84
+ },
85
+ "@blueprintjs/datetime": {
86
+ "react": "18.2.0",
87
+ "react-dom": "18.2.0"
88
+ },
89
+ "@blueprintjs/select": {
90
+ "react": "18.2.0",
91
+ "react-dom": "18.2.0"
84
92
  }
85
93
  },
86
94
  "samepage": {
@@ -0,0 +1,48 @@
1
+ diff --git a/node_modules/@blueprintjs/core/lib/esm/components/alert/alert.d.ts b/node_modules/@blueprintjs/core/lib/esm/components/alert/alert.d.ts
2
+ index 09b06be..f74f6a3 100644
3
+ --- a/node_modules/@blueprintjs/core/lib/esm/components/alert/alert.d.ts
4
+ +++ b/node_modules/@blueprintjs/core/lib/esm/components/alert/alert.d.ts
5
+ @@ -5,6 +5,7 @@ import { IOverlayLifecycleProps } from "../overlay/overlay";
6
+ export declare type AlertProps = IAlertProps;
7
+ /** @deprecated use AlertProps */
8
+ export interface IAlertProps extends IOverlayLifecycleProps, Props {
9
+ + children?: React.ReactNode;
10
+ /**
11
+ * Whether pressing <kbd>escape</kbd> when focused on the Alert should cancel the alert.
12
+ * If this prop is enabled, then either `onCancel` or `onClose` must also be defined.
13
+ diff --git a/node_modules/@blueprintjs/core/lib/esm/components/dialog/dialog.d.ts b/node_modules/@blueprintjs/core/lib/esm/components/dialog/dialog.d.ts
14
+ index e90ee31..3e4f4ef 100644
15
+ --- a/node_modules/@blueprintjs/core/lib/esm/components/dialog/dialog.d.ts
16
+ +++ b/node_modules/@blueprintjs/core/lib/esm/components/dialog/dialog.d.ts
17
+ @@ -6,6 +6,7 @@ import { IBackdropProps, OverlayableProps } from "../overlay/overlay";
18
+ export declare type DialogProps = IDialogProps;
19
+ /** @deprecated use DialogProps */
20
+ export interface IDialogProps extends OverlayableProps, IBackdropProps, Props {
21
+ + children?: React.ReactNode;
22
+ /**
23
+ * Toggles the visibility of the overlay and its children.
24
+ * This prop is required because the component is controlled.
25
+ diff --git a/node_modules/@blueprintjs/core/lib/esm/components/tabs/tabs.d.ts b/node_modules/@blueprintjs/core/lib/esm/components/tabs/tabs.d.ts
26
+ index 2ca5fe5..870a32e 100644
27
+ --- a/node_modules/@blueprintjs/core/lib/esm/components/tabs/tabs.d.ts
28
+ +++ b/node_modules/@blueprintjs/core/lib/esm/components/tabs/tabs.d.ts
29
+ @@ -6,6 +6,7 @@ export declare const Expander: React.FunctionComponent;
30
+ export declare type TabsProps = ITabsProps;
31
+ /** @deprecated use TabsProps */
32
+ export interface ITabsProps extends Props {
33
+ + children?: React.ReactNode;
34
+ /**
35
+ * Whether the selected tab indicator should animate its movement.
36
+ *
37
+ diff --git a/node_modules/@blueprintjs/core/lib/esm/components/tooltip/tooltip.d.ts b/node_modules/@blueprintjs/core/lib/esm/components/tooltip/tooltip.d.ts
38
+ index 94f4af9..4db48a9 100644
39
+ --- a/node_modules/@blueprintjs/core/lib/esm/components/tooltip/tooltip.d.ts
40
+ +++ b/node_modules/@blueprintjs/core/lib/esm/components/tooltip/tooltip.d.ts
41
+ @@ -6,6 +6,7 @@ import { IPopoverSharedProps } from "../popover/popoverSharedProps";
42
+ export declare type TooltipProps = ITooltipProps;
43
+ /** @deprecated use TooltipProps */
44
+ export interface ITooltipProps extends IPopoverSharedProps, IntentProps {
45
+ + children?: React.ReactNode;
46
+ /**
47
+ * The content that will be displayed inside of the tooltip.
48
+ */
@@ -0,0 +1,12 @@
1
+ diff --git a/node_modules/@blueprintjs/select/lib/esm/components/select/select.d.ts b/node_modules/@blueprintjs/select/lib/esm/components/select/select.d.ts
2
+ index f8b9bc6..ee0b6da 100644
3
+ --- a/node_modules/@blueprintjs/select/lib/esm/components/select/select.d.ts
4
+ +++ b/node_modules/@blueprintjs/select/lib/esm/components/select/select.d.ts
5
+ @@ -4,6 +4,7 @@ import { IListItemsProps } from "../../common";
6
+ export declare type SelectProps<T> = ISelectProps<T>;
7
+ /** @deprecated use SelectProps */
8
+ export interface ISelectProps<T> extends IListItemsProps<T> {
9
+ + children?: React.ReactNode;
10
+ /**
11
+ * Whether the component should take up the full width of its container.
12
+ * This overrides `popoverProps.fill`. You also have to ensure that the child
@@ -1,248 +1,248 @@
1
- import {
2
- InputGroup,
3
- Menu,
4
- MenuItem,
5
- PopoverPosition,
6
- Popover,
7
- Button,
8
- TextArea,
9
- } from "@blueprintjs/core";
10
- import React, {
11
- useState,
12
- useCallback,
13
- useMemo,
14
- useRef,
15
- useEffect,
16
- } from "react";
17
- import useArrowKeyDown from "../hooks/useArrowKeyDown";
18
- import fuzzy from "fuzzy";
19
-
20
- type FilterOptions<T> = (options: T[], query: string) => T[];
21
- type OnNewItem<T> = (s: string) => T;
22
- type ItemToQuery<T> = (t?: T) => string;
23
-
24
- export type AutocompleteInputProps<T = string> = {
25
- value?: T;
26
- setValue: (q: T) => void;
27
- showButton?: boolean;
28
- onBlur?: (v: string) => void;
29
- onConfirm?: () => void;
30
- options?: T[];
31
- placeholder?: string;
32
- autoFocus?: boolean;
33
- multiline?: boolean;
34
- id?: string;
35
- filterOptions?: FilterOptions<T>;
36
- itemToQuery?: ItemToQuery<T>;
37
- renderItem?: (props: {
38
- item: T;
39
- onClick: () => void;
40
- active: boolean;
41
- }) => React.ReactElement;
42
- onNewItem?: OnNewItem<T>;
43
- disabled?: boolean;
44
- maxItemsDisplayed?: number;
45
- };
46
-
47
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint
48
- const AutocompleteInput = <T extends unknown = string>({
49
- value,
50
- setValue,
51
- onBlur,
52
- onConfirm,
53
- showButton,
54
- options = [],
55
- placeholder = "Enter value",
56
- autoFocus,
57
- multiline,
58
- id,
59
- filterOptions: _filterOptions,
60
- itemToQuery: _itemToQuery,
61
- renderItem,
62
- onNewItem: _onNewItem,
63
- disabled,
64
- maxItemsDisplayed = Infinity,
65
- }: AutocompleteInputProps<T>): React.ReactElement => {
66
- const [isOpen, setIsOpen] = useState(false);
67
- const itemToQuery = useMemo<ItemToQuery<T>>(
68
- () => _itemToQuery || ((s) => (s ? `${s}` : "")),
69
- [_itemToQuery]
70
- );
71
- const [query, setQuery] = useState<string>(() => itemToQuery(value));
72
- const open = useCallback(() => setIsOpen(true), [setIsOpen]);
73
- const close = useCallback(() => setIsOpen(false), [setIsOpen]);
74
- const [isTyping, setIsTyping] = useState(false);
75
- const filterOptions = useMemo<FilterOptions<T>>(
76
- () =>
77
- _filterOptions ||
78
- ((o, q) =>
79
- fuzzy
80
- .filter(q, o, { extract: itemToQuery })
81
- .map((f) => f.original)
82
- .filter((f): f is T => !!f)),
83
- [_filterOptions, itemToQuery]
84
- );
85
- const onNewItem = useMemo<OnNewItem<T>>(
86
- () => _onNewItem || ((s) => s as T),
87
- [_onNewItem]
88
- );
89
-
90
- const items = useMemo(
91
- () =>
92
- (query ? filterOptions(options, query) : options).slice(
93
- 0,
94
- maxItemsDisplayed
95
- ),
96
- [query, options, filterOptions, maxItemsDisplayed]
97
- );
98
- const menuRef = useRef<HTMLUListElement>(null);
99
- const inputRef = useRef<HTMLInputElement & HTMLTextAreaElement>(null);
100
- const onEnter = useCallback(
101
- (value?: T) => {
102
- if (isOpen && value) {
103
- setQuery(itemToQuery(value));
104
- setValue(value);
105
- setIsTyping(false);
106
- } else if (onConfirm) {
107
- onConfirm();
108
- } else {
109
- setIsOpen(true);
110
- }
111
- },
112
- [setValue, onConfirm, isOpen]
113
- );
114
- const { activeIndex, onKeyDown } = useArrowKeyDown({
115
- onEnter,
116
- results: items,
117
- menuRef,
118
- });
119
- useEffect(() => {
120
- if (!items.length || !isTyping) close();
121
- else open();
122
- }, [items, close, open, isTyping]);
123
- useEffect(() => {
124
- if (query && isOpen) setValue(items[activeIndex] || onNewItem(query));
125
- else if (query) setValue(onNewItem(query));
126
- }, [setValue, activeIndex, items, onNewItem, query]);
127
- useEffect(() => {
128
- if (
129
- inputRef.current &&
130
- inputRef.current === document.activeElement &&
131
- value
132
- ) {
133
- const index = itemToQuery(value).length;
134
- inputRef.current.setSelectionRange(index, index);
135
- }
136
- const touchEndListener = (e: TouchEvent) => {
137
- if (
138
- !e.target ||
139
- !menuRef.current ||
140
- menuRef.current.contains(e.target as Element)
141
- ) {
142
- return;
143
- }
144
- if (!inputRef.current || inputRef.current.contains(e.target as Element)) {
145
- return;
146
- }
147
- close();
148
- };
149
- document.body.addEventListener("touchend", touchEndListener);
150
- return () =>
151
- document.body.removeEventListener("touchend", touchEndListener);
152
- }, [inputRef, menuRef, close]);
153
- const Input = useMemo(() => (multiline ? TextArea : InputGroup), [multiline]);
154
- return (
155
- <Popover
156
- portalClassName={"roamjs-autocomplete-input"}
157
- targetClassName={"roamjs-autocomplete-input-target"}
158
- captureDismiss={true}
159
- isOpen={isOpen}
160
- onOpened={open}
161
- minimal
162
- autoFocus={false}
163
- enforceFocus={false}
164
- position={PopoverPosition.BOTTOM_LEFT}
165
- modifiers={{
166
- flip: { enabled: false },
167
- preventOverflow: { enabled: false },
168
- }}
169
- content={
170
- <Menu className={"max-h-64 overflow-auto max-w-md"} ulRef={menuRef}>
171
- {items.map((t, i) => {
172
- const onClick = () => {
173
- setIsTyping(false);
174
- setValue(t);
175
- setQuery(itemToQuery(t));
176
- inputRef.current?.focus();
177
- };
178
- const sharedProps = {
179
- onClick,
180
- onTouchEnd: onClick,
181
- active: activeIndex === i,
182
- };
183
- return renderItem ? (
184
- <React.Fragment key={i}>
185
- {renderItem?.({
186
- item: t,
187
- ...sharedProps,
188
- })}
189
- </React.Fragment>
190
- ) : (
191
- <MenuItem
192
- text={itemToQuery(t)}
193
- key={i}
194
- multiline
195
- {...sharedProps}
196
- />
197
- );
198
- })}
199
- </Menu>
200
- }
201
- target={
202
- <Input
203
- disabled={disabled}
204
- value={query}
205
- onChange={(e) => {
206
- setIsTyping(true);
207
- setQuery(e.target.value);
208
- }}
209
- autoFocus={autoFocus}
210
- placeholder={placeholder}
211
- onKeyDown={(e) => {
212
- if (e.key === "Escape") {
213
- e.stopPropagation();
214
- close();
215
- } else {
216
- onKeyDown(e);
217
- }
218
- }}
219
- id={id}
220
- onClick={() => setIsTyping(true)}
221
- onBlur={(e) => {
222
- if (
223
- e.relatedTarget === null ||
224
- !(e.relatedTarget as HTMLElement).closest?.(
225
- ".roamjs-autocomplete-input"
226
- )
227
- ) {
228
- setIsTyping(false);
229
- }
230
- if (onBlur) {
231
- onBlur(e.target.value);
232
- }
233
- }}
234
- inputRef={inputRef}
235
- {...(showButton
236
- ? {
237
- rightElement: (
238
- <Button icon={"add"} minimal onClick={() => onEnter()} />
239
- ),
240
- }
241
- : {})}
242
- />
243
- }
244
- />
245
- );
246
- };
247
-
248
- export default AutocompleteInput;
1
+ import {
2
+ InputGroup,
3
+ Menu,
4
+ MenuItem,
5
+ PopoverPosition,
6
+ Popover,
7
+ Button,
8
+ TextArea,
9
+ } from "@blueprintjs/core";
10
+ import React, {
11
+ useState,
12
+ useCallback,
13
+ useMemo,
14
+ useRef,
15
+ useEffect,
16
+ } from "react";
17
+ import useArrowKeyDown from "../hooks/useArrowKeyDown";
18
+ import fuzzy from "fuzzy";
19
+
20
+ type FilterOptions<T> = (options: T[], query: string) => T[];
21
+ type OnNewItem<T> = (s: string) => T;
22
+ type ItemToQuery<T> = (t?: T) => string;
23
+
24
+ export type AutocompleteInputProps<T = string> = {
25
+ value?: T;
26
+ setValue: (q: T) => void;
27
+ showButton?: boolean;
28
+ onBlur?: (v: string) => void;
29
+ onConfirm?: () => void;
30
+ options?: T[];
31
+ placeholder?: string;
32
+ autoFocus?: boolean;
33
+ multiline?: boolean;
34
+ id?: string;
35
+ filterOptions?: FilterOptions<T>;
36
+ itemToQuery?: ItemToQuery<T>;
37
+ renderItem?: (props: {
38
+ item: T;
39
+ onClick: () => void;
40
+ active: boolean;
41
+ }) => React.ReactElement;
42
+ onNewItem?: OnNewItem<T>;
43
+ disabled?: boolean;
44
+ maxItemsDisplayed?: number;
45
+ };
46
+
47
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint
48
+ const AutocompleteInput = <T extends unknown = string>({
49
+ value,
50
+ setValue,
51
+ onBlur,
52
+ onConfirm,
53
+ showButton,
54
+ options = [],
55
+ placeholder = "Enter value",
56
+ autoFocus,
57
+ multiline,
58
+ id,
59
+ filterOptions: _filterOptions,
60
+ itemToQuery: _itemToQuery,
61
+ renderItem,
62
+ onNewItem: _onNewItem,
63
+ disabled,
64
+ maxItemsDisplayed = Infinity,
65
+ }: AutocompleteInputProps<T>): React.ReactElement => {
66
+ const [isOpen, setIsOpen] = useState(false);
67
+ const itemToQuery = useMemo<ItemToQuery<T>>(
68
+ () => _itemToQuery || ((s) => (s ? `${s}` : "")),
69
+ [_itemToQuery]
70
+ );
71
+ const [query, setQuery] = useState<string>(() => itemToQuery(value));
72
+ const open = useCallback(() => setIsOpen(true), [setIsOpen]);
73
+ const close = useCallback(() => setIsOpen(false), [setIsOpen]);
74
+ const [isTyping, setIsTyping] = useState(false);
75
+ const filterOptions = useMemo<FilterOptions<T>>(
76
+ () =>
77
+ _filterOptions ||
78
+ ((o, q) =>
79
+ fuzzy
80
+ .filter(q, o, { extract: itemToQuery })
81
+ .map((f) => f.original)
82
+ .filter((f): f is T => !!f)),
83
+ [_filterOptions, itemToQuery]
84
+ );
85
+ const onNewItem = useMemo<OnNewItem<T>>(
86
+ () => _onNewItem || ((s) => s as T),
87
+ [_onNewItem]
88
+ );
89
+
90
+ const items = useMemo(
91
+ () =>
92
+ (query ? filterOptions(options, query) : options).slice(
93
+ 0,
94
+ maxItemsDisplayed
95
+ ),
96
+ [query, options, filterOptions, maxItemsDisplayed]
97
+ );
98
+ const menuRef = useRef<HTMLUListElement>(null);
99
+ const inputRef = useRef<HTMLInputElement & HTMLTextAreaElement>(null);
100
+ const onEnter = useCallback(
101
+ (value?: T) => {
102
+ if (isOpen && value) {
103
+ setQuery(itemToQuery(value));
104
+ setValue(value);
105
+ setIsTyping(false);
106
+ } else if (onConfirm) {
107
+ onConfirm();
108
+ } else {
109
+ setIsOpen(true);
110
+ }
111
+ },
112
+ [setValue, onConfirm, isOpen]
113
+ );
114
+ const { activeIndex, onKeyDown } = useArrowKeyDown({
115
+ onEnter,
116
+ results: items,
117
+ menuRef,
118
+ });
119
+ useEffect(() => {
120
+ if (!items.length || !isTyping) close();
121
+ else open();
122
+ }, [items, close, open, isTyping]);
123
+ useEffect(() => {
124
+ if (query && isOpen) setValue(items[activeIndex] || onNewItem(query));
125
+ else if (query) setValue(onNewItem(query));
126
+ }, [setValue, activeIndex, items, onNewItem, query]);
127
+ useEffect(() => {
128
+ if (
129
+ inputRef.current &&
130
+ inputRef.current === document.activeElement &&
131
+ value
132
+ ) {
133
+ const index = itemToQuery(value).length;
134
+ inputRef.current.setSelectionRange(index, index);
135
+ }
136
+ const touchEndListener = (e: TouchEvent) => {
137
+ if (
138
+ !e.target ||
139
+ !menuRef.current ||
140
+ menuRef.current.contains(e.target as Element)
141
+ ) {
142
+ return;
143
+ }
144
+ if (!inputRef.current || inputRef.current.contains(e.target as Element)) {
145
+ return;
146
+ }
147
+ close();
148
+ };
149
+ document.body.addEventListener("touchend", touchEndListener);
150
+ return () =>
151
+ document.body.removeEventListener("touchend", touchEndListener);
152
+ }, [inputRef, menuRef, close]);
153
+ const Input = useMemo(() => (multiline ? TextArea : InputGroup), [multiline]);
154
+ return (
155
+ <Popover
156
+ portalClassName={"roamjs-autocomplete-input"}
157
+ targetClassName={"roamjs-autocomplete-input-target"}
158
+ captureDismiss={true}
159
+ isOpen={isOpen}
160
+ onOpened={open}
161
+ minimal
162
+ autoFocus={false}
163
+ enforceFocus={false}
164
+ position={PopoverPosition.BOTTOM_LEFT}
165
+ modifiers={{
166
+ flip: { enabled: false },
167
+ preventOverflow: { enabled: false },
168
+ }}
169
+ content={
170
+ <Menu className={"max-h-64 overflow-auto max-w-md"} ulRef={menuRef}>
171
+ {items.map((t, i) => {
172
+ const onClick = () => {
173
+ setIsTyping(false);
174
+ setValue(t);
175
+ setQuery(itemToQuery(t));
176
+ inputRef.current?.focus();
177
+ };
178
+ const sharedProps = {
179
+ onClick,
180
+ onTouchEnd: onClick,
181
+ active: activeIndex === i,
182
+ };
183
+ return renderItem ? (
184
+ <React.Fragment key={i}>
185
+ {renderItem?.({
186
+ item: t,
187
+ ...sharedProps,
188
+ })}
189
+ </React.Fragment>
190
+ ) : (
191
+ <MenuItem
192
+ text={itemToQuery(t)}
193
+ key={i}
194
+ multiline
195
+ {...sharedProps}
196
+ />
197
+ );
198
+ })}
199
+ </Menu>
200
+ }
201
+ target={
202
+ <Input
203
+ disabled={disabled}
204
+ value={query}
205
+ onChange={(e) => {
206
+ setIsTyping(true);
207
+ setQuery(e.target.value);
208
+ }}
209
+ autoFocus={autoFocus}
210
+ placeholder={placeholder}
211
+ onKeyDown={(e) => {
212
+ if (e.key === "Escape") {
213
+ e.stopPropagation();
214
+ close();
215
+ } else {
216
+ onKeyDown(e);
217
+ }
218
+ }}
219
+ id={id}
220
+ onClick={() => setIsTyping(true)}
221
+ onBlur={(e) => {
222
+ if (
223
+ e.relatedTarget === null ||
224
+ !(e.relatedTarget as HTMLElement).closest?.(
225
+ ".roamjs-autocomplete-input"
226
+ )
227
+ ) {
228
+ setIsTyping(false);
229
+ }
230
+ if (onBlur) {
231
+ onBlur(e.target.value);
232
+ }
233
+ }}
234
+ inputRef={inputRef}
235
+ {...(showButton
236
+ ? {
237
+ rightElement: (
238
+ <Button icon={"add"} minimal onClick={() => onEnter()} />
239
+ ),
240
+ }
241
+ : {})}
242
+ />
243
+ }
244
+ />
245
+ );
246
+ };
247
+
248
+ export default AutocompleteInput;
@@ -1,7 +1,11 @@
1
1
  import React from "react";
2
2
  import createBlock from "../writes/createBlock";
3
3
 
4
- type BlockErrorBoundaryProps = { blockUid: string; message: string };
4
+ type BlockErrorBoundaryProps = {
5
+ blockUid: string;
6
+ message: string;
7
+ children: React.ReactNode;
8
+ };
5
9
  type BlockErrorBoundaryState = { hasError: boolean };
6
10
 
7
11
  class BlockErrorBoundary extends React.Component<