@textbus/platform-browser 3.0.1 → 3.0.3

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.
@@ -2,3 +2,4 @@ export declare const isWindows: () => boolean;
2
2
  export declare const isMac: () => boolean;
3
3
  export declare const isSafari: () => boolean;
4
4
  export declare const isFirefox: () => boolean;
5
+ export declare const isMobileBrowser: () => boolean;
@@ -28,7 +28,8 @@ export declare class DomRenderer implements NativeRenderer {
28
28
  xlinktype: string;
29
29
  'xlink:type': string;
30
30
  };
31
- formElement: Record<string, string[]>;
31
+ booleanProps: Record<string, string[]>;
32
+ valueProps: Record<string, string[]>;
32
33
  listen<T = any>(node: NativeNode, type: string, callback: (ev: T) => any): void;
33
34
  unListen(node: NativeNode, type: string, callback: (ev: any) => any): void;
34
35
  createTextNode(textContent: string): NativeNode;
@@ -1,6 +1,6 @@
1
1
  import { Injector } from '@tanbo/di';
2
2
  import { Observable } from '@tanbo/stream';
3
- import { Commander, Controller, Keyboard, Scheduler, Selection } from '@textbus/core';
3
+ import { Commander, Controller, Keyboard, Renderer, Scheduler, Selection } from '@textbus/core';
4
4
  import { Caret, CaretPosition, CompositionState, Input, Scroller } from './types';
5
5
  import { Parser } from '../dom-support/parser';
6
6
  declare class NativeCaret implements Caret {
@@ -29,6 +29,7 @@ export declare class NativeInput extends Input {
29
29
  private scheduler;
30
30
  private selection;
31
31
  private keyboard;
32
+ private renderer;
32
33
  private commander;
33
34
  private controller;
34
35
  caret: NativeCaret;
@@ -44,8 +45,9 @@ export declare class NativeInput extends Input {
44
45
  private nativeRange;
45
46
  private isSafari;
46
47
  private isMac;
48
+ private isMobileBrowser;
47
49
  private isSougouPinYin;
48
- constructor(injector: Injector, parser: Parser, scheduler: Scheduler, selection: Selection, keyboard: Keyboard, commander: Commander, controller: Controller);
50
+ constructor(injector: Injector, parser: Parser, scheduler: Scheduler, selection: Selection, keyboard: Keyboard, renderer: Renderer, commander: Commander, controller: Controller);
49
51
  focus(nativeRange: Range): void;
50
52
  blur(): void;
51
53
  destroy(): void;
@@ -102,6 +102,7 @@ const isWindows = () => /win(dows|32|64)/i.test(navigator.userAgent);
102
102
  const isMac = () => /mac os/i.test(navigator.userAgent);
103
103
  const isSafari = () => /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent);
104
104
  const isFirefox = () => /Firefox/.test(navigator.userAgent);
105
+ const isMobileBrowser = () => /Android|iPhone|iPad/.test(navigator.userAgent);
105
106
 
106
107
  /******************************************************************************
107
108
  Copyright (c) Microsoft Corporation.
@@ -1118,14 +1119,20 @@ let DomRenderer = DomRenderer_1 = class DomRenderer {
1118
1119
  xlinktype: 'xlink:type',
1119
1120
  'xlink:type': 'xlink:type'
1120
1121
  };
1121
- this.formElement = {
1122
- input: ['disabled', 'readonly', 'value'],
1122
+ this.booleanProps = {
1123
+ input: ['disabled', 'readonly'],
1123
1124
  select: ['disabled', 'readonly'],
1124
- option: ['disabled', 'selected', 'value'],
1125
+ option: ['disabled', 'selected'],
1125
1126
  button: ['disabled'],
1126
1127
  video: ['controls', 'autoplay', 'loop', 'muted'],
1127
1128
  audio: ['controls', 'autoplay', 'loop', 'muted'],
1128
1129
  };
1130
+ this.valueProps = {
1131
+ input: ['value'],
1132
+ option: ['value'],
1133
+ video: ['src'],
1134
+ audio: ['src']
1135
+ };
1129
1136
  }
1130
1137
  listen(node, type, callback) {
1131
1138
  node.addEventListener(type, callback);
@@ -1179,20 +1186,30 @@ let DomRenderer = DomRenderer_1 = class DomRenderer {
1179
1186
  return;
1180
1187
  }
1181
1188
  target.setAttribute(key, value);
1182
- const propNames = this.formElement[target.tagName.toLowerCase()];
1183
- if (propNames && propNames.includes(key)) {
1189
+ const tag = target.tagName.toLowerCase();
1190
+ const booleanTagNames = this.booleanProps[tag];
1191
+ const valueTagNames = this.valueProps[tag];
1192
+ if (booleanTagNames && booleanTagNames.includes(key)) {
1184
1193
  target[key] = Boolean(value);
1185
1194
  }
1195
+ if (valueTagNames && valueTagNames.includes(key)) {
1196
+ target[key] = value;
1197
+ }
1186
1198
  }
1187
1199
  removeAttribute(target, key) {
1188
1200
  if (this.possibleXlinkNames[key]) {
1189
1201
  this.removeXlinkAttribute(target, this.possibleXlinkNames[key]);
1190
1202
  }
1191
1203
  target.removeAttribute(key);
1192
- const propNames = this.formElement[target.tagName.toLowerCase()];
1193
- if (propNames && propNames.includes(key)) {
1204
+ const tag = target.tagName.toLowerCase();
1205
+ const booleanTagNames = this.booleanProps[tag];
1206
+ const valueTagNames = this.valueProps[tag];
1207
+ if (booleanTagNames && booleanTagNames.includes(key)) {
1194
1208
  target[key] = false;
1195
1209
  }
1210
+ if (valueTagNames && valueTagNames.includes(key)) {
1211
+ target[key] = '';
1212
+ }
1196
1213
  }
1197
1214
  setXlinkAttribute(target, key, value) {
1198
1215
  target.setAttributeNS(this.xlinkNameSpace, key, value);
@@ -1986,13 +2003,14 @@ let NativeInput = class NativeInput extends Input {
1986
2003
  get disabled() {
1987
2004
  return this._disabled;
1988
2005
  }
1989
- constructor(injector, parser, scheduler, selection, keyboard, commander, controller) {
2006
+ constructor(injector, parser, scheduler, selection, keyboard, renderer, commander, controller) {
1990
2007
  super();
1991
2008
  this.injector = injector;
1992
2009
  this.parser = parser;
1993
2010
  this.scheduler = scheduler;
1994
2011
  this.selection = selection;
1995
2012
  this.keyboard = keyboard;
2013
+ this.renderer = renderer;
1996
2014
  this.commander = commander;
1997
2015
  this.controller = controller;
1998
2016
  this.caret = new NativeCaret(this.scheduler);
@@ -2005,6 +2023,7 @@ let NativeInput = class NativeInput extends Input {
2005
2023
  this.nativeRange = null;
2006
2024
  this.isSafari = isSafari();
2007
2025
  this.isMac = isMac();
2026
+ this.isMobileBrowser = isMobileBrowser();
2008
2027
  this.isSougouPinYin = false; // 有 bug 版本搜狗拼音
2009
2028
  this.documentView = injector.get(VIEW_DOCUMENT);
2010
2029
  if (!controller.readonly) {
@@ -2163,15 +2182,41 @@ let NativeInput = class NativeInput extends Input {
2163
2182
  data: ev.data
2164
2183
  });
2165
2184
  invokeListener(startSlot.parent, 'onCompositionUpdate', event);
2166
- }), merge(fromEvent(input, 'beforeinput').pipe(filter(ev => {
2185
+ }), merge(fromEvent(input, 'beforeinput').pipe(map(ev => {
2186
+ var _a;
2167
2187
  ev.preventDefault();
2188
+ if (ev.inputType === 'insertCompositionText') {
2189
+ return null;
2190
+ }
2191
+ if (ev.inputType === 'insertReplacementText') {
2192
+ const range = ev.getTargetRanges()[0];
2193
+ const location = this.renderer.getLocationByNativeNode(range.startContainer);
2194
+ const startSlot = this.selection.startSlot;
2195
+ this.selection.setBaseAndExtent(startSlot, location.startIndex + range.startOffset, startSlot, location.startIndex + range.endOffset);
2196
+ this.commander.delete();
2197
+ return ((_a = ev.dataTransfer) === null || _a === void 0 ? void 0 : _a.getData('text')) || ev.data || null;
2198
+ }
2199
+ isCompositionEnd = ev.inputType === 'insertFromComposition';
2200
+ if (isCompositionEnd && this.composition) {
2201
+ if (this.isMobileBrowser) {
2202
+ this.composition = false;
2203
+ this.compositionState = null;
2204
+ }
2205
+ else {
2206
+ return null;
2207
+ }
2208
+ }
2168
2209
  if (this.isSafari) {
2169
- isCompositionEnd = ev.inputType === 'insertFromComposition';
2170
- return ev.inputType === 'insertText' || ev.inputType === 'insertFromComposition';
2210
+ if (ev.inputType === 'insertText' || isCompositionEnd) {
2211
+ return ev.data;
2212
+ }
2171
2213
  }
2172
- return !ev.isComposing && !!ev.data;
2173
- }), map(ev => {
2174
- return ev.data;
2214
+ if (!ev.isComposing && !!ev.data) {
2215
+ return ev.data;
2216
+ }
2217
+ return null;
2218
+ }), filter(text => {
2219
+ return text;
2175
2220
  })), this.isSafari ? new Observable() : fromEvent(input, 'compositionend').pipe(map(ev => {
2176
2221
  isCompositionEnd = true;
2177
2222
  ev.preventDefault();
@@ -2204,6 +2249,7 @@ NativeInput = __decorate([
2204
2249
  Scheduler,
2205
2250
  Selection,
2206
2251
  Keyboard,
2252
+ Renderer,
2207
2253
  Commander,
2208
2254
  Controller])
2209
2255
  ], NativeInput);
@@ -2787,4 +2833,4 @@ class Viewer extends Starter {
2787
2833
  }
2788
2834
  }
2789
2835
 
2790
- export { CollaborateCursor, CollaborateSelectionAwarenessDelegate, DomRenderer, EDITOR_OPTIONS, Input, MagicInput, NativeInput, OutputTranslator, Parser, SelectionBridge, VIEW_CONTAINER, VIEW_DOCUMENT, VIEW_MASK, Viewer, createElement, createTextNode, getLayoutRectByRange, isFirefox, isMac, isSafari, isWindows };
2836
+ export { CollaborateCursor, CollaborateSelectionAwarenessDelegate, DomRenderer, EDITOR_OPTIONS, Input, MagicInput, NativeInput, OutputTranslator, Parser, SelectionBridge, VIEW_CONTAINER, VIEW_DOCUMENT, VIEW_MASK, Viewer, createElement, createTextNode, getLayoutRectByRange, isFirefox, isMac, isMobileBrowser, isSafari, isWindows };
package/bundles/index.js CHANGED
@@ -104,6 +104,7 @@ const isWindows = () => /win(dows|32|64)/i.test(navigator.userAgent);
104
104
  const isMac = () => /mac os/i.test(navigator.userAgent);
105
105
  const isSafari = () => /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent);
106
106
  const isFirefox = () => /Firefox/.test(navigator.userAgent);
107
+ const isMobileBrowser = () => /Android|iPhone|iPad/.test(navigator.userAgent);
107
108
 
108
109
  /******************************************************************************
109
110
  Copyright (c) Microsoft Corporation.
@@ -1120,14 +1121,20 @@ exports.DomRenderer = DomRenderer_1 = class DomRenderer {
1120
1121
  xlinktype: 'xlink:type',
1121
1122
  'xlink:type': 'xlink:type'
1122
1123
  };
1123
- this.formElement = {
1124
- input: ['disabled', 'readonly', 'value'],
1124
+ this.booleanProps = {
1125
+ input: ['disabled', 'readonly'],
1125
1126
  select: ['disabled', 'readonly'],
1126
- option: ['disabled', 'selected', 'value'],
1127
+ option: ['disabled', 'selected'],
1127
1128
  button: ['disabled'],
1128
1129
  video: ['controls', 'autoplay', 'loop', 'muted'],
1129
1130
  audio: ['controls', 'autoplay', 'loop', 'muted'],
1130
1131
  };
1132
+ this.valueProps = {
1133
+ input: ['value'],
1134
+ option: ['value'],
1135
+ video: ['src'],
1136
+ audio: ['src']
1137
+ };
1131
1138
  }
1132
1139
  listen(node, type, callback) {
1133
1140
  node.addEventListener(type, callback);
@@ -1181,20 +1188,30 @@ exports.DomRenderer = DomRenderer_1 = class DomRenderer {
1181
1188
  return;
1182
1189
  }
1183
1190
  target.setAttribute(key, value);
1184
- const propNames = this.formElement[target.tagName.toLowerCase()];
1185
- if (propNames && propNames.includes(key)) {
1191
+ const tag = target.tagName.toLowerCase();
1192
+ const booleanTagNames = this.booleanProps[tag];
1193
+ const valueTagNames = this.valueProps[tag];
1194
+ if (booleanTagNames && booleanTagNames.includes(key)) {
1186
1195
  target[key] = Boolean(value);
1187
1196
  }
1197
+ if (valueTagNames && valueTagNames.includes(key)) {
1198
+ target[key] = value;
1199
+ }
1188
1200
  }
1189
1201
  removeAttribute(target, key) {
1190
1202
  if (this.possibleXlinkNames[key]) {
1191
1203
  this.removeXlinkAttribute(target, this.possibleXlinkNames[key]);
1192
1204
  }
1193
1205
  target.removeAttribute(key);
1194
- const propNames = this.formElement[target.tagName.toLowerCase()];
1195
- if (propNames && propNames.includes(key)) {
1206
+ const tag = target.tagName.toLowerCase();
1207
+ const booleanTagNames = this.booleanProps[tag];
1208
+ const valueTagNames = this.valueProps[tag];
1209
+ if (booleanTagNames && booleanTagNames.includes(key)) {
1196
1210
  target[key] = false;
1197
1211
  }
1212
+ if (valueTagNames && valueTagNames.includes(key)) {
1213
+ target[key] = '';
1214
+ }
1198
1215
  }
1199
1216
  setXlinkAttribute(target, key, value) {
1200
1217
  target.setAttributeNS(this.xlinkNameSpace, key, value);
@@ -1988,13 +2005,14 @@ exports.NativeInput = class NativeInput extends Input {
1988
2005
  get disabled() {
1989
2006
  return this._disabled;
1990
2007
  }
1991
- constructor(injector, parser, scheduler, selection, keyboard, commander, controller) {
2008
+ constructor(injector, parser, scheduler, selection, keyboard, renderer, commander, controller) {
1992
2009
  super();
1993
2010
  this.injector = injector;
1994
2011
  this.parser = parser;
1995
2012
  this.scheduler = scheduler;
1996
2013
  this.selection = selection;
1997
2014
  this.keyboard = keyboard;
2015
+ this.renderer = renderer;
1998
2016
  this.commander = commander;
1999
2017
  this.controller = controller;
2000
2018
  this.caret = new NativeCaret(this.scheduler);
@@ -2007,6 +2025,7 @@ exports.NativeInput = class NativeInput extends Input {
2007
2025
  this.nativeRange = null;
2008
2026
  this.isSafari = isSafari();
2009
2027
  this.isMac = isMac();
2028
+ this.isMobileBrowser = isMobileBrowser();
2010
2029
  this.isSougouPinYin = false; // 有 bug 版本搜狗拼音
2011
2030
  this.documentView = injector.get(VIEW_DOCUMENT);
2012
2031
  if (!controller.readonly) {
@@ -2165,15 +2184,41 @@ exports.NativeInput = class NativeInput extends Input {
2165
2184
  data: ev.data
2166
2185
  });
2167
2186
  core.invokeListener(startSlot.parent, 'onCompositionUpdate', event);
2168
- }), stream.merge(stream.fromEvent(input, 'beforeinput').pipe(stream.filter(ev => {
2187
+ }), stream.merge(stream.fromEvent(input, 'beforeinput').pipe(stream.map(ev => {
2188
+ var _a;
2169
2189
  ev.preventDefault();
2190
+ if (ev.inputType === 'insertCompositionText') {
2191
+ return null;
2192
+ }
2193
+ if (ev.inputType === 'insertReplacementText') {
2194
+ const range = ev.getTargetRanges()[0];
2195
+ const location = this.renderer.getLocationByNativeNode(range.startContainer);
2196
+ const startSlot = this.selection.startSlot;
2197
+ this.selection.setBaseAndExtent(startSlot, location.startIndex + range.startOffset, startSlot, location.startIndex + range.endOffset);
2198
+ this.commander.delete();
2199
+ return ((_a = ev.dataTransfer) === null || _a === void 0 ? void 0 : _a.getData('text')) || ev.data || null;
2200
+ }
2201
+ isCompositionEnd = ev.inputType === 'insertFromComposition';
2202
+ if (isCompositionEnd && this.composition) {
2203
+ if (this.isMobileBrowser) {
2204
+ this.composition = false;
2205
+ this.compositionState = null;
2206
+ }
2207
+ else {
2208
+ return null;
2209
+ }
2210
+ }
2170
2211
  if (this.isSafari) {
2171
- isCompositionEnd = ev.inputType === 'insertFromComposition';
2172
- return ev.inputType === 'insertText' || ev.inputType === 'insertFromComposition';
2212
+ if (ev.inputType === 'insertText' || isCompositionEnd) {
2213
+ return ev.data;
2214
+ }
2173
2215
  }
2174
- return !ev.isComposing && !!ev.data;
2175
- }), stream.map(ev => {
2176
- return ev.data;
2216
+ if (!ev.isComposing && !!ev.data) {
2217
+ return ev.data;
2218
+ }
2219
+ return null;
2220
+ }), stream.filter(text => {
2221
+ return text;
2177
2222
  })), this.isSafari ? new stream.Observable() : stream.fromEvent(input, 'compositionend').pipe(stream.map(ev => {
2178
2223
  isCompositionEnd = true;
2179
2224
  ev.preventDefault();
@@ -2206,6 +2251,7 @@ exports.NativeInput = __decorate([
2206
2251
  core.Scheduler,
2207
2252
  core.Selection,
2208
2253
  core.Keyboard,
2254
+ core.Renderer,
2209
2255
  core.Commander,
2210
2256
  core.Controller])
2211
2257
  ], exports.NativeInput);
@@ -2801,5 +2847,6 @@ exports.createTextNode = createTextNode;
2801
2847
  exports.getLayoutRectByRange = getLayoutRectByRange;
2802
2848
  exports.isFirefox = isFirefox;
2803
2849
  exports.isMac = isMac;
2850
+ exports.isMobileBrowser = isMobileBrowser;
2804
2851
  exports.isSafari = isSafari;
2805
2852
  exports.isWindows = isWindows;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@textbus/platform-browser",
3
- "version": "3.0.1",
3
+ "version": "3.0.3",
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",
@@ -48,5 +48,5 @@
48
48
  "bugs": {
49
49
  "url": "https://github.com/textbus/textbus.git/issues"
50
50
  },
51
- "gitHead": "a74f952c6e72e51005208e0b79921007e11bb6b0"
51
+ "gitHead": "8087ffa86e0db3b8be429308ce81a3739b36fec6"
52
52
  }