@textbus/adapter-react 4.0.0-alpha.41 → 4.0.0-alpha.43

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,30 +1,81 @@
1
- import { useState, useEffect, createElement } from 'react';
2
- import { Subject } from '@tanbo/stream';
3
- import { makeError, VElement, VTextNode, replaceEmpty, invokeListener } from '@textbus/core';
1
+ import { makeError, VElement, VTextNode } from '@textbus/core';
4
2
  import { DomAdapter } from '@textbus/platform-browser';
3
+ import { createElement, useState, useEffect } from 'react';
5
4
 
6
- // hack start
7
- // 在 composition 输入时,浏览器会默认删除占位节点(<br>),这会导致 react 在 diff 时报错
8
- const oldRemoveChild = Node.prototype.removeChild;
9
- Node.prototype.removeChild = function (child) {
10
- if (child) {
11
- if (!child.parentNode) {
12
- return child;
13
- }
14
- }
15
- return oldRemoveChild.call(this, child);
16
- };
17
- // hack end
18
5
  const adapterError = makeError('ReactAdapter');
19
- /**
20
- * Textbus 桥接 React 渲染能力适配器,用于在 React 项目中渲染 Textbus 数据
21
- */
22
- class Adapter extends DomAdapter {
6
+ class ReactAdapter extends DomAdapter {
23
7
  constructor(components, mount) {
24
- super(mount);
25
- this.onViewUpdated = new Subject();
8
+ super({
9
+ createCompositionNode(compositionState, updateNativeCompositionNode) {
10
+ return new VElement('span', {
11
+ style: {
12
+ textDecoration: 'underline'
13
+ },
14
+ ref: (node) => {
15
+ updateNativeCompositionNode(node);
16
+ }
17
+ }, [
18
+ new VTextNode(compositionState.text)
19
+ ]);
20
+ },
21
+ getParentNode(node) {
22
+ return node.parentNode;
23
+ },
24
+ getChildNodes(parentElement) {
25
+ return Array.from(parentElement.childNodes);
26
+ },
27
+ isNativeElementNode(node) {
28
+ return node instanceof HTMLElement;
29
+ },
30
+ getChildByIndex(parentElement, index) {
31
+ return parentElement.childNodes[index];
32
+ },
33
+ getAndUpdateSlotRootNativeElement(vEle, update) {
34
+ const currentRef = vEle.attrs.get('ref');
35
+ if (currentRef) {
36
+ vEle.attrs.set('ref', (v) => {
37
+ update(v);
38
+ if (typeof currentRef === 'function') {
39
+ currentRef(v);
40
+ }
41
+ else if (!currentRef.current) {
42
+ currentRef.current = v;
43
+ }
44
+ });
45
+ }
46
+ else {
47
+ vEle.attrs.set('ref', update);
48
+ }
49
+ },
50
+ componentRender: (component) => {
51
+ const comp = this.components[component.name] || this.components['*'];
52
+ if (comp) {
53
+ component.changeMarker.rendered();
54
+ return createElement(comp, {
55
+ key: component.id,
56
+ component
57
+ });
58
+ }
59
+ throw adapterError(`cannot found view component \`${component.name}\`!`);
60
+ },
61
+ vElementToViewElement(vNode, children) {
62
+ const props = Object.assign({}, (Array.from(vNode.attrs).reduce((a, b) => {
63
+ a[b[0]] = b[1];
64
+ return a;
65
+ }, {})));
66
+ if (vNode.classes.size) {
67
+ props.className = Array.from(vNode.classes).join(' ');
68
+ }
69
+ if (vNode.styles) {
70
+ props.style = Array.from(vNode.styles).reduce((a, b) => {
71
+ a[b[0]] = b[1];
72
+ return a;
73
+ }, {});
74
+ }
75
+ return createElement(vNode.tagName, props, ...children);
76
+ }
77
+ }, mount);
26
78
  this.components = {};
27
- this.componentRendingStack = [];
28
79
  Object.keys(components).forEach(key => {
29
80
  this.components[key] = (props) => {
30
81
  const component = props.component;
@@ -70,101 +121,9 @@ class Adapter extends DomAdapter {
70
121
  };
71
122
  });
72
123
  }
73
- componentRender(component) {
74
- const comp = this.components[component.name] || this.components['*'];
75
- if (comp) {
76
- component.changeMarker.rendered();
77
- return createElement(comp, {
78
- key: component.id,
79
- component
80
- });
81
- }
82
- throw adapterError(`cannot found view component \`${component.name}\`!`);
83
- }
84
- slotRender(slot, slotHostRender, renderEnv) {
85
- var _a;
86
- const context = this.componentRendingStack[this.componentRendingStack.length - 1];
87
- if (context) {
88
- context.__slots__.push(slot);
89
- }
90
- else if (!this.renderedSlotCache.has(slot)) {
91
- throw adapterError(`Unrendered slots must be rendered together with the corresponding "${((_a = slot.parent) === null || _a === void 0 ? void 0 : _a.name) || 'unknown'}" component`);
92
- }
93
- this.renderedSlotCache.set(slot, true);
94
- const vElement = slot.toTree(slotHostRender, renderEnv);
95
- this.slotRootVElementCaches.set(slot, vElement);
96
- const vNodeToJSX = (vNode) => {
97
- const children = [];
98
- if (this.composition && this.composition.slot === slot) {
99
- this.insertCompositionByIndex(slot, vNode, this.composition, () => {
100
- return new VElement('span', {
101
- style: {
102
- textDecoration: 'underline'
103
- },
104
- ref: (node) => {
105
- this.compositionNode = node;
106
- }
107
- }, [
108
- new VTextNode(this.composition.text)
109
- ]);
110
- });
111
- }
112
- for (let i = 0; i < vNode.children.length; i++) {
113
- const child = vNode.children[i];
114
- if (child instanceof VElement) {
115
- children.push(vNodeToJSX(child));
116
- }
117
- else if (child instanceof VTextNode) {
118
- children.push(replaceEmpty(child.textContent));
119
- }
120
- else {
121
- children.push(this.componentRender(child));
122
- if (!this.firstRending) {
123
- invokeListener(child, 'onParentSlotUpdated');
124
- }
125
- }
126
- }
127
- const props = Object.assign({}, (Array.from(vNode.attrs).reduce((a, b) => {
128
- a[b[0]] = b[1];
129
- return a;
130
- }, {})));
131
- if (vNode.classes.size) {
132
- props.className = Array.from(vNode.classes).join(' ');
133
- }
134
- if (vNode.styles) {
135
- props.style = Array.from(vNode.styles).reduce((a, b) => {
136
- a[b[0]] = b[1];
137
- return a;
138
- }, {});
139
- }
140
- return createElement(vNode.tagName, props, ...children);
141
- };
142
- const refFn = (nativeNode) => {
143
- if (!nativeNode) {
144
- this.slotRootNativeElementCaches.remove(slot);
145
- }
146
- else {
147
- this.slotRootNativeElementCaches.set(slot, nativeNode);
148
- }
149
- };
150
- const currentRef = vElement.attrs.get('ref');
151
- if (currentRef) {
152
- vElement.attrs.set('ref', (v) => {
153
- refFn(v);
154
- if (typeof currentRef === 'function') {
155
- currentRef(v);
156
- }
157
- else if (!currentRef.current) {
158
- currentRef.current = v;
159
- }
160
- });
161
- }
162
- else {
163
- vElement.attrs.set('ref', refFn);
164
- }
165
- slot.__changeMarker__.rendered();
166
- return vNodeToJSX(vElement);
124
+ copy() {
125
+ document.execCommand('copy');
167
126
  }
168
127
  }
169
128
 
170
- export { Adapter };
129
+ export { ReactAdapter };
package/bundles/index.js CHANGED
@@ -1,32 +1,83 @@
1
1
  'use strict';
2
2
 
3
- var react = require('react');
4
- var stream = require('@tanbo/stream');
5
3
  var core = require('@textbus/core');
6
4
  var platformBrowser = require('@textbus/platform-browser');
5
+ var react = require('react');
7
6
 
8
- // hack start
9
- // 在 composition 输入时,浏览器会默认删除占位节点(<br>),这会导致 react 在 diff 时报错
10
- const oldRemoveChild = Node.prototype.removeChild;
11
- Node.prototype.removeChild = function (child) {
12
- if (child) {
13
- if (!child.parentNode) {
14
- return child;
15
- }
16
- }
17
- return oldRemoveChild.call(this, child);
18
- };
19
- // hack end
20
7
  const adapterError = core.makeError('ReactAdapter');
21
- /**
22
- * Textbus 桥接 React 渲染能力适配器,用于在 React 项目中渲染 Textbus 数据
23
- */
24
- class Adapter extends platformBrowser.DomAdapter {
8
+ class ReactAdapter extends platformBrowser.DomAdapter {
25
9
  constructor(components, mount) {
26
- super(mount);
27
- this.onViewUpdated = new stream.Subject();
10
+ super({
11
+ createCompositionNode(compositionState, updateNativeCompositionNode) {
12
+ return new core.VElement('span', {
13
+ style: {
14
+ textDecoration: 'underline'
15
+ },
16
+ ref: (node) => {
17
+ updateNativeCompositionNode(node);
18
+ }
19
+ }, [
20
+ new core.VTextNode(compositionState.text)
21
+ ]);
22
+ },
23
+ getParentNode(node) {
24
+ return node.parentNode;
25
+ },
26
+ getChildNodes(parentElement) {
27
+ return Array.from(parentElement.childNodes);
28
+ },
29
+ isNativeElementNode(node) {
30
+ return node instanceof HTMLElement;
31
+ },
32
+ getChildByIndex(parentElement, index) {
33
+ return parentElement.childNodes[index];
34
+ },
35
+ getAndUpdateSlotRootNativeElement(vEle, update) {
36
+ const currentRef = vEle.attrs.get('ref');
37
+ if (currentRef) {
38
+ vEle.attrs.set('ref', (v) => {
39
+ update(v);
40
+ if (typeof currentRef === 'function') {
41
+ currentRef(v);
42
+ }
43
+ else if (!currentRef.current) {
44
+ currentRef.current = v;
45
+ }
46
+ });
47
+ }
48
+ else {
49
+ vEle.attrs.set('ref', update);
50
+ }
51
+ },
52
+ componentRender: (component) => {
53
+ const comp = this.components[component.name] || this.components['*'];
54
+ if (comp) {
55
+ component.changeMarker.rendered();
56
+ return react.createElement(comp, {
57
+ key: component.id,
58
+ component
59
+ });
60
+ }
61
+ throw adapterError(`cannot found view component \`${component.name}\`!`);
62
+ },
63
+ vElementToViewElement(vNode, children) {
64
+ const props = Object.assign({}, (Array.from(vNode.attrs).reduce((a, b) => {
65
+ a[b[0]] = b[1];
66
+ return a;
67
+ }, {})));
68
+ if (vNode.classes.size) {
69
+ props.className = Array.from(vNode.classes).join(' ');
70
+ }
71
+ if (vNode.styles) {
72
+ props.style = Array.from(vNode.styles).reduce((a, b) => {
73
+ a[b[0]] = b[1];
74
+ return a;
75
+ }, {});
76
+ }
77
+ return react.createElement(vNode.tagName, props, ...children);
78
+ }
79
+ }, mount);
28
80
  this.components = {};
29
- this.componentRendingStack = [];
30
81
  Object.keys(components).forEach(key => {
31
82
  this.components[key] = (props) => {
32
83
  const component = props.component;
@@ -72,101 +123,9 @@ class Adapter extends platformBrowser.DomAdapter {
72
123
  };
73
124
  });
74
125
  }
75
- componentRender(component) {
76
- const comp = this.components[component.name] || this.components['*'];
77
- if (comp) {
78
- component.changeMarker.rendered();
79
- return react.createElement(comp, {
80
- key: component.id,
81
- component
82
- });
83
- }
84
- throw adapterError(`cannot found view component \`${component.name}\`!`);
85
- }
86
- slotRender(slot, slotHostRender, renderEnv) {
87
- var _a;
88
- const context = this.componentRendingStack[this.componentRendingStack.length - 1];
89
- if (context) {
90
- context.__slots__.push(slot);
91
- }
92
- else if (!this.renderedSlotCache.has(slot)) {
93
- throw adapterError(`Unrendered slots must be rendered together with the corresponding "${((_a = slot.parent) === null || _a === void 0 ? void 0 : _a.name) || 'unknown'}" component`);
94
- }
95
- this.renderedSlotCache.set(slot, true);
96
- const vElement = slot.toTree(slotHostRender, renderEnv);
97
- this.slotRootVElementCaches.set(slot, vElement);
98
- const vNodeToJSX = (vNode) => {
99
- const children = [];
100
- if (this.composition && this.composition.slot === slot) {
101
- this.insertCompositionByIndex(slot, vNode, this.composition, () => {
102
- return new core.VElement('span', {
103
- style: {
104
- textDecoration: 'underline'
105
- },
106
- ref: (node) => {
107
- this.compositionNode = node;
108
- }
109
- }, [
110
- new core.VTextNode(this.composition.text)
111
- ]);
112
- });
113
- }
114
- for (let i = 0; i < vNode.children.length; i++) {
115
- const child = vNode.children[i];
116
- if (child instanceof core.VElement) {
117
- children.push(vNodeToJSX(child));
118
- }
119
- else if (child instanceof core.VTextNode) {
120
- children.push(core.replaceEmpty(child.textContent));
121
- }
122
- else {
123
- children.push(this.componentRender(child));
124
- if (!this.firstRending) {
125
- core.invokeListener(child, 'onParentSlotUpdated');
126
- }
127
- }
128
- }
129
- const props = Object.assign({}, (Array.from(vNode.attrs).reduce((a, b) => {
130
- a[b[0]] = b[1];
131
- return a;
132
- }, {})));
133
- if (vNode.classes.size) {
134
- props.className = Array.from(vNode.classes).join(' ');
135
- }
136
- if (vNode.styles) {
137
- props.style = Array.from(vNode.styles).reduce((a, b) => {
138
- a[b[0]] = b[1];
139
- return a;
140
- }, {});
141
- }
142
- return react.createElement(vNode.tagName, props, ...children);
143
- };
144
- const refFn = (nativeNode) => {
145
- if (!nativeNode) {
146
- this.slotRootNativeElementCaches.remove(slot);
147
- }
148
- else {
149
- this.slotRootNativeElementCaches.set(slot, nativeNode);
150
- }
151
- };
152
- const currentRef = vElement.attrs.get('ref');
153
- if (currentRef) {
154
- vElement.attrs.set('ref', (v) => {
155
- refFn(v);
156
- if (typeof currentRef === 'function') {
157
- currentRef(v);
158
- }
159
- else if (!currentRef.current) {
160
- currentRef.current = v;
161
- }
162
- });
163
- }
164
- else {
165
- vElement.attrs.set('ref', refFn);
166
- }
167
- slot.__changeMarker__.rendered();
168
- return vNodeToJSX(vElement);
126
+ copy() {
127
+ document.execCommand('copy');
169
128
  }
170
129
  }
171
130
 
172
- exports.Adapter = Adapter;
131
+ exports.ReactAdapter = ReactAdapter;
@@ -1 +1 @@
1
- export * from './adapter';
1
+ export * from './react-adapter';
@@ -0,0 +1,15 @@
1
+ import { Component, ViewMount } from '@textbus/core';
2
+ import { DomAdapter } from '@textbus/platform-browser';
3
+ import { JSX } from 'react';
4
+ export interface ViewComponentProps<T extends Component> {
5
+ component: T;
6
+ rootRef: ((rootNode: HTMLElement) => void);
7
+ }
8
+ export interface ReactAdapterComponents {
9
+ [key: string]: (props: ViewComponentProps<any>) => JSX.Element;
10
+ }
11
+ export declare class ReactAdapter extends DomAdapter<JSX.Element, JSX.Element> {
12
+ private components;
13
+ constructor(components: ReactAdapterComponents, mount: ViewMount<JSX.Element, HTMLElement>);
14
+ copy(): void;
15
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@textbus/adapter-react",
3
- "version": "4.0.0-alpha.41",
3
+ "version": "4.0.0-alpha.43",
4
4
  "description": "Textbus is a rich text editor and framework that is highly customizable and extensible to achieve rich wysiwyg effects.",
5
5
  "main": "./bundles/index.js",
6
6
  "module": "./bundles/index.esm.js",
@@ -26,8 +26,8 @@
26
26
  ],
27
27
  "dependencies": {
28
28
  "@tanbo/stream": "^1.2.3",
29
- "@textbus/core": "^4.0.0-alpha.41",
30
- "@textbus/platform-browser": "^4.0.0-alpha.41",
29
+ "@textbus/core": "^4.0.0-alpha.43",
30
+ "@textbus/platform-browser": "^4.0.0-alpha.43",
31
31
  "react": "^17.0.0 || ^18.0.0"
32
32
  },
33
33
  "devDependencies": {
@@ -49,5 +49,5 @@
49
49
  "bugs": {
50
50
  "url": "https://github.com/textbus/textbus.git/issues"
51
51
  },
52
- "gitHead": "b5c18b176790c339fb7fb35e3d427b8a81ffcd84"
52
+ "gitHead": "23f1cf769789b56e1fcbaa25655bd0dfd57a24f9"
53
53
  }
@@ -1,22 +0,0 @@
1
- import { JSX } from 'react';
2
- import { Subject } from '@tanbo/stream';
3
- import { Component, Slot, VElement, VTextNode } from '@textbus/core';
4
- import { DomAdapter } from '@textbus/platform-browser';
5
- export interface ViewComponentProps<T extends Component> {
6
- component: T;
7
- rootRef: ((rootNode: HTMLElement) => void);
8
- }
9
- export interface ReactAdapterComponents {
10
- [key: string]: (props: ViewComponentProps<any>) => JSX.Element;
11
- }
12
- /**
13
- * Textbus 桥接 React 渲染能力适配器,用于在 React 项目中渲染 Textbus 数据
14
- */
15
- export declare class Adapter extends DomAdapter<JSX.Element, JSX.Element> {
16
- onViewUpdated: Subject<void>;
17
- private components;
18
- private componentRendingStack;
19
- constructor(components: ReactAdapterComponents, mount: (host: HTMLElement, root: JSX.Element) => (void | (() => void)));
20
- componentRender(component: Component): JSX.Element;
21
- slotRender(slot: Slot, slotHostRender: (children: Array<VElement | VTextNode | Component>) => VElement, renderEnv?: any): JSX.Element;
22
- }