@designtools/next-plugin 0.1.8 → 0.1.10

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @designtools/next-plugin
2
2
 
3
- Next.js config wrapper for [@designtools/codesurface](../codesurface). Adds source location annotations and mounts the selection overlay — development only.
3
+ Next.js config wrapper for [@designtools/surface](../surface). Adds source location annotations and mounts the selection overlay — development only.
4
4
 
5
5
  ## Installation
6
6
 
@@ -40,9 +40,9 @@ Runs a Babel pass over every `.tsx` / `.jsx` file (excluding `node_modules`) tha
40
40
 
41
41
  SWC stays enabled as the primary compiler — Babel is only used for this annotation pass.
42
42
 
43
- ### 2. CodeSurface mount loader
43
+ ### 2. Surface mount loader
44
44
 
45
- Transforms your root layout file (`app/layout.tsx` or `src/app/layout.tsx`) to auto-mount the `<CodeSurface />` selection overlay component. This component handles element selection, hover highlighting, inline style previews, and postMessage communication with the editor UI.
45
+ Transforms your root layout file (`app/layout.tsx` or `src/app/layout.tsx`) to auto-mount the `<Surface />` selection overlay component. This component handles element selection, hover highlighting, inline style previews, and postMessage communication with the editor UI.
46
46
 
47
47
  Both loaders are skipped entirely in production builds.
48
48
 
@@ -51,7 +51,21 @@ Both loaders are skipped entirely in production builds.
51
51
  | Export | Description |
52
52
  |--------|-------------|
53
53
  | `@designtools/next-plugin` | `withDesigntools()` config wrapper |
54
- | `@designtools/next-plugin/codesurface` | `<CodeSurface />` React component (mounted automatically — you shouldn't need to import this directly) |
54
+ | `@designtools/next-plugin/surface` | `<Surface />` React component (mounted automatically — you shouldn't need to import this directly) |
55
+
56
+ ## Supported styling systems
57
+
58
+ All styling systems supported by Surface work with the Next.js plugin:
59
+
60
+ | System | Status |
61
+ |--------|--------|
62
+ | Tailwind CSS v3 / v4 | Stable |
63
+ | CSS Variables | Stable |
64
+ | Plain CSS | Stable |
65
+ | CSS Modules | Stable |
66
+ | Sass / SCSS | Planned |
67
+
68
+ See the [Surface README](../surface/README.md) for the full support matrix.
55
69
 
56
70
  ## License
57
71
 
@@ -35,7 +35,7 @@ function codesurfaceMountLoader(source) {
35
35
  }
36
36
  const importStatements = [
37
37
  `import { CodeSurface } from "@designtools/next-plugin/codesurface";`,
38
- `import "./designtools-registry";`
38
+ `import { DesigntoolsRegistry } from "./designtools-registry";`
39
39
  ].join("\n") + "\n";
40
40
  let modified = source;
41
41
  const firstImportIndex = source.indexOf("import ");
@@ -46,7 +46,7 @@ function codesurfaceMountLoader(source) {
46
46
  }
47
47
  modified = modified.replace(
48
48
  /(\{children\})/,
49
- `<CodeSurface />
49
+ `<CodeSurface /><DesigntoolsRegistry />
50
50
  $1`
51
51
  );
52
52
  callback(null, modified);
@@ -13,7 +13,7 @@ function codesurfaceMountLoader(source) {
13
13
  }
14
14
  const importStatements = [
15
15
  `import { CodeSurface } from "@designtools/next-plugin/codesurface";`,
16
- `import "./designtools-registry";`
16
+ `import { DesigntoolsRegistry } from "./designtools-registry";`
17
17
  ].join("\n") + "\n";
18
18
  let modified = source;
19
19
  const firstImportIndex = source.indexOf("import ");
@@ -24,7 +24,7 @@ function codesurfaceMountLoader(source) {
24
24
  }
25
25
  modified = modified.replace(
26
26
  /(\{children\})/,
27
- `<CodeSurface />
27
+ `<CodeSurface /><DesigntoolsRegistry />
28
28
  $1`
29
29
  );
30
30
  callback(null, modified);
@@ -312,20 +312,18 @@ function CodeSurface() {
312
312
  const children = [];
313
313
  if (fiber.child) walkFiber(fiber.child, children, scope);
314
314
  const text = el ? getDirectText(el) : "";
315
- if (children.length > 0 || text) {
316
- return {
317
- id: el ? getDomPath(el) : "",
318
- name: `<${tag}>`,
319
- type: "element",
320
- dataSlot: null,
321
- source: el?.getAttribute("data-source") || null,
322
- scope,
323
- textContent: text,
324
- children
325
- };
326
- }
315
+ return {
316
+ id: el ? getDomPath(el) : "",
317
+ name: `<${tag}>`,
318
+ type: "element",
319
+ dataSlot: null,
320
+ source: el?.getAttribute("data-source") || null,
321
+ scope,
322
+ textContent: text,
323
+ children
324
+ };
327
325
  }
328
- if (el?.hasAttribute("data-source") && !skipTags.has(tag)) {
326
+ if (currentTreeMode === "dom" && el?.hasAttribute("data-source") && !skipTags.has(tag)) {
329
327
  const children = [];
330
328
  if (fiber.child) walkFiber(fiber.child, children, scope);
331
329
  const text = el ? getDirectText(el) : "";
@@ -454,14 +452,16 @@ function CodeSurface() {
454
452
  }
455
453
  }
456
454
  }
457
- function sendComponentTree() {
455
+ let currentTreeMode = "components";
456
+ function sendComponentTree(mode) {
457
+ if (mode) currentTreeMode = mode;
458
458
  const tree = buildComponentTree(document.body);
459
459
  window.parent.postMessage({ type: "tool:componentTree", tree }, "*");
460
460
  }
461
461
  let debounceTimer = null;
462
462
  function debouncedSendTree() {
463
463
  if (debounceTimer) clearTimeout(debounceTimer);
464
- debounceTimer = setTimeout(sendComponentTree, 300);
464
+ debounceTimer = setTimeout(() => sendComponentTree(), 300);
465
465
  }
466
466
  const treeObserver = new MutationObserver(debouncedSendTree);
467
467
  treeObserver.observe(document.body, { childList: true, subtree: true });
@@ -716,6 +716,15 @@ function CodeSurface() {
716
716
  if (s.tooltip) s.tooltip.style.display = "none";
717
717
  s.hoveredElement = null;
718
718
  }
719
+ function clearSelection() {
720
+ s.selectedElement = null;
721
+ s.selectedDomPath = null;
722
+ if (s.selectedOverlay) s.selectedOverlay.style.display = "none";
723
+ if (s.overlayRafId) {
724
+ cancelAnimationFrame(s.overlayRafId);
725
+ s.overlayRafId = null;
726
+ }
727
+ }
719
728
  function onMouseMove(e) {
720
729
  if (!s.selectionMode || !s.highlightOverlay || !s.tooltip) return;
721
730
  const el = document.elementFromPoint(e.clientX, e.clientY);
@@ -756,6 +765,9 @@ function CodeSurface() {
756
765
  case "tool:exitSelectionMode":
757
766
  exitSelectionMode();
758
767
  break;
768
+ case "tool:clearSelection":
769
+ clearSelection();
770
+ break;
759
771
  case "tool:previewInlineStyle": {
760
772
  if (s.selectedElement && s.selectedElement instanceof HTMLElement) {
761
773
  const prop = msg.property;
@@ -821,7 +833,7 @@ function CodeSurface() {
821
833
  }
822
834
  break;
823
835
  case "tool:requestComponentTree":
824
- sendComponentTree();
836
+ sendComponentTree(msg.mode || "components");
825
837
  break;
826
838
  case "tool:highlightByTreeId": {
827
839
  const id = msg.id;
@@ -290,20 +290,18 @@ function CodeSurface() {
290
290
  const children = [];
291
291
  if (fiber.child) walkFiber(fiber.child, children, scope);
292
292
  const text = el ? getDirectText(el) : "";
293
- if (children.length > 0 || text) {
294
- return {
295
- id: el ? getDomPath(el) : "",
296
- name: `<${tag}>`,
297
- type: "element",
298
- dataSlot: null,
299
- source: el?.getAttribute("data-source") || null,
300
- scope,
301
- textContent: text,
302
- children
303
- };
304
- }
293
+ return {
294
+ id: el ? getDomPath(el) : "",
295
+ name: `<${tag}>`,
296
+ type: "element",
297
+ dataSlot: null,
298
+ source: el?.getAttribute("data-source") || null,
299
+ scope,
300
+ textContent: text,
301
+ children
302
+ };
305
303
  }
306
- if (el?.hasAttribute("data-source") && !skipTags.has(tag)) {
304
+ if (currentTreeMode === "dom" && el?.hasAttribute("data-source") && !skipTags.has(tag)) {
307
305
  const children = [];
308
306
  if (fiber.child) walkFiber(fiber.child, children, scope);
309
307
  const text = el ? getDirectText(el) : "";
@@ -432,14 +430,16 @@ function CodeSurface() {
432
430
  }
433
431
  }
434
432
  }
435
- function sendComponentTree() {
433
+ let currentTreeMode = "components";
434
+ function sendComponentTree(mode) {
435
+ if (mode) currentTreeMode = mode;
436
436
  const tree = buildComponentTree(document.body);
437
437
  window.parent.postMessage({ type: "tool:componentTree", tree }, "*");
438
438
  }
439
439
  let debounceTimer = null;
440
440
  function debouncedSendTree() {
441
441
  if (debounceTimer) clearTimeout(debounceTimer);
442
- debounceTimer = setTimeout(sendComponentTree, 300);
442
+ debounceTimer = setTimeout(() => sendComponentTree(), 300);
443
443
  }
444
444
  const treeObserver = new MutationObserver(debouncedSendTree);
445
445
  treeObserver.observe(document.body, { childList: true, subtree: true });
@@ -694,6 +694,15 @@ function CodeSurface() {
694
694
  if (s.tooltip) s.tooltip.style.display = "none";
695
695
  s.hoveredElement = null;
696
696
  }
697
+ function clearSelection() {
698
+ s.selectedElement = null;
699
+ s.selectedDomPath = null;
700
+ if (s.selectedOverlay) s.selectedOverlay.style.display = "none";
701
+ if (s.overlayRafId) {
702
+ cancelAnimationFrame(s.overlayRafId);
703
+ s.overlayRafId = null;
704
+ }
705
+ }
697
706
  function onMouseMove(e) {
698
707
  if (!s.selectionMode || !s.highlightOverlay || !s.tooltip) return;
699
708
  const el = document.elementFromPoint(e.clientX, e.clientY);
@@ -734,6 +743,9 @@ function CodeSurface() {
734
743
  case "tool:exitSelectionMode":
735
744
  exitSelectionMode();
736
745
  break;
746
+ case "tool:clearSelection":
747
+ clearSelection();
748
+ break;
737
749
  case "tool:previewInlineStyle": {
738
750
  if (s.selectedElement && s.selectedElement instanceof HTMLElement) {
739
751
  const prop = msg.property;
@@ -799,7 +811,7 @@ function CodeSurface() {
799
811
  }
800
812
  break;
801
813
  case "tool:requestComponentTree":
802
- sendComponentTree();
814
+ sendComponentTree(msg.mode || "components");
803
815
  break;
804
816
  case "tool:highlightByTreeId": {
805
817
  const id = msg.id;
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Next.js config wrapper that adds the designtools source annotation loader
3
- * and auto-mounts the <CodeSurface /> selection component in development.
3
+ * and auto-mounts the <Surface /> selection component in development.
4
4
  *
5
5
  * Usage:
6
6
  * import { withDesigntools } from "@designtools/next-plugin";
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Next.js config wrapper that adds the designtools source annotation loader
3
- * and auto-mounts the <CodeSurface /> selection component in development.
3
+ * and auto-mounts the <Surface /> selection component in development.
4
4
  *
5
5
  * Usage:
6
6
  * import { withDesigntools } from "@designtools/next-plugin";
package/dist/index.js CHANGED
@@ -50,11 +50,17 @@ const COMPONENT_REGISTRY: Record<string, () => Promise<any>> = {
50
50
  ${registryEntries}
51
51
  };
52
52
 
53
- // Self-register on window so CodeSurface can access it without
53
+ // Self-register on window so Surface can access it without
54
54
  // passing functions through the RSC serialization boundary.
55
55
  if (typeof window !== "undefined") {
56
56
  (window as any).__DESIGNTOOLS_REGISTRY__ = COMPONENT_REGISTRY;
57
57
  }
58
+
59
+ // Exported as a rendered component to prevent tree-shaking of the
60
+ // side-effect registration above. The mount loader renders this in layout.
61
+ export function DesigntoolsRegistry() {
62
+ return null;
63
+ }
58
64
  `;
59
65
  import_fs.default.writeFileSync(import_path.default.join(appDir, REGISTRY_FILE), content, "utf-8");
60
66
  ensureGitignore(projectRoot);
@@ -117,7 +123,7 @@ function withDesigntools(nextConfig = {}) {
117
123
  ],
118
124
  use: [
119
125
  {
120
- loader: import_path2.default.resolve(__dirname, "codesurface-mount-loader.js")
126
+ loader: import_path2.default.resolve(__dirname, "surface-mount-loader.js")
121
127
  }
122
128
  ]
123
129
  });
@@ -138,40 +144,40 @@ function withDesigntools(nextConfig = {}) {
138
144
  }
139
145
  };
140
146
  const mountLoader = {
141
- loader: import_path2.default.resolve(__dirname, "codesurface-mount-loader.js")
147
+ loader: import_path2.default.resolve(__dirname, "surface-mount-loader.js")
142
148
  };
143
149
  const sourceRule = {
144
150
  loaders: [sourceLoader],
145
- as: "*.tsx",
146
151
  condition: {
147
- path: /\.(tsx|jsx)$/
152
+ not: "foreign"
148
153
  }
149
154
  };
150
- const wildcardGlob = "{*,designtools-source}";
151
- let wildcardRule = nextConfig.turbopack?.rules?.[wildcardGlob] ?? [];
152
- wildcardRule = [
153
- ...Array.isArray(wildcardRule) ? wildcardRule : [wildcardRule],
154
- sourceRule
155
- ];
156
155
  const mountRule = {
157
156
  loaders: [mountLoader],
158
- as: "*.tsx",
159
157
  condition: {
160
- path: /layout\.(tsx|jsx)$/
158
+ all: [
159
+ { not: "foreign" },
160
+ { path: /layout\.(tsx|jsx)$/ }
161
+ ]
161
162
  }
162
163
  };
163
- const mountGlob = "{*,designtools-mount}";
164
- let mountGlobRule = nextConfig.turbopack?.rules?.[mountGlob] ?? [];
165
- mountGlobRule = [
166
- ...Array.isArray(mountGlobRule) ? mountGlobRule : [mountGlobRule],
167
- mountRule
168
- ];
164
+ const existingRules = nextConfig.turbopack?.rules ?? {};
165
+ const tsxRule = existingRules["*.tsx"] ?? [];
166
+ const jsxRule = existingRules["*.jsx"] ?? [];
169
167
  result.turbopack = {
170
168
  ...nextConfig.turbopack,
171
169
  rules: {
172
- ...nextConfig.turbopack?.rules,
173
- [wildcardGlob]: wildcardRule,
174
- [mountGlob]: mountGlobRule
170
+ ...existingRules,
171
+ "*.tsx": [
172
+ ...Array.isArray(tsxRule) ? tsxRule : [tsxRule],
173
+ sourceRule,
174
+ mountRule
175
+ ],
176
+ "*.jsx": [
177
+ ...Array.isArray(jsxRule) ? jsxRule : [jsxRule],
178
+ sourceRule,
179
+ mountRule
180
+ ]
175
181
  }
176
182
  };
177
183
  }
package/dist/index.mjs CHANGED
@@ -18,11 +18,17 @@ const COMPONENT_REGISTRY: Record<string, () => Promise<any>> = {
18
18
  ${registryEntries}
19
19
  };
20
20
 
21
- // Self-register on window so CodeSurface can access it without
21
+ // Self-register on window so Surface can access it without
22
22
  // passing functions through the RSC serialization boundary.
23
23
  if (typeof window !== "undefined") {
24
24
  (window as any).__DESIGNTOOLS_REGISTRY__ = COMPONENT_REGISTRY;
25
25
  }
26
+
27
+ // Exported as a rendered component to prevent tree-shaking of the
28
+ // side-effect registration above. The mount loader renders this in layout.
29
+ export function DesigntoolsRegistry() {
30
+ return null;
31
+ }
26
32
  `;
27
33
  fs.writeFileSync(path.join(appDir, REGISTRY_FILE), content, "utf-8");
28
34
  ensureGitignore(projectRoot);
@@ -85,7 +91,7 @@ function withDesigntools(nextConfig = {}) {
85
91
  ],
86
92
  use: [
87
93
  {
88
- loader: path2.resolve(__dirname, "codesurface-mount-loader.js")
94
+ loader: path2.resolve(__dirname, "surface-mount-loader.js")
89
95
  }
90
96
  ]
91
97
  });
@@ -106,40 +112,40 @@ function withDesigntools(nextConfig = {}) {
106
112
  }
107
113
  };
108
114
  const mountLoader = {
109
- loader: path2.resolve(__dirname, "codesurface-mount-loader.js")
115
+ loader: path2.resolve(__dirname, "surface-mount-loader.js")
110
116
  };
111
117
  const sourceRule = {
112
118
  loaders: [sourceLoader],
113
- as: "*.tsx",
114
119
  condition: {
115
- path: /\.(tsx|jsx)$/
120
+ not: "foreign"
116
121
  }
117
122
  };
118
- const wildcardGlob = "{*,designtools-source}";
119
- let wildcardRule = nextConfig.turbopack?.rules?.[wildcardGlob] ?? [];
120
- wildcardRule = [
121
- ...Array.isArray(wildcardRule) ? wildcardRule : [wildcardRule],
122
- sourceRule
123
- ];
124
123
  const mountRule = {
125
124
  loaders: [mountLoader],
126
- as: "*.tsx",
127
125
  condition: {
128
- path: /layout\.(tsx|jsx)$/
126
+ all: [
127
+ { not: "foreign" },
128
+ { path: /layout\.(tsx|jsx)$/ }
129
+ ]
129
130
  }
130
131
  };
131
- const mountGlob = "{*,designtools-mount}";
132
- let mountGlobRule = nextConfig.turbopack?.rules?.[mountGlob] ?? [];
133
- mountGlobRule = [
134
- ...Array.isArray(mountGlobRule) ? mountGlobRule : [mountGlobRule],
135
- mountRule
136
- ];
132
+ const existingRules = nextConfig.turbopack?.rules ?? {};
133
+ const tsxRule = existingRules["*.tsx"] ?? [];
134
+ const jsxRule = existingRules["*.jsx"] ?? [];
137
135
  result.turbopack = {
138
136
  ...nextConfig.turbopack,
139
137
  rules: {
140
- ...nextConfig.turbopack?.rules,
141
- [wildcardGlob]: wildcardRule,
142
- [mountGlob]: mountGlobRule
138
+ ...existingRules,
139
+ "*.tsx": [
140
+ ...Array.isArray(tsxRule) ? tsxRule : [tsxRule],
141
+ sourceRule,
142
+ mountRule
143
+ ],
144
+ "*.jsx": [
145
+ ...Array.isArray(jsxRule) ? jsxRule : [jsxRule],
146
+ sourceRule,
147
+ mountRule
148
+ ]
143
149
  }
144
150
  };
145
151
  }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Webpack loader that auto-mounts <Surface /> in the root layout.
3
+ * Only runs in development. Injects the import and component into the JSX.
4
+ *
5
+ * Strategy: Simple string injection — find the {children} pattern in the layout
6
+ * and add <Surface /> alongside it.
7
+ */
8
+ interface LoaderContext {
9
+ resourcePath: string;
10
+ callback(err: Error | null, content?: string): void;
11
+ async(): (err: Error | null, content?: string) => void;
12
+ }
13
+ declare function surfaceMountLoader(this: LoaderContext, source: string): void;
14
+
15
+ export { surfaceMountLoader as default };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Webpack loader that auto-mounts <Surface /> in the root layout.
3
+ * Only runs in development. Injects the import and component into the JSX.
4
+ *
5
+ * Strategy: Simple string injection — find the {children} pattern in the layout
6
+ * and add <Surface /> alongside it.
7
+ */
8
+ interface LoaderContext {
9
+ resourcePath: string;
10
+ callback(err: Error | null, content?: string): void;
11
+ async(): (err: Error | null, content?: string) => void;
12
+ }
13
+ declare function surfaceMountLoader(this: LoaderContext, source: string): void;
14
+
15
+ export { surfaceMountLoader as default };
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/surface-mount-loader.ts
21
+ var surface_mount_loader_exports = {};
22
+ __export(surface_mount_loader_exports, {
23
+ default: () => surfaceMountLoader
24
+ });
25
+ module.exports = __toCommonJS(surface_mount_loader_exports);
26
+ function surfaceMountLoader(source) {
27
+ const callback = this.async();
28
+ if (!source.includes("<html")) {
29
+ callback(null, source);
30
+ return;
31
+ }
32
+ if (source.includes("Surface")) {
33
+ callback(null, source);
34
+ return;
35
+ }
36
+ const importStatements = [
37
+ `import { Surface } from "@designtools/next-plugin/surface";`,
38
+ `import { DesigntoolsRegistry } from "./designtools-registry";`
39
+ ].join("\n") + "\n";
40
+ let modified = source;
41
+ const firstImportIndex = source.indexOf("import ");
42
+ if (firstImportIndex !== -1) {
43
+ modified = source.slice(0, firstImportIndex) + importStatements + source.slice(firstImportIndex);
44
+ } else {
45
+ modified = importStatements + source;
46
+ }
47
+ modified = modified.replace(
48
+ /(\{children\})/,
49
+ `<Surface /><DesigntoolsRegistry />
50
+ $1`
51
+ );
52
+ callback(null, modified);
53
+ }
@@ -0,0 +1,34 @@
1
+ import "./chunk-Y6FXYEAI.mjs";
2
+
3
+ // src/surface-mount-loader.ts
4
+ function surfaceMountLoader(source) {
5
+ const callback = this.async();
6
+ if (!source.includes("<html")) {
7
+ callback(null, source);
8
+ return;
9
+ }
10
+ if (source.includes("Surface")) {
11
+ callback(null, source);
12
+ return;
13
+ }
14
+ const importStatements = [
15
+ `import { Surface } from "@designtools/next-plugin/surface";`,
16
+ `import { DesigntoolsRegistry } from "./designtools-registry";`
17
+ ].join("\n") + "\n";
18
+ let modified = source;
19
+ const firstImportIndex = source.indexOf("import ");
20
+ if (firstImportIndex !== -1) {
21
+ modified = source.slice(0, firstImportIndex) + importStatements + source.slice(firstImportIndex);
22
+ } else {
23
+ modified = importStatements + source;
24
+ }
25
+ modified = modified.replace(
26
+ /(\{children\})/,
27
+ `<Surface /><DesigntoolsRegistry />
28
+ $1`
29
+ );
30
+ callback(null, modified);
31
+ }
32
+ export {
33
+ surfaceMountLoader as default
34
+ };
@@ -0,0 +1,5 @@
1
+ import * as react from 'react';
2
+
3
+ declare function Surface(): react.ReactPortal | null;
4
+
5
+ export { Surface };
@@ -0,0 +1,5 @@
1
+ import * as react from 'react';
2
+
3
+ declare function Surface(): react.ReactPortal | null;
4
+
5
+ export { Surface };