@jupyterlab/json-extension 4.0.0-alpha.9 → 4.0.0-beta.1

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.
@@ -11,6 +11,7 @@ export interface IProps {
11
11
  * The application language translator.
12
12
  */
13
13
  translator?: ITranslator;
14
+ forwardedRef?: React.Ref<HTMLDivElement>;
14
15
  }
15
16
  /**
16
17
  * The state of the JSON tree component.
@@ -28,6 +29,7 @@ export declare class Component extends React.Component<IProps, IState> {
28
29
  value: string;
29
30
  };
30
31
  timer: number;
32
+ componentDidMount(): void;
31
33
  handleChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
32
34
  render(): JSX.Element;
33
35
  }
package/lib/component.js CHANGED
@@ -1,11 +1,21 @@
1
1
  // Copyright (c) Jupyter Development Team.
2
2
  // Distributed under the terms of the Modified BSD License.
3
+ import { jupyterHighlightStyle } from '@jupyterlab/codemirror';
3
4
  import { nullTranslator } from '@jupyterlab/translation';
4
5
  import { InputGroup } from '@jupyterlab/ui-components';
6
+ import { tags } from '@lezer/highlight';
5
7
  import { JSONExt } from '@lumino/coreutils';
6
8
  import * as React from 'react';
7
- import Highlight from 'react-highlighter';
9
+ import Highlighter from 'react-highlight-words';
8
10
  import { JSONTree } from 'react-json-tree';
11
+ import { StyleModule } from 'style-mod';
12
+ /**
13
+ * Get the CodeMirror style for a given tag.
14
+ */
15
+ function getStyle(tag) {
16
+ var _a;
17
+ return (_a = jupyterHighlightStyle.style([tag])) !== null && _a !== void 0 ? _a : '';
18
+ }
9
19
  /**
10
20
  * A component that renders JSON data as a collapsible tree.
11
21
  */
@@ -23,21 +33,24 @@ export class Component extends React.Component {
23
33
  }, 300);
24
34
  };
25
35
  }
36
+ componentDidMount() {
37
+ StyleModule.mount(document, jupyterHighlightStyle.module);
38
+ }
26
39
  render() {
27
40
  const translator = this.props.translator || nullTranslator;
28
41
  const trans = translator.load('jupyterlab');
29
- const { data, metadata } = this.props;
42
+ const { data, metadata, forwardedRef } = this.props;
30
43
  const root = metadata && metadata.root ? metadata.root : 'root';
31
44
  const keyPaths = this.state.filter
32
45
  ? filterPaths(data, this.state.filter, [root])
33
46
  : [root];
34
- return (React.createElement("div", { className: "container" },
47
+ return (React.createElement("div", { className: "container", ref: forwardedRef },
35
48
  React.createElement(InputGroup, { className: "filter", type: "text", placeholder: trans.__('Filter…'), onChange: this.handleChange, value: this.state.value, rightIcon: "ui-components:search" }),
36
49
  React.createElement(JSONTree, { data: data, collectionLimit: 100, theme: {
37
50
  extend: theme,
38
- valueLabel: 'cm-variable',
39
- valueText: 'cm-string',
40
- nestedNodeItemString: 'cm-comment'
51
+ valueLabel: getStyle(tags.variableName),
52
+ valueText: getStyle(tags.string),
53
+ nestedNodeItemString: getStyle(tags.comment)
41
54
  }, invertTheme: false, keyPath: [root], getItemString: (type, data, itemType, itemString) => Array.isArray(data) ? (
42
55
  // Always display array type and the number of items i.e. "[] 2 items".
43
56
  React.createElement("span", null,
@@ -47,29 +60,19 @@ export class Component extends React.Component {
47
60
  // Only display object type when it's empty i.e. "{}".
48
61
  React.createElement("span", null, itemType)) : (null // Upstream typings don't accept null, but it should be ok
49
62
  ), labelRenderer: ([label, type]) => {
50
- // let className = 'cm-variable';
51
- // if (type === 'root') {
52
- // className = 'cm-variable-2';
53
- // }
54
- // if (type === 'array') {
55
- // className = 'cm-variable-2';
56
- // }
57
- // if (type === 'Object') {
58
- // className = 'cm-variable-3';
59
- // }
60
- return (React.createElement("span", { className: "cm-keyword" },
61
- React.createElement(Highlight, { search: this.state.filter, matchStyle: { backgroundColor: 'yellow' } }, `${label}: `)));
63
+ return (React.createElement("span", { className: getStyle(tags.keyword) },
64
+ React.createElement(Highlighter, { searchWords: [this.state.filter], textToHighlight: `${label}`, highlightClassName: "jp-mod-selected" })));
62
65
  }, valueRenderer: raw => {
63
- let className = 'cm-string';
66
+ let className = getStyle(tags.string);
64
67
  if (typeof raw === 'number') {
65
- className = 'cm-number';
68
+ className = getStyle(tags.number);
66
69
  }
67
70
  if (raw === 'true' || raw === 'false') {
68
- className = 'cm-keyword';
71
+ className = getStyle(tags.keyword);
69
72
  }
70
73
  return (React.createElement("span", { className: className },
71
- React.createElement(Highlight, { search: this.state.filter, matchStyle: { backgroundColor: 'yellow' } }, `${raw}`)));
72
- }, shouldExpandNode: (keyPath, data, level) => metadata && metadata.expanded
74
+ React.createElement(Highlighter, { searchWords: [this.state.filter], textToHighlight: `${raw}`, highlightClassName: "jp-mod-selected" })));
75
+ }, shouldExpandNodeInitially: (keyPath, data, level) => metadata && metadata.expanded
73
76
  ? true
74
77
  : keyPaths.join(',').includes(keyPath.join(',')) })));
75
78
  }
@@ -1 +1 @@
1
- {"version":3,"file":"component.js","sourceRoot":"","sources":["../src/component.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"component.js","sourceRoot":"","sources":["../src/component.tsx"],"names":[],"mappings":"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"}
package/lib/index.d.ts CHANGED
@@ -30,6 +30,7 @@ export declare class RenderedJSON extends Widget implements IRenderMime.IRendere
30
30
  protected onBeforeDetach(msg: Message): void;
31
31
  translator: ITranslator;
32
32
  private _mimeType;
33
+ private _rootDOM;
33
34
  }
34
35
  /**
35
36
  * A mime renderer factory for JSON data.
package/lib/index.js CHANGED
@@ -8,8 +8,7 @@ import { Printing } from '@jupyterlab/apputils';
8
8
  import { nullTranslator } from '@jupyterlab/translation';
9
9
  import { Widget } from '@lumino/widgets';
10
10
  import * as React from 'react';
11
- import * as ReactDOM from 'react-dom';
12
- import { Component } from './component';
11
+ import { createRoot } from 'react-dom/client';
13
12
  /**
14
13
  * The CSS class to add to the JSON Widget.
15
14
  */
@@ -27,9 +26,9 @@ export class RenderedJSON extends Widget {
27
26
  */
28
27
  constructor(options) {
29
28
  super();
29
+ this._rootDOM = null;
30
30
  this.addClass(CSS_CLASS);
31
31
  this.addClass('CodeMirror');
32
- this.addClass('cm-s-jupyter');
33
32
  this._mimeType = options.mimeType;
34
33
  this.translator = options.translator || nullTranslator;
35
34
  }
@@ -39,13 +38,15 @@ export class RenderedJSON extends Widget {
39
38
  /**
40
39
  * Render JSON into this widget's node.
41
40
  */
42
- renderModel(model) {
41
+ async renderModel(model) {
42
+ const { Component } = await import('./component');
43
43
  const data = (model.data[this._mimeType] || {});
44
44
  const metadata = (model.metadata[this._mimeType] || {});
45
+ if (this._rootDOM === null) {
46
+ this._rootDOM = createRoot(this.node);
47
+ }
45
48
  return new Promise((resolve, reject) => {
46
- ReactDOM.render(React.createElement(Component, { data: data, metadata: metadata, translator: this.translator }), this.node, () => {
47
- resolve();
48
- });
49
+ this._rootDOM.render(React.createElement(Component, { data: data, metadata: metadata, translator: this.translator, forwardedRef: () => resolve() }));
49
50
  });
50
51
  }
51
52
  /**
@@ -53,7 +54,10 @@ export class RenderedJSON extends Widget {
53
54
  */
54
55
  onBeforeDetach(msg) {
55
56
  // Unmount the component so it can tear down.
56
- ReactDOM.unmountComponentAtNode(this.node);
57
+ if (this._rootDOM) {
58
+ this._rootDOM.unmount();
59
+ this._rootDOM = null;
60
+ }
57
61
  }
58
62
  }
59
63
  /**
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,2DAA2D;AAC3D;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,OAAO,EAAe,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAGtE,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,QAAQ,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC;;GAEG;AACH,MAAM,SAAS,GAAG,iBAAiB,CAAC;AAEpC;;GAEG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,kBAAkB,CAAC;AAE5C;;GAEG;AACH,MAAM,OAAO,YACX,SAAQ,MAAM;IAEd;;OAEG;IACH,YAAY,OAAqC;QAC/C,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QACzB,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QAC5B,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;QAC9B,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC;QAClC,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,cAAc,CAAC;IACzD,CAAC;IAED,CAAC,QAAQ,CAAC,MAAM,CAAC;QACf,OAAO,GAAkB,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IACzD,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,KAA6B;QACvC,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAA2B,CAAC;QAC1E,MAAM,QAAQ,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAe,CAAC;QACtE,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC3C,QAAQ,CAAC,MAAM,CACb,oBAAC,SAAS,IACR,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,IAAI,CAAC,UAAU,GAC3B,EACF,IAAI,CAAC,IAAI,EACT,GAAG,EAAE;gBACH,OAAO,EAAE,CAAC;YACZ,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACO,cAAc,CAAC,GAAY;QACnC,6CAA6C;QAC7C,QAAQ,CAAC,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7C,CAAC;CAIF;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAiC;IAC3D,IAAI,EAAE,IAAI;IACV,SAAS,EAAE,CAAC,SAAS,CAAC;IACtB,cAAc,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,YAAY,CAAC,OAAO,CAAC;CACrD,CAAC;AAEF,MAAM,UAAU,GAAsD;IACpE;QACE,EAAE,EAAE,oCAAoC;QACxC,eAAe;QACf,IAAI,EAAE,CAAC;QACP,QAAQ,EAAE,MAAM;QAChB,4BAA4B,EAAE;YAC5B,IAAI,EAAE,MAAM;YACZ,+CAA+C;YAC/C,eAAe,EAAE,MAAM;YACvB,SAAS,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC;YAC1C,UAAU,EAAE,CAAC,MAAM,CAAC;SACrB;KACF;CACF,CAAC;AAEF,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jupyterlab/json-extension",
3
- "version": "4.0.0-alpha.9",
3
+ "version": "4.0.0-beta.1",
4
4
  "description": "JupyterLab - JSON Renderer",
5
5
  "homepage": "https://github.com/jupyterlab/jupyterlab",
6
6
  "bugs": {
@@ -23,7 +23,8 @@
23
23
  },
24
24
  "files": [
25
25
  "lib/*.{d.ts,js,js.map}",
26
- "style/*"
26
+ "style/*",
27
+ "src/**/*.{ts,tsx}"
27
28
  ],
28
29
  "scripts": {
29
30
  "build": "tsc -b",
@@ -32,25 +33,28 @@
32
33
  "watch": "tsc -b --watch"
33
34
  },
34
35
  "dependencies": {
35
- "@jupyterlab/apputils": "^4.0.0-alpha.9",
36
- "@jupyterlab/rendermime-interfaces": "^4.0.0-alpha.9",
37
- "@jupyterlab/translation": "^4.0.0-alpha.9",
38
- "@jupyterlab/ui-components": "^4.0.0-alpha.24",
39
- "@lumino/coreutils": "^1.12.0",
40
- "@lumino/messaging": "^1.10.1",
41
- "@lumino/widgets": "^1.31.1",
42
- "react": "^17.0.1",
43
- "react-dom": "^17.0.1",
44
- "react-highlighter": "^0.4.3",
45
- "react-json-tree": "^0.16.1"
36
+ "@jupyterlab/apputils": "^4.0.0-beta.1",
37
+ "@jupyterlab/codemirror": "^4.0.0-beta.1",
38
+ "@jupyterlab/rendermime-interfaces": "^3.8.0-beta.1",
39
+ "@jupyterlab/translation": "^4.0.0-beta.1",
40
+ "@jupyterlab/ui-components": "^4.0.0-beta.1",
41
+ "@lezer/highlight": "^1.0.0",
42
+ "@lumino/coreutils": "^2.0.0",
43
+ "@lumino/messaging": "^2.0.0",
44
+ "@lumino/widgets": "^2.0.1",
45
+ "react": "^18.2.0",
46
+ "react-dom": "^18.2.0",
47
+ "react-highlight-words": "^0.20.0",
48
+ "react-json-tree": "^0.18.0",
49
+ "style-mod": "^4.0.0"
46
50
  },
47
51
  "devDependencies": {
48
- "@types/react": "^17.0.0",
49
- "@types/react-dom": "^17.0.0",
50
- "@types/react-highlighter": "^0.3.4",
52
+ "@types/react": "^18.0.26",
53
+ "@types/react-dom": "^18.0.9",
54
+ "@types/react-highlight-words": "^0.16.4",
51
55
  "rimraf": "~3.0.0",
52
- "typedoc": "~0.22.10",
53
- "typescript": "~4.6.3"
56
+ "typedoc": "~0.23.25",
57
+ "typescript": "~5.0.2"
54
58
  },
55
59
  "publishConfig": {
56
60
  "access": "public"
@@ -0,0 +1,209 @@
1
+ // Copyright (c) Jupyter Development Team.
2
+ // Distributed under the terms of the Modified BSD License.
3
+
4
+ import { jupyterHighlightStyle } from '@jupyterlab/codemirror';
5
+ import { ITranslator, nullTranslator } from '@jupyterlab/translation';
6
+ import { InputGroup } from '@jupyterlab/ui-components';
7
+ import { Tag, tags } from '@lezer/highlight';
8
+ import { JSONArray, JSONExt, JSONObject, JSONValue } from '@lumino/coreutils';
9
+ import * as React from 'react';
10
+ import Highlighter from 'react-highlight-words';
11
+ import { JSONTree } from 'react-json-tree';
12
+ import { StyleModule } from 'style-mod';
13
+
14
+ /**
15
+ * The properties for the JSON tree component.
16
+ */
17
+ export interface IProps {
18
+ data: NonNullable<JSONValue>;
19
+ metadata?: JSONObject;
20
+
21
+ /**
22
+ * The application language translator.
23
+ */
24
+ translator?: ITranslator;
25
+ forwardedRef?: React.Ref<HTMLDivElement>;
26
+ }
27
+
28
+ /**
29
+ * The state of the JSON tree component.
30
+ */
31
+ export interface IState {
32
+ filter?: string;
33
+ value: string;
34
+ }
35
+
36
+ /**
37
+ * Get the CodeMirror style for a given tag.
38
+ */
39
+ function getStyle(tag: Tag): string {
40
+ return jupyterHighlightStyle.style([tag]) ?? '';
41
+ }
42
+
43
+ /**
44
+ * A component that renders JSON data as a collapsible tree.
45
+ */
46
+ export class Component extends React.Component<IProps, IState> {
47
+ state = { filter: '', value: '' };
48
+
49
+ timer: number = 0;
50
+
51
+ componentDidMount(): void {
52
+ StyleModule.mount(document, jupyterHighlightStyle.module as StyleModule);
53
+ }
54
+
55
+ handleChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
56
+ const { value } = event.target;
57
+ this.setState({ value });
58
+ window.clearTimeout(this.timer);
59
+ this.timer = window.setTimeout(() => {
60
+ this.setState({ filter: value });
61
+ }, 300);
62
+ };
63
+
64
+ render(): JSX.Element {
65
+ const translator = this.props.translator || nullTranslator;
66
+ const trans = translator.load('jupyterlab');
67
+
68
+ const { data, metadata, forwardedRef } = this.props;
69
+ const root = metadata && metadata.root ? (metadata.root as string) : 'root';
70
+ const keyPaths = this.state.filter
71
+ ? filterPaths(data, this.state.filter, [root])
72
+ : [root];
73
+ return (
74
+ <div className="container" ref={forwardedRef}>
75
+ <InputGroup
76
+ className="filter"
77
+ type="text"
78
+ placeholder={trans.__('Filter…')}
79
+ onChange={this.handleChange}
80
+ value={this.state.value}
81
+ rightIcon="ui-components:search"
82
+ />
83
+ <JSONTree
84
+ data={data}
85
+ collectionLimit={100}
86
+ theme={{
87
+ extend: theme,
88
+ valueLabel: getStyle(tags.variableName),
89
+ valueText: getStyle(tags.string),
90
+ nestedNodeItemString: getStyle(tags.comment)
91
+ }}
92
+ invertTheme={false}
93
+ keyPath={[root]}
94
+ getItemString={(type, data, itemType, itemString) =>
95
+ Array.isArray(data) ? (
96
+ // Always display array type and the number of items i.e. "[] 2 items".
97
+ <span>
98
+ {itemType} {itemString}
99
+ </span>
100
+ ) : Object.keys(data as object).length === 0 ? (
101
+ // Only display object type when it's empty i.e. "{}".
102
+ <span>{itemType}</span>
103
+ ) : (
104
+ null! // Upstream typings don't accept null, but it should be ok
105
+ )
106
+ }
107
+ labelRenderer={([label, type]) => {
108
+ return (
109
+ <span className={getStyle(tags.keyword)}>
110
+ <Highlighter
111
+ searchWords={[this.state.filter]}
112
+ textToHighlight={`${label}`}
113
+ highlightClassName="jp-mod-selected"
114
+ ></Highlighter>
115
+ </span>
116
+ );
117
+ }}
118
+ valueRenderer={raw => {
119
+ let className = getStyle(tags.string);
120
+ if (typeof raw === 'number') {
121
+ className = getStyle(tags.number);
122
+ }
123
+ if (raw === 'true' || raw === 'false') {
124
+ className = getStyle(tags.keyword);
125
+ }
126
+ return (
127
+ <span className={className}>
128
+ <Highlighter
129
+ searchWords={[this.state.filter]}
130
+ textToHighlight={`${raw}`}
131
+ highlightClassName="jp-mod-selected"
132
+ ></Highlighter>
133
+ </span>
134
+ );
135
+ }}
136
+ shouldExpandNodeInitially={(keyPath, data, level) =>
137
+ metadata && metadata.expanded
138
+ ? true
139
+ : keyPaths.join(',').includes(keyPath.join(','))
140
+ }
141
+ />
142
+ </div>
143
+ );
144
+ }
145
+ }
146
+
147
+ // Provide an invalid theme object (this is on purpose!) to invalidate the
148
+ // react-json-tree's inline styles that override CodeMirror CSS classes
149
+ const theme = {
150
+ scheme: 'jupyter',
151
+ base00: 'invalid',
152
+ base01: 'invalid',
153
+ base02: 'invalid',
154
+ base03: 'invalid',
155
+ base04: 'invalid',
156
+ base05: 'invalid',
157
+ base06: 'invalid',
158
+ base07: 'invalid',
159
+ base08: 'invalid',
160
+ base09: 'invalid',
161
+ base0A: 'invalid',
162
+ base0B: 'invalid',
163
+ base0C: 'invalid',
164
+ base0D: 'invalid',
165
+ base0E: 'invalid',
166
+ base0F: 'invalid',
167
+ author: 'invalid'
168
+ };
169
+
170
+ function objectIncludes(data: JSONValue, query: string): boolean {
171
+ return JSON.stringify(data).includes(query);
172
+ }
173
+
174
+ function filterPaths(
175
+ data: NonNullable<JSONValue>,
176
+ query: string,
177
+ parent: JSONArray = ['root']
178
+ ): JSONArray {
179
+ if (JSONExt.isArray(data)) {
180
+ return data.reduce((result: JSONArray, item: JSONValue, index: number) => {
181
+ if (item && typeof item === 'object' && objectIncludes(item, query)) {
182
+ return [
183
+ ...result,
184
+ [index, ...parent].join(','),
185
+ ...filterPaths(item, query, [index, ...parent])
186
+ ];
187
+ }
188
+ return result;
189
+ }, []) as JSONArray;
190
+ }
191
+ if (JSONExt.isObject(data)) {
192
+ return Object.keys(data).reduce((result: JSONArray, key: string) => {
193
+ const item = data[key];
194
+ if (
195
+ item &&
196
+ typeof item === 'object' &&
197
+ (key.includes(query) || objectIncludes(item, query))
198
+ ) {
199
+ return [
200
+ ...result,
201
+ [key, ...parent].join(','),
202
+ ...filterPaths(item, query, [key, ...parent])
203
+ ];
204
+ }
205
+ return result;
206
+ }, []);
207
+ }
208
+ return [];
209
+ }
package/src/index.tsx ADDED
@@ -0,0 +1,112 @@
1
+ // Copyright (c) Jupyter Development Team.
2
+ // Distributed under the terms of the Modified BSD License.
3
+ /**
4
+ * @packageDocumentation
5
+ * @module json-extension
6
+ */
7
+
8
+ import { Printing } from '@jupyterlab/apputils';
9
+ import { IRenderMime } from '@jupyterlab/rendermime-interfaces';
10
+ import { ITranslator, nullTranslator } from '@jupyterlab/translation';
11
+ import { JSONObject, JSONValue } from '@lumino/coreutils';
12
+ import { Message } from '@lumino/messaging';
13
+ import { Widget } from '@lumino/widgets';
14
+ import * as React from 'react';
15
+ import { createRoot, Root } from 'react-dom/client';
16
+
17
+ /**
18
+ * The CSS class to add to the JSON Widget.
19
+ */
20
+ const CSS_CLASS = 'jp-RenderedJSON';
21
+
22
+ /**
23
+ * The MIME type for JSON.
24
+ */
25
+ export const MIME_TYPE = 'application/json';
26
+
27
+ /**
28
+ * A renderer for JSON data.
29
+ */
30
+ export class RenderedJSON
31
+ extends Widget
32
+ implements IRenderMime.IRenderer, Printing.IPrintable
33
+ {
34
+ /**
35
+ * Create a new widget for rendering JSON.
36
+ */
37
+ constructor(options: IRenderMime.IRendererOptions) {
38
+ super();
39
+ this.addClass(CSS_CLASS);
40
+ this.addClass('CodeMirror');
41
+ this._mimeType = options.mimeType;
42
+ this.translator = options.translator || nullTranslator;
43
+ }
44
+
45
+ [Printing.symbol]() {
46
+ return (): Promise<void> => Printing.printWidget(this);
47
+ }
48
+
49
+ /**
50
+ * Render JSON into this widget's node.
51
+ */
52
+ async renderModel(model: IRenderMime.IMimeModel): Promise<void> {
53
+ const { Component } = await import('./component');
54
+ const data = (model.data[this._mimeType] || {}) as NonNullable<JSONValue>;
55
+ const metadata = (model.metadata[this._mimeType] || {}) as JSONObject;
56
+ if (this._rootDOM === null) {
57
+ this._rootDOM = createRoot(this.node);
58
+ }
59
+ return new Promise<void>((resolve, reject) => {
60
+ this._rootDOM!.render(
61
+ <Component
62
+ data={data}
63
+ metadata={metadata}
64
+ translator={this.translator}
65
+ forwardedRef={() => resolve()}
66
+ />
67
+ );
68
+ });
69
+ }
70
+
71
+ /**
72
+ * Called before the widget is detached from the DOM.
73
+ */
74
+ protected onBeforeDetach(msg: Message): void {
75
+ // Unmount the component so it can tear down.
76
+ if (this._rootDOM) {
77
+ this._rootDOM.unmount();
78
+ this._rootDOM = null;
79
+ }
80
+ }
81
+
82
+ translator: ITranslator;
83
+ private _mimeType: string;
84
+ private _rootDOM: Root | null = null;
85
+ }
86
+
87
+ /**
88
+ * A mime renderer factory for JSON data.
89
+ */
90
+ export const rendererFactory: IRenderMime.IRendererFactory = {
91
+ safe: true,
92
+ mimeTypes: [MIME_TYPE],
93
+ createRenderer: options => new RenderedJSON(options)
94
+ };
95
+
96
+ const extensions: IRenderMime.IExtension | IRenderMime.IExtension[] = [
97
+ {
98
+ id: '@jupyterlab/json-extension:factory',
99
+ rendererFactory,
100
+ rank: 0,
101
+ dataType: 'json',
102
+ documentWidgetFactoryOptions: {
103
+ name: 'JSON',
104
+ // TODO: how to translate label of the factory?
105
+ primaryFileType: 'json',
106
+ fileTypes: ['json', 'notebook', 'geojson'],
107
+ defaultFor: ['json']
108
+ }
109
+ }
110
+ ];
111
+
112
+ export default extensions;
package/style/base.css CHANGED
@@ -41,6 +41,11 @@
41
41
  overflow-y: auto;
42
42
  }
43
43
 
44
+ .jp-RenderedJSON mark.jp-mod-selected {
45
+ background-color: var(--jp-search-unselected-match-background-color);
46
+ color: var(--jp-search-unselected-match-color);
47
+ }
48
+
44
49
  /* Output styles */
45
50
 
46
51
  /* .jp-OutputArea .jp-RenderedJSON {
package/style/index.css CHANGED
@@ -7,5 +7,6 @@
7
7
  @import url('~@lumino/widgets/style/index.css');
8
8
  @import url('~@jupyterlab/ui-components/style/index.css');
9
9
  @import url('~@jupyterlab/apputils/style/index.css');
10
+ @import url('~@jupyterlab/codemirror/style/index.css');
10
11
 
11
12
  @import url('./base.css');
package/style/index.js CHANGED
@@ -7,5 +7,6 @@
7
7
  import '@lumino/widgets/style/index.js';
8
8
  import '@jupyterlab/ui-components/style/index.js';
9
9
  import '@jupyterlab/apputils/style/index.js';
10
+ import '@jupyterlab/codemirror/style/index.js';
10
11
 
11
12
  import './base.css';