Comparing version 0.7.0 to 0.8.0
@@ -7,2 +7,44 @@ # Changelog | ||
## 0.8.0 (August 8, 2016) | ||
### Added | ||
* `customStyleFn` for more control over inline style ranges | ||
* Uses `internalClipboard` for Safari | ||
* Metadata for `ContentBlock` objects | ||
* `convertFromHTMLToContentBlocks`: | ||
* Support for `mailto` protocol for links | ||
* Support "unset" inline styles | ||
* Run ESLint on examples | ||
### Changed | ||
* Removed redundant ESLint module in TeX example | ||
* Update Travis CI config for readability, Node v4 requirements, and pruning/updating npm dependencies | ||
* Use `immutable` ~3.7.4 to avoid Flow errors in updated versions | ||
* Modify `getSelectionOffsetKeyForNode` to search for nested offset-annotated nodes | ||
* Upgrade eslint to 3.0.1, use fbjs config | ||
* Update to Flow 0.28 | ||
* Jest | ||
* Update to 12.1.1 | ||
* Replaced `jest.fn().mockReturnValue(x)` with `jest.fn(() => x)` | ||
* Remove extra spaces from the text decoration style | ||
* No longer using `nullthrows` for `blockRenderMap` | ||
* `convertFromHTMLToContentBlocks`: | ||
* Improved variable names in `joinChunks` | ||
* Additional whitelisted entities such as `className`, `rel`, `target`, `title` | ||
### Fixed | ||
* Fix bug where placeholder text was not being erased in Chrome | ||
* Fix bug where double click link in Firefox broke selection | ||
* Kill iOS tooltips | ||
* removed unnecessary `undefined` checks on `DraftEditorLeaf` | ||
* `convertFromHTMLToContentBlocks`: | ||
* Preserve pasted block type on paste | ||
* Strip XML carriage returns and zero-width spaces | ||
* `getBlockMapSupportedTags()` will always return a valid array of tags | ||
* Documentation fixes | ||
## 0.7.0 (May 3, 2016) | ||
@@ -9,0 +51,0 @@ |
@@ -28,2 +28,3 @@ /** | ||
var AtomicBlockUtils = { | ||
@@ -30,0 +31,0 @@ insertAtomicBlock: function insertAtomicBlock(editorState, entityKey, character) { |
@@ -13,6 +13,2 @@ /** | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
'use strict'; |
@@ -19,2 +19,3 @@ /** | ||
var BlockMapBuilder = { | ||
@@ -21,0 +22,0 @@ createFromArray: function createFromArray(blocks) { |
@@ -24,2 +24,3 @@ /** | ||
var returnTrue = emptyFunction.thatReturnsTrue; | ||
@@ -26,0 +27,0 @@ |
@@ -16,10 +16,8 @@ /** | ||
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; | ||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
var _require = require('immutable'); | ||
@@ -31,2 +29,3 @@ | ||
var EMPTY_SET = OrderedSet(); | ||
@@ -41,4 +40,4 @@ | ||
var CharacterMetadata = (function (_CharacterMetadataRecord) { | ||
_inherits(CharacterMetadata, _CharacterMetadataRecord); | ||
var CharacterMetadata = function (_CharacterMetadataRec) { | ||
_inherits(CharacterMetadata, _CharacterMetadataRec); | ||
@@ -48,68 +47,60 @@ function CharacterMetadata() { | ||
_get(Object.getPrototypeOf(CharacterMetadata.prototype), 'constructor', this).apply(this, arguments); | ||
return _possibleConstructorReturn(this, _CharacterMetadataRec.apply(this, arguments)); | ||
} | ||
_createClass(CharacterMetadata, [{ | ||
key: 'getStyle', | ||
value: function getStyle() { | ||
return this.get('style'); | ||
} | ||
}, { | ||
key: 'getEntity', | ||
value: function getEntity() { | ||
return this.get('entity'); | ||
} | ||
}, { | ||
key: 'hasStyle', | ||
value: function hasStyle(style) { | ||
return this.getStyle().has(style); | ||
} | ||
}], [{ | ||
key: 'applyStyle', | ||
value: function applyStyle(record, style) { | ||
var withStyle = record.set('style', record.getStyle().add(style)); | ||
return CharacterMetadata.create(withStyle); | ||
} | ||
}, { | ||
key: 'removeStyle', | ||
value: function removeStyle(record, style) { | ||
var withoutStyle = record.set('style', record.getStyle().remove(style)); | ||
return CharacterMetadata.create(withoutStyle); | ||
} | ||
}, { | ||
key: 'applyEntity', | ||
value: function applyEntity(record, entityKey) { | ||
var withEntity = record.getEntity() === entityKey ? record : record.set('entity', entityKey); | ||
return CharacterMetadata.create(withEntity); | ||
} | ||
CharacterMetadata.prototype.getStyle = function getStyle() { | ||
return this.get('style'); | ||
}; | ||
/** | ||
* Use this function instead of the `CharacterMetadata` constructor. | ||
* Since most content generally uses only a very small number of | ||
* style/entity permutations, we can reuse these objects as often as | ||
* possible. | ||
*/ | ||
}, { | ||
key: 'create', | ||
value: function create(config) { | ||
if (!config) { | ||
return EMPTY; | ||
} | ||
CharacterMetadata.prototype.getEntity = function getEntity() { | ||
return this.get('entity'); | ||
}; | ||
// Fill in unspecified properties, if necessary. | ||
var configMap = Map({ style: EMPTY_SET, entity: null }).merge(config); | ||
CharacterMetadata.prototype.hasStyle = function hasStyle(style) { | ||
return this.getStyle().has(style); | ||
}; | ||
var existing = pool.get(configMap); | ||
if (existing) { | ||
return existing; | ||
} | ||
CharacterMetadata.applyStyle = function applyStyle(record, style) { | ||
var withStyle = record.set('style', record.getStyle().add(style)); | ||
return CharacterMetadata.create(withStyle); | ||
}; | ||
var newCharacter = new CharacterMetadata(configMap); | ||
pool = pool.set(configMap, newCharacter); | ||
return newCharacter; | ||
CharacterMetadata.removeStyle = function removeStyle(record, style) { | ||
var withoutStyle = record.set('style', record.getStyle().remove(style)); | ||
return CharacterMetadata.create(withoutStyle); | ||
}; | ||
CharacterMetadata.applyEntity = function applyEntity(record, entityKey) { | ||
var withEntity = record.getEntity() === entityKey ? record : record.set('entity', entityKey); | ||
return CharacterMetadata.create(withEntity); | ||
}; | ||
/** | ||
* Use this function instead of the `CharacterMetadata` constructor. | ||
* Since most content generally uses only a very small number of | ||
* style/entity permutations, we can reuse these objects as often as | ||
* possible. | ||
*/ | ||
CharacterMetadata.create = function create(config) { | ||
if (!config) { | ||
return EMPTY; | ||
} | ||
}]); | ||
// Fill in unspecified properties, if necessary. | ||
var configMap = Map({ style: EMPTY_SET, entity: null }).merge(config); | ||
var existing = pool.get(configMap); | ||
if (existing) { | ||
return existing; | ||
} | ||
var newCharacter = new CharacterMetadata(configMap); | ||
pool = pool.set(configMap, newCharacter); | ||
return newCharacter; | ||
}; | ||
return CharacterMetadata; | ||
})(CharacterMetadataRecord); | ||
}(CharacterMetadataRecord); | ||
@@ -116,0 +107,0 @@ var EMPTY = new CharacterMetadata(); |
@@ -16,6 +16,4 @@ /** | ||
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } | ||
var Immutable = require('immutable'); | ||
@@ -25,2 +23,3 @@ | ||
var DELIMITER = '.'; | ||
@@ -48,3 +47,3 @@ | ||
var CompositeDraftDecorator = (function () { | ||
var CompositeDraftDecorator = function () { | ||
function CompositeDraftDecorator(decorators) { | ||
@@ -59,45 +58,41 @@ _classCallCheck(this, CompositeDraftDecorator); | ||
/** | ||
* Determine whether we can occupy the specified slice of the decorations | ||
* array. | ||
*/ | ||
CompositeDraftDecorator.prototype.getDecorations = function getDecorations(block) { | ||
var decorations = Array(block.getText().length).fill(null); | ||
_createClass(CompositeDraftDecorator, [{ | ||
key: 'getDecorations', | ||
value: function getDecorations(block) { | ||
var decorations = Array(block.getText().length).fill(null); | ||
this._decorators.forEach(function ( /*object*/decorator, /*number*/ii) { | ||
var counter = 0; | ||
var strategy = decorator.strategy; | ||
strategy(block, function ( /*number*/start, /*number*/end) { | ||
// Find out if any of our matching range is already occupied | ||
// by another decorator. If so, discard the match. Otherwise, store | ||
// the component key for rendering. | ||
if (canOccupySlice(decorations, start, end)) { | ||
occupySlice(decorations, start, end, ii + DELIMITER + counter); | ||
counter++; | ||
} | ||
}); | ||
this._decorators.forEach(function ( /*object*/decorator, /*number*/ii) { | ||
var counter = 0; | ||
var strategy = decorator.strategy; | ||
strategy(block, function ( /*number*/start, /*number*/end) { | ||
// Find out if any of our matching range is already occupied | ||
// by another decorator. If so, discard the match. Otherwise, store | ||
// the component key for rendering. | ||
if (canOccupySlice(decorations, start, end)) { | ||
occupySlice(decorations, start, end, ii + DELIMITER + counter); | ||
counter++; | ||
} | ||
}); | ||
}); | ||
return List(decorations); | ||
} | ||
}, { | ||
key: 'getComponentForKey', | ||
value: function getComponentForKey(key) { | ||
var componentKey = parseInt(key.split(DELIMITER)[0], 10); | ||
return this._decorators[componentKey].component; | ||
} | ||
}, { | ||
key: 'getPropsForKey', | ||
value: function getPropsForKey(key) { | ||
var componentKey = parseInt(key.split(DELIMITER)[0], 10); | ||
return this._decorators[componentKey].props; | ||
} | ||
}]); | ||
return List(decorations); | ||
}; | ||
CompositeDraftDecorator.prototype.getComponentForKey = function getComponentForKey(key) { | ||
var componentKey = parseInt(key.split(DELIMITER)[0], 10); | ||
return this._decorators[componentKey].component; | ||
}; | ||
CompositeDraftDecorator.prototype.getPropsForKey = function getPropsForKey(key) { | ||
var componentKey = parseInt(key.split(DELIMITER)[0], 10); | ||
return this._decorators[componentKey].props; | ||
}; | ||
return CompositeDraftDecorator; | ||
})(); | ||
}(); | ||
/** | ||
* Determine whether we can occupy the specified slice of the decorations | ||
* array. | ||
*/ | ||
function canOccupySlice(decorations, start, end) { | ||
@@ -104,0 +99,0 @@ for (var ii = start; ii < end; ii++) { |
@@ -10,3 +10,2 @@ /** | ||
* @providesModule ContentBlock | ||
* @typechecks | ||
* | ||
@@ -17,10 +16,8 @@ */ | ||
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; | ||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
var Immutable = require('immutable'); | ||
@@ -31,5 +28,7 @@ | ||
var List = Immutable.List; | ||
var Map = Immutable.Map; | ||
var OrderedSet = Immutable.OrderedSet; | ||
var Record = Immutable.Record; | ||
var EMPTY_SET = OrderedSet(); | ||
@@ -42,3 +41,4 @@ | ||
characterList: List(), | ||
depth: 0 | ||
depth: 0, | ||
data: Map() | ||
}; | ||
@@ -48,3 +48,3 @@ | ||
var ContentBlock = (function (_ContentBlockRecord) { | ||
var ContentBlock = function (_ContentBlockRecord) { | ||
_inherits(ContentBlock, _ContentBlockRecord); | ||
@@ -55,69 +55,63 @@ | ||
_get(Object.getPrototypeOf(ContentBlock.prototype), 'constructor', this).apply(this, arguments); | ||
return _possibleConstructorReturn(this, _ContentBlockRecord.apply(this, arguments)); | ||
} | ||
_createClass(ContentBlock, [{ | ||
key: 'getKey', | ||
value: function getKey() { | ||
return this.get('key'); | ||
} | ||
}, { | ||
key: 'getType', | ||
value: function getType() { | ||
return this.get('type'); | ||
} | ||
}, { | ||
key: 'getText', | ||
value: function getText() { | ||
return this.get('text'); | ||
} | ||
}, { | ||
key: 'getCharacterList', | ||
value: function getCharacterList() { | ||
return this.get('characterList'); | ||
} | ||
}, { | ||
key: 'getLength', | ||
value: function getLength() { | ||
return this.getText().length; | ||
} | ||
}, { | ||
key: 'getDepth', | ||
value: function getDepth() { | ||
return this.get('depth'); | ||
} | ||
}, { | ||
key: 'getInlineStyleAt', | ||
value: function getInlineStyleAt(offset) { | ||
var character = this.getCharacterList().get(offset); | ||
return character ? character.getStyle() : EMPTY_SET; | ||
} | ||
}, { | ||
key: 'getEntityAt', | ||
value: function getEntityAt(offset) { | ||
var character = this.getCharacterList().get(offset); | ||
return character ? character.getEntity() : null; | ||
} | ||
ContentBlock.prototype.getKey = function getKey() { | ||
return this.get('key'); | ||
}; | ||
/** | ||
* Execute a callback for every contiguous range of styles within the block. | ||
*/ | ||
}, { | ||
key: 'findStyleRanges', | ||
value: function findStyleRanges(filterFn, callback) { | ||
findRangesImmutable(this.getCharacterList(), haveEqualStyle, filterFn, callback); | ||
} | ||
ContentBlock.prototype.getType = function getType() { | ||
return this.get('type'); | ||
}; | ||
/** | ||
* Execute a callback for every contiguous range of entities within the block. | ||
*/ | ||
}, { | ||
key: 'findEntityRanges', | ||
value: function findEntityRanges(filterFn, callback) { | ||
findRangesImmutable(this.getCharacterList(), haveEqualEntity, filterFn, callback); | ||
} | ||
}]); | ||
ContentBlock.prototype.getText = function getText() { | ||
return this.get('text'); | ||
}; | ||
ContentBlock.prototype.getCharacterList = function getCharacterList() { | ||
return this.get('characterList'); | ||
}; | ||
ContentBlock.prototype.getLength = function getLength() { | ||
return this.getText().length; | ||
}; | ||
ContentBlock.prototype.getDepth = function getDepth() { | ||
return this.get('depth'); | ||
}; | ||
ContentBlock.prototype.getData = function getData() { | ||
return this.get('data'); | ||
}; | ||
ContentBlock.prototype.getInlineStyleAt = function getInlineStyleAt(offset) { | ||
var character = this.getCharacterList().get(offset); | ||
return character ? character.getStyle() : EMPTY_SET; | ||
}; | ||
ContentBlock.prototype.getEntityAt = function getEntityAt(offset) { | ||
var character = this.getCharacterList().get(offset); | ||
return character ? character.getEntity() : null; | ||
}; | ||
/** | ||
* Execute a callback for every contiguous range of styles within the block. | ||
*/ | ||
ContentBlock.prototype.findStyleRanges = function findStyleRanges(filterFn, callback) { | ||
findRangesImmutable(this.getCharacterList(), haveEqualStyle, filterFn, callback); | ||
}; | ||
/** | ||
* Execute a callback for every contiguous range of entities within the block. | ||
*/ | ||
ContentBlock.prototype.findEntityRanges = function findEntityRanges(filterFn, callback) { | ||
findRangesImmutable(this.getCharacterList(), haveEqualEntity, filterFn, callback); | ||
}; | ||
return ContentBlock; | ||
})(ContentBlockRecord); | ||
}(ContentBlockRecord); | ||
@@ -124,0 +118,0 @@ function haveEqualStyle(charA, charB) { |
@@ -16,10 +16,8 @@ /** | ||
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
var _get = function get(_x2, _x3, _x4) { var _again = true; _function: while (_again) { var object = _x2, property = _x3, receiver = _x4; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x2 = parent; _x3 = property; _x4 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; | ||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
var BlockMapBuilder = require('./BlockMapBuilder'); | ||
@@ -38,2 +36,3 @@ var CharacterMetadata = require('./CharacterMetadata'); | ||
var defaultRecord = { | ||
@@ -47,3 +46,3 @@ blockMap: null, | ||
var ContentState = (function (_ContentStateRecord) { | ||
var ContentState = function (_ContentStateRecord) { | ||
_inherits(ContentState, _ContentStateRecord); | ||
@@ -54,115 +53,98 @@ | ||
_get(Object.getPrototypeOf(ContentState.prototype), 'constructor', this).apply(this, arguments); | ||
return _possibleConstructorReturn(this, _ContentStateRecord.apply(this, arguments)); | ||
} | ||
_createClass(ContentState, [{ | ||
key: 'getBlockMap', | ||
value: function getBlockMap() { | ||
return this.get('blockMap'); | ||
} | ||
}, { | ||
key: 'getSelectionBefore', | ||
value: function getSelectionBefore() { | ||
return this.get('selectionBefore'); | ||
} | ||
}, { | ||
key: 'getSelectionAfter', | ||
value: function getSelectionAfter() { | ||
return this.get('selectionAfter'); | ||
} | ||
}, { | ||
key: 'getBlockForKey', | ||
value: function getBlockForKey(key) { | ||
var block = this.getBlockMap().get(key); | ||
return block; | ||
} | ||
}, { | ||
key: 'getKeyBefore', | ||
value: function getKeyBefore(key) { | ||
return this.getBlockMap().reverse().keySeq().skipUntil(function (v) { | ||
return v === key; | ||
}).skip(1).first(); | ||
} | ||
}, { | ||
key: 'getKeyAfter', | ||
value: function getKeyAfter(key) { | ||
return this.getBlockMap().keySeq().skipUntil(function (v) { | ||
return v === key; | ||
}).skip(1).first(); | ||
} | ||
}, { | ||
key: 'getBlockAfter', | ||
value: function getBlockAfter(key) { | ||
return this.getBlockMap().skipUntil(function (_, k) { | ||
return k === key; | ||
}).skip(1).first(); | ||
} | ||
}, { | ||
key: 'getBlockBefore', | ||
value: function getBlockBefore(key) { | ||
return this.getBlockMap().reverse().skipUntil(function (_, k) { | ||
return k === key; | ||
}).skip(1).first(); | ||
} | ||
}, { | ||
key: 'getBlocksAsArray', | ||
value: function getBlocksAsArray() { | ||
return this.getBlockMap().toArray(); | ||
} | ||
}, { | ||
key: 'getFirstBlock', | ||
value: function getFirstBlock() { | ||
return this.getBlockMap().first(); | ||
} | ||
}, { | ||
key: 'getLastBlock', | ||
value: function getLastBlock() { | ||
return this.getBlockMap().last(); | ||
} | ||
}, { | ||
key: 'getPlainText', | ||
value: function getPlainText(delimiter) { | ||
return this.getBlockMap().map(function (block) { | ||
return block ? block.getText() : ''; | ||
}).join(delimiter || '\n'); | ||
} | ||
}, { | ||
key: 'hasText', | ||
value: function hasText() { | ||
var blockMap = this.getBlockMap(); | ||
return blockMap.size > 1 || blockMap.first().getLength() > 0; | ||
} | ||
}], [{ | ||
key: 'createFromBlockArray', | ||
value: function createFromBlockArray(blocks) { | ||
var blockMap = BlockMapBuilder.createFromArray(blocks); | ||
var selectionState = SelectionState.createEmpty(blockMap.first().getKey()); | ||
return new ContentState({ | ||
blockMap: blockMap, | ||
selectionBefore: selectionState, | ||
selectionAfter: selectionState | ||
}); | ||
} | ||
}, { | ||
key: 'createFromText', | ||
value: function createFromText(text) { | ||
var delimiter = arguments.length <= 1 || arguments[1] === undefined ? /\r\n?|\n/g : arguments[1]; | ||
ContentState.prototype.getBlockMap = function getBlockMap() { | ||
return this.get('blockMap'); | ||
}; | ||
var strings = text.split(delimiter); | ||
var blocks = strings.map(function (block) { | ||
block = sanitizeDraftText(block); | ||
return new ContentBlock({ | ||
key: generateRandomKey(), | ||
text: block, | ||
type: 'unstyled', | ||
characterList: List(Repeat(CharacterMetadata.EMPTY, block.length)) | ||
}); | ||
ContentState.prototype.getSelectionBefore = function getSelectionBefore() { | ||
return this.get('selectionBefore'); | ||
}; | ||
ContentState.prototype.getSelectionAfter = function getSelectionAfter() { | ||
return this.get('selectionAfter'); | ||
}; | ||
ContentState.prototype.getBlockForKey = function getBlockForKey(key) { | ||
var block = this.getBlockMap().get(key); | ||
return block; | ||
}; | ||
ContentState.prototype.getKeyBefore = function getKeyBefore(key) { | ||
return this.getBlockMap().reverse().keySeq().skipUntil(function (v) { | ||
return v === key; | ||
}).skip(1).first(); | ||
}; | ||
ContentState.prototype.getKeyAfter = function getKeyAfter(key) { | ||
return this.getBlockMap().keySeq().skipUntil(function (v) { | ||
return v === key; | ||
}).skip(1).first(); | ||
}; | ||
ContentState.prototype.getBlockAfter = function getBlockAfter(key) { | ||
return this.getBlockMap().skipUntil(function (_, k) { | ||
return k === key; | ||
}).skip(1).first(); | ||
}; | ||
ContentState.prototype.getBlockBefore = function getBlockBefore(key) { | ||
return this.getBlockMap().reverse().skipUntil(function (_, k) { | ||
return k === key; | ||
}).skip(1).first(); | ||
}; | ||
ContentState.prototype.getBlocksAsArray = function getBlocksAsArray() { | ||
return this.getBlockMap().toArray(); | ||
}; | ||
ContentState.prototype.getFirstBlock = function getFirstBlock() { | ||
return this.getBlockMap().first(); | ||
}; | ||
ContentState.prototype.getLastBlock = function getLastBlock() { | ||
return this.getBlockMap().last(); | ||
}; | ||
ContentState.prototype.getPlainText = function getPlainText(delimiter) { | ||
return this.getBlockMap().map(function (block) { | ||
return block ? block.getText() : ''; | ||
}).join(delimiter || '\n'); | ||
}; | ||
ContentState.prototype.hasText = function hasText() { | ||
var blockMap = this.getBlockMap(); | ||
return blockMap.size > 1 || blockMap.first().getLength() > 0; | ||
}; | ||
ContentState.createFromBlockArray = function createFromBlockArray(blocks) { | ||
var blockMap = BlockMapBuilder.createFromArray(blocks); | ||
var selectionState = SelectionState.createEmpty(blockMap.first().getKey()); | ||
return new ContentState({ | ||
blockMap: blockMap, | ||
selectionBefore: selectionState, | ||
selectionAfter: selectionState | ||
}); | ||
}; | ||
ContentState.createFromText = function createFromText(text) { | ||
var delimiter = arguments.length <= 1 || arguments[1] === undefined ? /\r\n?|\n/g : arguments[1]; | ||
var strings = text.split(delimiter); | ||
var blocks = strings.map(function (block) { | ||
block = sanitizeDraftText(block); | ||
return new ContentBlock({ | ||
key: generateRandomKey(), | ||
text: block, | ||
type: 'unstyled', | ||
characterList: List(Repeat(CharacterMetadata.EMPTY, block.length)) | ||
}); | ||
return ContentState.createFromBlockArray(blocks); | ||
} | ||
}]); | ||
}); | ||
return ContentState.createFromBlockArray(blocks); | ||
}; | ||
return ContentState; | ||
})(ContentStateRecord); | ||
}(ContentStateRecord); | ||
module.exports = ContentState; |
@@ -22,2 +22,3 @@ /** | ||
var ContentStateInlineStyle = { | ||
@@ -24,0 +25,0 @@ add: function add(contentState, selectionState, inlineStyle) { |
@@ -43,3 +43,4 @@ /** | ||
inlineStyleRanges: encodeInlineStyleRanges(block), | ||
entityRanges: encodeEntityRanges(block, entityStorageMap) | ||
entityRanges: encodeEntityRanges(block, entityStorageMap), | ||
data: block.getData().toObject() | ||
}); | ||
@@ -46,0 +47,0 @@ }); |
@@ -32,2 +32,3 @@ /** | ||
var NBSP = ' '; | ||
@@ -43,3 +44,9 @@ var SPACE = ' '; | ||
var REGEX_NBSP = new RegExp(NBSP, 'g'); | ||
var REGEX_CARRIAGE = new RegExp(' ?', 'g'); | ||
var REGEX_ZWS = new RegExp('​?', 'g'); | ||
// https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight | ||
var boldValues = ['bold', 'bolder', '500', '600', '700', '800', '900']; | ||
var notBoldValues = ['light', 'lighter', '100', '200', '300', '400']; | ||
// Block tag flow is different because LIs do not have | ||
@@ -59,2 +66,4 @@ // a deterministic style ;_; | ||
var anchorAttr = ['className', 'href', 'rel', 'target', 'title']; | ||
var lastBlock; | ||
@@ -117,3 +126,3 @@ | ||
}).valueSeq().toSet().filter(function (tag) { | ||
return tag !== unstyledElement; | ||
return tag && tag !== unstyledElement; | ||
}).toArray().sort(); | ||
@@ -159,17 +168,28 @@ } | ||
currentStyle = currentStyle.withMutations(function (style) { | ||
if (htmlElement.style.fontWeight === 'bold') { | ||
var fontWeight = htmlElement.style.fontWeight; | ||
var fontStyle = htmlElement.style.fontStyle; | ||
var textDecoration = htmlElement.style.textDecoration; | ||
if (boldValues.indexOf(fontWeight) >= 0) { | ||
style.add('BOLD'); | ||
} else if (notBoldValues.indexOf(fontWeight) >= 0) { | ||
style.remove('BOLD'); | ||
} | ||
if (htmlElement.style.fontStyle === 'italic') { | ||
if (fontStyle === 'italic') { | ||
style.add('ITALIC'); | ||
} else if (fontStyle === 'normal') { | ||
style.remove('ITALIC'); | ||
} | ||
if (htmlElement.style.textDecoration === 'underline') { | ||
if (textDecoration === 'underline') { | ||
style.add('UNDERLINE'); | ||
} | ||
if (htmlElement.style.textDecoration === 'line-through') { | ||
if (textDecoration === 'line-through') { | ||
style.add('STRIKETHROUGH'); | ||
} | ||
if (textDecoration === 'none') { | ||
style.remove('UNDERLINE'); | ||
style.remove('STRIKETHROUGH'); | ||
} | ||
}).toOrderedSet(); | ||
@@ -184,5 +204,6 @@ })(); | ||
// extra delimiter to preserve niceness. | ||
var lastInB = B.text.slice(0, 1); | ||
var lastInA = A.text.slice(-1); | ||
var firstInB = B.text.slice(0, 1); | ||
if (A.text.slice(-1) === '\r' && lastInB === '\r') { | ||
if (lastInA === '\r' && firstInB === '\r') { | ||
A.text = A.text.slice(0, -1); | ||
@@ -195,6 +216,6 @@ A.inlines.pop(); | ||
// Kill whitespace after blocks | ||
if (A.text.slice(-1) === '\r') { | ||
if (lastInA === '\r') { | ||
if (B.text === SPACE || B.text === '\n') { | ||
return A; | ||
} else if (lastInB === SPACE || lastInB === '\n') { | ||
} else if (firstInB === SPACE || firstInB === '\n') { | ||
B.text = B.text.slice(1); | ||
@@ -226,5 +247,5 @@ B.inlines.shift(); | ||
function hasValidLinkText(link) { | ||
!(link instanceof HTMLAnchorElement) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Link must be an HTMLAnchorElement.') : invariant(false) : undefined; | ||
!(link instanceof HTMLAnchorElement) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Link must be an HTMLAnchorElement.') : invariant(false) : void 0; | ||
var protocol = link.protocol; | ||
return protocol === 'http:' || protocol === 'https:'; | ||
return protocol === 'http:' || protocol === 'https:' || protocol === 'mailto:'; | ||
} | ||
@@ -304,8 +325,20 @@ | ||
var entityId = null; | ||
var href = null; | ||
while (child) { | ||
if (nodeName === 'a' && child.href && hasValidLinkText(child)) { | ||
href = new URI(child.href).toString(); | ||
entityId = DraftEntity.create('LINK', 'MUTABLE', { url: href }); | ||
if (child instanceof HTMLAnchorElement && child.href && hasValidLinkText(child)) { | ||
(function () { | ||
var anchor = child; | ||
var entityConfig = {}; | ||
anchorAttr.forEach(function (attr) { | ||
var anchorAttribute = anchor.getAttribute(attr); | ||
if (anchorAttribute) { | ||
entityConfig[attr] = anchorAttribute; | ||
} | ||
}); | ||
entityConfig.url = new URI(anchor.href).toString(); | ||
entityId = DraftEntity.create('LINK', 'MUTABLE', entityConfig); | ||
})(); | ||
} else { | ||
@@ -338,3 +371,3 @@ entityId = undefined; | ||
function getChunkForHTML(html, DOMBuilder, blockRenderMap) { | ||
html = html.trim().replace(REGEX_CR, '').replace(REGEX_NBSP, SPACE); | ||
html = html.trim().replace(REGEX_CR, '').replace(REGEX_NBSP, SPACE).replace(REGEX_CARRIAGE, '').replace(REGEX_ZWS, ''); | ||
@@ -395,3 +428,3 @@ var supportedBlockTags = getBlockMapSupportedTags(blockRenderMap); | ||
// Be ABSOLUTELY SURE that the dom builder you pass hare won't execute | ||
// Be ABSOLUTELY SURE that the dom builder you pass here won't execute | ||
// arbitrary code in whatever environment you're running this in. For an | ||
@@ -398,0 +431,0 @@ // example of how we try to do this in-browser, see getSafeBodyFromHTML. |
@@ -15,7 +15,10 @@ /** | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var _assign = require('object-assign'); | ||
var _extends = _assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var ContentBlock = require('./ContentBlock'); | ||
var ContentState = require('./ContentState'); | ||
var DraftEntity = require('./DraftEntity'); | ||
var Immutable = require('immutable'); | ||
@@ -27,2 +30,5 @@ var createCharacterList = require('./createCharacterList'); | ||
var Map = Immutable.Map; | ||
function convertFromRawToDraftState(rawState) { | ||
@@ -32,2 +38,3 @@ var blocks = rawState.blocks; | ||
var fromStorageToLocal = {}; | ||
@@ -51,2 +58,3 @@ Object.keys(entityMap).forEach(function (storageKey) { | ||
var entityRanges = block.entityRanges; | ||
var data = block.data; | ||
@@ -57,2 +65,3 @@ key = key || generateRandomKey(); | ||
entityRanges = entityRanges || []; | ||
data = Map(data); | ||
@@ -71,3 +80,3 @@ var inlineStyles = decodeInlineStyleRanges(text, inlineStyleRanges); | ||
return new ContentBlock({ key: key, type: type, text: text, depth: depth, characterList: characterList }); | ||
return new ContentBlock({ key: key, type: type, text: text, depth: depth, characterList: characterList, data: data }); | ||
}); | ||
@@ -74,0 +83,0 @@ |
@@ -21,2 +21,3 @@ /** | ||
function createCharacterList(inlineStyles, entities) { | ||
@@ -23,0 +24,0 @@ var characterArray = inlineStyles.map(function (style, ii) { |
@@ -23,2 +23,3 @@ /** | ||
*/ | ||
function decodeEntityRanges(text, ranges) { | ||
@@ -25,0 +26,0 @@ var entities = Array(text.length).fill(null); |
@@ -23,2 +23,3 @@ /** | ||
var EMPTY_SET = OrderedSet(); | ||
@@ -25,0 +26,0 @@ |
@@ -13,6 +13,2 @@ /** | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
'use strict'; |
@@ -13,6 +13,2 @@ /** | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
'use strict'; |
@@ -13,6 +13,2 @@ /** | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
'use strict'; |
@@ -17,5 +17,2 @@ /** | ||
* The list of default valid block tags. | ||
*/ | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
*/ |
@@ -17,5 +17,2 @@ /** | ||
* The list of default valid block types. | ||
*/ | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
*/ |
@@ -13,21 +13,2 @@ /** | ||
/** | ||
* A DraftDecorator is a strategy-component pair intended for use when | ||
* rendering content. | ||
* | ||
* - A "strategy": A function that accepts a ContentBlock object and | ||
* continuously executes a callback with start/end values corresponding to | ||
* relevant matches in the document text. For example, getHashtagMatches | ||
* uses a hashtag regex to find hashtag strings in the block, and | ||
* for each hashtag match, executes the callback with start/end pairs. | ||
* | ||
* - A "component": A React component that will be used to render the | ||
* "decorated" section of text. | ||
* | ||
* - "props": Props to be passed into the React component that will be used. | ||
*/ | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
'use strict'; |
@@ -13,26 +13,2 @@ /** | ||
/** | ||
* An interface for document decorator classes, allowing the creation of | ||
* custom decorator classes. | ||
* | ||
* See `CompositeDraftDecorator` for the most common use case. | ||
*/ | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
/** | ||
* Given a `ContentBlock`, return an immutable List of decorator keys. | ||
*/ | ||
/** | ||
* Given a decorator key, return the component to use when rendering | ||
* this decorated range. | ||
*/ | ||
/** | ||
* Given a decorator key, optionally return the props to use when rendering | ||
* this decorated range. | ||
*/ | ||
'use strict'; |
@@ -18,5 +18,2 @@ /** | ||
* around to indicate whether a drag type is internal or external. | ||
*/ | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
*/ |
@@ -16,11 +16,11 @@ /** | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var _assign = require('object-assign'); | ||
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); | ||
var _extends = _assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } | ||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
@@ -69,75 +69,59 @@ var DefaultDraftBlockRenderMap = require('./DefaultDraftBlockRenderMap'); | ||
*/ | ||
var DraftEditor = (function (_React$Component) { | ||
var DraftEditor = function (_React$Component) { | ||
_inherits(DraftEditor, _React$Component); | ||
_createClass(DraftEditor, null, [{ | ||
key: 'defaultProps', | ||
value: { | ||
blockRenderMap: DefaultDraftBlockRenderMap, | ||
blockRendererFn: emptyFunction.thatReturnsNull, | ||
blockStyleFn: emptyFunction.thatReturns(''), | ||
keyBindingFn: getDefaultKeyBinding, | ||
readOnly: false, | ||
spellCheck: false, | ||
stripPastedStyles: false | ||
}, | ||
enumerable: true | ||
}]); | ||
function DraftEditor(props) { | ||
var _this = this; | ||
_classCallCheck(this, DraftEditor); | ||
_get(Object.getPrototypeOf(DraftEditor.prototype), 'constructor', this).call(this, props); | ||
var _this = _possibleConstructorReturn(this, _React$Component.call(this, props)); | ||
this._blockSelectEvents = false; | ||
this._clipboard = null; | ||
this._guardAgainstRender = false; | ||
this._handler = null; | ||
this._dragCount = 0; | ||
this._editorKey = generateRandomKey(); | ||
this._placeholderAccessibilityID = 'placeholder-' + this._editorKey; | ||
_this._blockSelectEvents = false; | ||
_this._clipboard = null; | ||
_this._guardAgainstRender = false; | ||
_this._handler = null; | ||
_this._dragCount = 0; | ||
_this._editorKey = generateRandomKey(); | ||
_this._placeholderAccessibilityID = 'placeholder-' + _this._editorKey; | ||
this._onBeforeInput = this._buildHandler('onBeforeInput'); | ||
this._onBlur = this._buildHandler('onBlur'); | ||
this._onCharacterData = this._buildHandler('onCharacterData'); | ||
this._onCompositionEnd = this._buildHandler('onCompositionEnd'); | ||
this._onCompositionStart = this._buildHandler('onCompositionStart'); | ||
this._onCopy = this._buildHandler('onCopy'); | ||
this._onCut = this._buildHandler('onCut'); | ||
this._onDragEnd = this._buildHandler('onDragEnd'); | ||
this._onDragOver = this._buildHandler('onDragOver'); | ||
this._onDragStart = this._buildHandler('onDragStart'); | ||
this._onDrop = this._buildHandler('onDrop'); | ||
this._onInput = this._buildHandler('onInput'); | ||
this._onFocus = this._buildHandler('onFocus'); | ||
this._onKeyDown = this._buildHandler('onKeyDown'); | ||
this._onKeyPress = this._buildHandler('onKeyPress'); | ||
this._onKeyUp = this._buildHandler('onKeyUp'); | ||
this._onMouseDown = this._buildHandler('onMouseDown'); | ||
this._onMouseUp = this._buildHandler('onMouseUp'); | ||
this._onPaste = this._buildHandler('onPaste'); | ||
this._onSelect = this._buildHandler('onSelect'); | ||
_this._onBeforeInput = _this._buildHandler('onBeforeInput'); | ||
_this._onBlur = _this._buildHandler('onBlur'); | ||
_this._onCharacterData = _this._buildHandler('onCharacterData'); | ||
_this._onCompositionEnd = _this._buildHandler('onCompositionEnd'); | ||
_this._onCompositionStart = _this._buildHandler('onCompositionStart'); | ||
_this._onCopy = _this._buildHandler('onCopy'); | ||
_this._onCut = _this._buildHandler('onCut'); | ||
_this._onDragEnd = _this._buildHandler('onDragEnd'); | ||
_this._onDragOver = _this._buildHandler('onDragOver'); | ||
_this._onDragStart = _this._buildHandler('onDragStart'); | ||
_this._onDrop = _this._buildHandler('onDrop'); | ||
_this._onInput = _this._buildHandler('onInput'); | ||
_this._onFocus = _this._buildHandler('onFocus'); | ||
_this._onKeyDown = _this._buildHandler('onKeyDown'); | ||
_this._onKeyPress = _this._buildHandler('onKeyPress'); | ||
_this._onKeyUp = _this._buildHandler('onKeyUp'); | ||
_this._onMouseDown = _this._buildHandler('onMouseDown'); | ||
_this._onMouseUp = _this._buildHandler('onMouseUp'); | ||
_this._onPaste = _this._buildHandler('onPaste'); | ||
_this._onSelect = _this._buildHandler('onSelect'); | ||
// Manual binding for public and internal methods. | ||
this.focus = this._focus.bind(this); | ||
this.blur = this._blur.bind(this); | ||
this.setMode = this._setMode.bind(this); | ||
this.exitCurrentMode = this._exitCurrentMode.bind(this); | ||
this.restoreEditorDOM = this._restoreEditorDOM.bind(this); | ||
this.setRenderGuard = this._setRenderGuard.bind(this); | ||
this.removeRenderGuard = this._removeRenderGuard.bind(this); | ||
this.setClipboard = this._setClipboard.bind(this); | ||
this.getClipboard = this._getClipboard.bind(this); | ||
this.getEditorKey = function () { | ||
_this.focus = _this._focus.bind(_this); | ||
_this.blur = _this._blur.bind(_this); | ||
_this.setMode = _this._setMode.bind(_this); | ||
_this.exitCurrentMode = _this._exitCurrentMode.bind(_this); | ||
_this.restoreEditorDOM = _this._restoreEditorDOM.bind(_this); | ||
_this.setRenderGuard = _this._setRenderGuard.bind(_this); | ||
_this.removeRenderGuard = _this._removeRenderGuard.bind(_this); | ||
_this.setClipboard = _this._setClipboard.bind(_this); | ||
_this.getClipboard = _this._getClipboard.bind(_this); | ||
_this.getEditorKey = function () { | ||
return _this._editorKey; | ||
}; | ||
this.update = this._update.bind(this); | ||
this.onDragEnter = this._onDragEnter.bind(this); | ||
this.onDragLeave = this._onDragLeave.bind(this); | ||
_this.update = _this._update.bind(_this); | ||
_this.onDragEnter = _this._onDragEnter.bind(_this); | ||
_this.onDragLeave = _this._onDragLeave.bind(_this); | ||
// See `_restoreEditorDOM()`. | ||
this.state = { containerKey: 0 }; | ||
_this.state = { containerKey: 0 }; | ||
return _this; | ||
} | ||
@@ -151,316 +135,319 @@ | ||
_createClass(DraftEditor, [{ | ||
key: '_buildHandler', | ||
value: function _buildHandler(eventName) { | ||
var _this2 = this; | ||
return function (e) { | ||
if (!_this2.props.readOnly) { | ||
var method = _this2._handler && _this2._handler[eventName]; | ||
method && method.call(_this2, e); | ||
} | ||
}; | ||
} | ||
}, { | ||
key: '_showPlaceholder', | ||
value: function _showPlaceholder() { | ||
return !!this.props.placeholder && !this.props.editorState.isInCompositionMode() && !this.props.editorState.getCurrentContent().hasText(); | ||
} | ||
}, { | ||
key: '_renderPlaceholder', | ||
value: function _renderPlaceholder() { | ||
if (this._showPlaceholder()) { | ||
return React.createElement(DraftEditorPlaceholder, { | ||
text: nullthrows(this.props.placeholder), | ||
editorState: this.props.editorState, | ||
textAlignment: this.props.textAlignment, | ||
accessibilityID: this._placeholderAccessibilityID | ||
}); | ||
/** | ||
* Define proxies that can route events to the current handler. | ||
*/ | ||
DraftEditor.prototype._buildHandler = function _buildHandler(eventName) { | ||
var _this2 = this; | ||
return function (e) { | ||
if (!_this2.props.readOnly) { | ||
var method = _this2._handler && _this2._handler[eventName]; | ||
method && method.call(_this2, e); | ||
} | ||
return null; | ||
} | ||
}, { | ||
key: 'render', | ||
value: function render() { | ||
var _props = this.props; | ||
var readOnly = _props.readOnly; | ||
var textAlignment = _props.textAlignment; | ||
}; | ||
}; | ||
var rootClass = cx({ | ||
'DraftEditor/root': true, | ||
'DraftEditor/alignLeft': textAlignment === 'left', | ||
'DraftEditor/alignRight': textAlignment === 'right', | ||
'DraftEditor/alignCenter': textAlignment === 'center' | ||
DraftEditor.prototype._showPlaceholder = function _showPlaceholder() { | ||
return !!this.props.placeholder && !this.props.editorState.isInCompositionMode() && !this.props.editorState.getCurrentContent().hasText(); | ||
}; | ||
DraftEditor.prototype._renderPlaceholder = function _renderPlaceholder() { | ||
if (this._showPlaceholder()) { | ||
return React.createElement(DraftEditorPlaceholder, { | ||
text: nullthrows(this.props.placeholder), | ||
editorState: this.props.editorState, | ||
textAlignment: this.props.textAlignment, | ||
accessibilityID: this._placeholderAccessibilityID | ||
}); | ||
var hasContent = this.props.editorState.getCurrentContent().hasText(); | ||
} | ||
return null; | ||
}; | ||
var contentStyle = { | ||
outline: 'none', | ||
whiteSpace: 'pre-wrap', | ||
wordWrap: 'break-word' | ||
}; | ||
DraftEditor.prototype.render = function render() { | ||
var _props = this.props; | ||
var readOnly = _props.readOnly; | ||
var textAlignment = _props.textAlignment; | ||
return React.createElement( | ||
var rootClass = cx({ | ||
'DraftEditor/root': true, | ||
'DraftEditor/alignLeft': textAlignment === 'left', | ||
'DraftEditor/alignRight': textAlignment === 'right', | ||
'DraftEditor/alignCenter': textAlignment === 'center' | ||
}); | ||
var contentStyle = { | ||
outline: 'none', | ||
whiteSpace: 'pre-wrap', | ||
wordWrap: 'break-word' | ||
}; | ||
return React.createElement( | ||
'div', | ||
{ className: rootClass }, | ||
this._renderPlaceholder(), | ||
React.createElement( | ||
'div', | ||
{ className: rootClass }, | ||
this._renderPlaceholder(), | ||
{ | ||
className: cx('DraftEditor/editorContainer'), | ||
key: 'editor' + this.state.containerKey, | ||
ref: 'editorContainer' }, | ||
React.createElement( | ||
'div', | ||
{ | ||
className: cx('DraftEditor/editorContainer'), | ||
key: 'editor' + this.state.containerKey, | ||
ref: 'editorContainer' }, | ||
React.createElement( | ||
'div', | ||
{ | ||
'aria-activedescendant': readOnly ? null : this.props.ariaActiveDescendantID, | ||
'aria-autocomplete': readOnly ? null : this.props.ariaAutoComplete, | ||
'aria-describedby': this._showPlaceholder() ? this._placeholderAccessibilityID : null, | ||
'aria-expanded': readOnly ? null : this.props.ariaExpanded, | ||
'aria-haspopup': readOnly ? null : this.props.ariaHasPopup, | ||
'aria-label': this.props.ariaLabel, | ||
'aria-owns': readOnly ? null : this.props.ariaOwneeID, | ||
className: cx('public/DraftEditor/content'), | ||
contentEditable: !readOnly, | ||
'data-testid': this.props.webDriverTestID, | ||
onBeforeInput: this._onBeforeInput, | ||
onBlur: this._onBlur, | ||
onCompositionEnd: this._onCompositionEnd, | ||
onCompositionStart: this._onCompositionStart, | ||
onCopy: this._onCopy, | ||
onCut: this._onCut, | ||
onDragEnd: this._onDragEnd, | ||
onDragEnter: this.onDragEnter, | ||
onDragLeave: this.onDragLeave, | ||
onDragOver: this._onDragOver, | ||
onDragStart: this._onDragStart, | ||
onDrop: this._onDrop, | ||
onFocus: this._onFocus, | ||
onInput: this._onInput, | ||
onKeyDown: this._onKeyDown, | ||
onKeyPress: this._onKeyPress, | ||
onKeyUp: this._onKeyUp, | ||
onMouseUp: this._onMouseUp, | ||
onPaste: this._onPaste, | ||
onSelect: this._onSelect, | ||
ref: 'editor', | ||
role: readOnly ? null : this.props.role || 'textbox', | ||
spellCheck: allowSpellCheck && this.props.spellCheck, | ||
style: contentStyle, | ||
suppressContentEditableWarning: true, | ||
tabIndex: this.props.tabIndex }, | ||
React.createElement(DraftEditorContents, { | ||
blockRenderMap: this.props.blockRenderMap, | ||
blockRendererFn: this.props.blockRendererFn, | ||
blockStyleFn: this.props.blockStyleFn, | ||
customStyleMap: _extends({}, DefaultDraftInlineStyle, this.props.customStyleMap), | ||
editorKey: this._editorKey, | ||
editorState: this.props.editorState | ||
}) | ||
) | ||
'aria-activedescendant': readOnly ? null : this.props.ariaActiveDescendantID, | ||
'aria-autocomplete': readOnly ? null : this.props.ariaAutoComplete, | ||
'aria-describedby': this._showPlaceholder() ? this._placeholderAccessibilityID : null, | ||
'aria-expanded': readOnly ? null : this.props.ariaExpanded, | ||
'aria-haspopup': readOnly ? null : this.props.ariaHasPopup, | ||
'aria-label': this.props.ariaLabel, | ||
'aria-owns': readOnly ? null : this.props.ariaOwneeID, | ||
className: cx('public/DraftEditor/content'), | ||
contentEditable: !readOnly, | ||
'data-testid': this.props.webDriverTestID, | ||
onBeforeInput: this._onBeforeInput, | ||
onBlur: this._onBlur, | ||
onCompositionEnd: this._onCompositionEnd, | ||
onCompositionStart: this._onCompositionStart, | ||
onCopy: this._onCopy, | ||
onCut: this._onCut, | ||
onDragEnd: this._onDragEnd, | ||
onDragEnter: this.onDragEnter, | ||
onDragLeave: this.onDragLeave, | ||
onDragOver: this._onDragOver, | ||
onDragStart: this._onDragStart, | ||
onDrop: this._onDrop, | ||
onFocus: this._onFocus, | ||
onInput: this._onInput, | ||
onKeyDown: this._onKeyDown, | ||
onKeyPress: this._onKeyPress, | ||
onKeyUp: this._onKeyUp, | ||
onMouseUp: this._onMouseUp, | ||
onPaste: this._onPaste, | ||
onSelect: this._onSelect, | ||
ref: 'editor', | ||
role: readOnly ? null : this.props.role || 'textbox', | ||
spellCheck: allowSpellCheck && this.props.spellCheck, | ||
style: contentStyle, | ||
suppressContentEditableWarning: true, | ||
tabIndex: this.props.tabIndex }, | ||
React.createElement(DraftEditorContents, { | ||
blockRenderMap: this.props.blockRenderMap, | ||
blockRendererFn: this.props.blockRendererFn, | ||
blockStyleFn: this.props.blockStyleFn, | ||
customStyleMap: _extends({}, DefaultDraftInlineStyle, this.props.customStyleMap), | ||
customStyleFn: this.props.customStyleFn, | ||
editorKey: this._editorKey, | ||
editorState: this.props.editorState | ||
}) | ||
) | ||
); | ||
} | ||
}, { | ||
key: 'componentDidMount', | ||
value: function componentDidMount() { | ||
this.setMode('edit'); | ||
) | ||
); | ||
}; | ||
/** | ||
* IE has a hardcoded "feature" that attempts to convert link text into | ||
* anchors in contentEditable DOM. This breaks the editor's expectations of | ||
* the DOM, and control is lost. Disable it to make IE behave. | ||
* See: http://blogs.msdn.com/b/ieinternals/archive/2010/09/15/ | ||
* ie9-beta-minor-change-list.aspx | ||
*/ | ||
if (isIE) { | ||
document.execCommand('AutoUrlDetect', false, false); | ||
} | ||
} | ||
DraftEditor.prototype.componentDidMount = function componentDidMount() { | ||
this.setMode('edit'); | ||
/** | ||
* Prevent selection events from affecting the current editor state. This | ||
* is mostly intended to defend against IE, which fires off `selectionchange` | ||
* events regardless of whether the selection is set via the browser or | ||
* programmatically. We only care about selection events that occur because | ||
* of browser interaction, not re-renders and forced selections. | ||
* IE has a hardcoded "feature" that attempts to convert link text into | ||
* anchors in contentEditable DOM. This breaks the editor's expectations of | ||
* the DOM, and control is lost. Disable it to make IE behave. | ||
* See: http://blogs.msdn.com/b/ieinternals/archive/2010/09/15/ | ||
* ie9-beta-minor-change-list.aspx | ||
*/ | ||
}, { | ||
key: 'componentWillUpdate', | ||
value: function componentWillUpdate() { | ||
this._blockSelectEvents = true; | ||
if (isIE) { | ||
document.execCommand('AutoUrlDetect', false, false); | ||
} | ||
}, { | ||
key: 'componentDidUpdate', | ||
value: function componentDidUpdate() { | ||
this._blockSelectEvents = false; | ||
} | ||
}; | ||
/** | ||
* Used via `this.focus()`. | ||
* | ||
* Force focus back onto the editor node. | ||
* | ||
* Forcing focus causes the browser to scroll to the top of the editor, which | ||
* may be undesirable when the editor is taller than the viewport. To solve | ||
* this, either use a specified scroll position (in cases like `cut` behavior | ||
* where it should be restored to a known position) or store the current | ||
* scroll state and put it back in place after focus has been forced. | ||
*/ | ||
}, { | ||
key: '_focus', | ||
value: function _focus(scrollPosition) { | ||
var editorState = this.props.editorState; | ||
/** | ||
* Prevent selection events from affecting the current editor state. This | ||
* is mostly intended to defend against IE, which fires off `selectionchange` | ||
* events regardless of whether the selection is set via the browser or | ||
* programmatically. We only care about selection events that occur because | ||
* of browser interaction, not re-renders and forced selections. | ||
*/ | ||
var alreadyHasFocus = editorState.getSelection().getHasFocus(); | ||
var editorNode = ReactDOM.findDOMNode(this.refs.editor); | ||
var scrollParent = Style.getScrollParent(editorNode); | ||
DraftEditor.prototype.componentWillUpdate = function componentWillUpdate() { | ||
this._blockSelectEvents = true; | ||
}; | ||
var _ref = scrollPosition || getScrollPosition(scrollParent); | ||
DraftEditor.prototype.componentDidUpdate = function componentDidUpdate() { | ||
this._blockSelectEvents = false; | ||
}; | ||
var x = _ref.x; | ||
var y = _ref.y; | ||
/** | ||
* Used via `this.focus()`. | ||
* | ||
* Force focus back onto the editor node. | ||
* | ||
* Forcing focus causes the browser to scroll to the top of the editor, which | ||
* may be undesirable when the editor is taller than the viewport. To solve | ||
* this, either use a specified scroll position (in cases like `cut` behavior | ||
* where it should be restored to a known position) or store the current | ||
* scroll state and put it back in place after focus has been forced. | ||
*/ | ||
editorNode.focus(); | ||
if (scrollParent === window) { | ||
window.scrollTo(x, y); | ||
} else { | ||
Scroll.setTop(scrollParent, y); | ||
} | ||
// On Chrome and Safari, calling focus on contenteditable focuses the | ||
// cursor at the first character. This is something you don't expect when | ||
// you're clicking on an input element but not directly on a character. | ||
// Put the cursor back where it was before the blur. | ||
if (!alreadyHasFocus) { | ||
this.update(EditorState.forceSelection(editorState, editorState.getSelection())); | ||
} | ||
} | ||
}, { | ||
key: '_blur', | ||
value: function _blur() { | ||
ReactDOM.findDOMNode(this.refs.editor).blur(); | ||
} | ||
DraftEditor.prototype._focus = function _focus(scrollPosition) { | ||
var editorState = this.props.editorState; | ||
/** | ||
* Used via `this.setMode(...)`. | ||
* | ||
* Set the behavior mode for the editor component. This switches the current | ||
* handler module to ensure that DOM events are managed appropriately for | ||
* the active mode. | ||
*/ | ||
}, { | ||
key: '_setMode', | ||
value: function _setMode(mode) { | ||
this._handler = handlerMap[mode]; | ||
} | ||
}, { | ||
key: '_exitCurrentMode', | ||
value: function _exitCurrentMode() { | ||
this.setMode('edit'); | ||
} | ||
var alreadyHasFocus = editorState.getSelection().getHasFocus(); | ||
var editorNode = ReactDOM.findDOMNode(this.refs.editor); | ||
/** | ||
* Used via `this.restoreEditorDOM()`. | ||
* | ||
* Force a complete re-render of the editor based on the current EditorState. | ||
* This is useful when we know we are going to lose control of the DOM | ||
* state (cut command, IME) and we want to make sure that reconciliation | ||
* occurs on a version of the DOM that is synchronized with our EditorState. | ||
*/ | ||
}, { | ||
key: '_restoreEditorDOM', | ||
value: function _restoreEditorDOM(scrollPosition) { | ||
var _this3 = this; | ||
var scrollParent = Style.getScrollParent(editorNode); | ||
this.setState({ containerKey: this.state.containerKey + 1 }, function () { | ||
_this3._focus(scrollPosition); | ||
}); | ||
} | ||
var _ref = scrollPosition || getScrollPosition(scrollParent); | ||
/** | ||
* Guard against rendering. Intended for use when we need to manually | ||
* reset editor contents, to ensure that no outside influences lead to | ||
* React reconciliation when we are in an uncertain state. | ||
*/ | ||
}, { | ||
key: '_setRenderGuard', | ||
value: function _setRenderGuard() { | ||
this._guardAgainstRender = true; | ||
} | ||
}, { | ||
key: '_removeRenderGuard', | ||
value: function _removeRenderGuard() { | ||
this._guardAgainstRender = false; | ||
} | ||
var x = _ref.x; | ||
var y = _ref.y; | ||
/** | ||
* Used via `this.setClipboard(...)`. | ||
* | ||
* Set the clipboard state for a cut/copy event. | ||
*/ | ||
}, { | ||
key: '_setClipboard', | ||
value: function _setClipboard(clipboard) { | ||
this._clipboard = clipboard; | ||
} | ||
/** | ||
* Used via `this.getClipboard()`. | ||
* | ||
* Retrieve the clipboard state for a cut/copy event. | ||
*/ | ||
}, { | ||
key: '_getClipboard', | ||
value: function _getClipboard() { | ||
return this._clipboard; | ||
editorNode.focus(); | ||
if (scrollParent === window) { | ||
window.scrollTo(x, y); | ||
} else { | ||
Scroll.setTop(scrollParent, y); | ||
} | ||
/** | ||
* Used via `this.update(...)`. | ||
* | ||
* Propagate a new `EditorState` object to higher-level components. This is | ||
* the method by which event handlers inform the `DraftEditor` component of | ||
* state changes. A component that composes a `DraftEditor` **must** provide | ||
* an `onChange` prop to receive state updates passed along from this | ||
* function. | ||
*/ | ||
}, { | ||
key: '_update', | ||
value: function _update(editorState) { | ||
this.props.onChange(editorState); | ||
// On Chrome and Safari, calling focus on contenteditable focuses the | ||
// cursor at the first character. This is something you don't expect when | ||
// you're clicking on an input element but not directly on a character. | ||
// Put the cursor back where it was before the blur. | ||
if (!alreadyHasFocus) { | ||
this.update(EditorState.forceSelection(editorState, editorState.getSelection())); | ||
} | ||
}; | ||
/** | ||
* Used in conjunction with `_onDragLeave()`, by counting the number of times | ||
* a dragged element enters and leaves the editor (or any of its children), | ||
* to determine when the dragged element absolutely leaves the editor. | ||
*/ | ||
}, { | ||
key: '_onDragEnter', | ||
value: function _onDragEnter() { | ||
this._dragCount++; | ||
} | ||
DraftEditor.prototype._blur = function _blur() { | ||
ReactDOM.findDOMNode(this.refs.editor).blur(); | ||
}; | ||
/** | ||
* See `_onDragEnter()`. | ||
*/ | ||
}, { | ||
key: '_onDragLeave', | ||
value: function _onDragLeave() { | ||
this._dragCount--; | ||
if (this._dragCount === 0) { | ||
this.exitCurrentMode(); | ||
} | ||
/** | ||
* Used via `this.setMode(...)`. | ||
* | ||
* Set the behavior mode for the editor component. This switches the current | ||
* handler module to ensure that DOM events are managed appropriately for | ||
* the active mode. | ||
*/ | ||
DraftEditor.prototype._setMode = function _setMode(mode) { | ||
this._handler = handlerMap[mode]; | ||
}; | ||
DraftEditor.prototype._exitCurrentMode = function _exitCurrentMode() { | ||
this.setMode('edit'); | ||
}; | ||
/** | ||
* Used via `this.restoreEditorDOM()`. | ||
* | ||
* Force a complete re-render of the editor based on the current EditorState. | ||
* This is useful when we know we are going to lose control of the DOM | ||
* state (cut command, IME) and we want to make sure that reconciliation | ||
* occurs on a version of the DOM that is synchronized with our EditorState. | ||
*/ | ||
DraftEditor.prototype._restoreEditorDOM = function _restoreEditorDOM(scrollPosition) { | ||
var _this3 = this; | ||
this.setState({ containerKey: this.state.containerKey + 1 }, function () { | ||
_this3._focus(scrollPosition); | ||
}); | ||
}; | ||
/** | ||
* Guard against rendering. Intended for use when we need to manually | ||
* reset editor contents, to ensure that no outside influences lead to | ||
* React reconciliation when we are in an uncertain state. | ||
*/ | ||
DraftEditor.prototype._setRenderGuard = function _setRenderGuard() { | ||
this._guardAgainstRender = true; | ||
}; | ||
DraftEditor.prototype._removeRenderGuard = function _removeRenderGuard() { | ||
this._guardAgainstRender = false; | ||
}; | ||
/** | ||
* Used via `this.setClipboard(...)`. | ||
* | ||
* Set the clipboard state for a cut/copy event. | ||
*/ | ||
DraftEditor.prototype._setClipboard = function _setClipboard(clipboard) { | ||
this._clipboard = clipboard; | ||
}; | ||
/** | ||
* Used via `this.getClipboard()`. | ||
* | ||
* Retrieve the clipboard state for a cut/copy event. | ||
*/ | ||
DraftEditor.prototype._getClipboard = function _getClipboard() { | ||
return this._clipboard; | ||
}; | ||
/** | ||
* Used via `this.update(...)`. | ||
* | ||
* Propagate a new `EditorState` object to higher-level components. This is | ||
* the method by which event handlers inform the `DraftEditor` component of | ||
* state changes. A component that composes a `DraftEditor` **must** provide | ||
* an `onChange` prop to receive state updates passed along from this | ||
* function. | ||
*/ | ||
DraftEditor.prototype._update = function _update(editorState) { | ||
this.props.onChange(editorState); | ||
}; | ||
/** | ||
* Used in conjunction with `_onDragLeave()`, by counting the number of times | ||
* a dragged element enters and leaves the editor (or any of its children), | ||
* to determine when the dragged element absolutely leaves the editor. | ||
*/ | ||
DraftEditor.prototype._onDragEnter = function _onDragEnter() { | ||
this._dragCount++; | ||
}; | ||
/** | ||
* See `_onDragEnter()`. | ||
*/ | ||
DraftEditor.prototype._onDragLeave = function _onDragLeave() { | ||
this._dragCount--; | ||
if (this._dragCount === 0) { | ||
this.exitCurrentMode(); | ||
} | ||
}]); | ||
}; | ||
return DraftEditor; | ||
})(React.Component); | ||
}(React.Component); | ||
module.exports = DraftEditor; | ||
DraftEditor.defaultProps = { | ||
blockRenderMap: DefaultDraftBlockRenderMap, | ||
blockRendererFn: emptyFunction.thatReturnsNull, | ||
blockStyleFn: emptyFunction.thatReturns(''), | ||
keyBindingFn: getDefaultKeyBinding, | ||
readOnly: false, | ||
spellCheck: false, | ||
stripPastedStyles: false | ||
}; | ||
/** | ||
* Define proxies that can route events to the current handler. | ||
*/ | ||
module.exports = DraftEditor; |
@@ -16,11 +16,11 @@ /** | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var _assign = require('object-assign'); | ||
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); | ||
var _extends = _assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } | ||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
@@ -52,4 +52,3 @@ var ContentBlock = require('./ContentBlock'); | ||
*/ | ||
var DraftEditorBlock = (function (_React$Component) { | ||
var DraftEditorBlock = function (_React$Component) { | ||
_inherits(DraftEditorBlock, _React$Component); | ||
@@ -60,150 +59,147 @@ | ||
_get(Object.getPrototypeOf(DraftEditorBlock.prototype), 'constructor', this).apply(this, arguments); | ||
return _possibleConstructorReturn(this, _React$Component.apply(this, arguments)); | ||
} | ||
DraftEditorBlock.prototype.shouldComponentUpdate = function shouldComponentUpdate(nextProps) { | ||
return this.props.block !== nextProps.block || this.props.tree !== nextProps.tree || this.props.direction !== nextProps.direction || isBlockOnSelectionEdge(nextProps.selection, nextProps.block.getKey()) && nextProps.forceSelection; | ||
}; | ||
/** | ||
* Return whether a block overlaps with either edge of the `SelectionState`. | ||
* When a block is mounted and overlaps the selection state, we need to make | ||
* sure that the cursor is visible to match native behavior. This may not | ||
* be the case if the user has pressed `RETURN` or pasted some content, since | ||
* programatically creating these new blocks and setting the DOM selection | ||
* will miss out on the browser natively scrolling to that position. | ||
* | ||
* To replicate native behavior, if the block overlaps the selection state | ||
* on mount, force the scroll position. Check the scroll state of the scroll | ||
* parent, and adjust it to align the entire block to the bottom of the | ||
* scroll parent. | ||
*/ | ||
_createClass(DraftEditorBlock, [{ | ||
key: 'shouldComponentUpdate', | ||
value: function shouldComponentUpdate(nextProps) { | ||
return this.props.block !== nextProps.block || this.props.tree !== nextProps.tree || this.props.direction !== nextProps.direction || isBlockOnSelectionEdge(nextProps.selection, nextProps.block.getKey()) && nextProps.forceSelection; | ||
DraftEditorBlock.prototype.componentDidMount = function componentDidMount() { | ||
var selection = this.props.selection; | ||
var endKey = selection.getEndKey(); | ||
if (!selection.getHasFocus() || endKey !== this.props.block.getKey()) { | ||
return; | ||
} | ||
/** | ||
* When a block is mounted and overlaps the selection state, we need to make | ||
* sure that the cursor is visible to match native behavior. This may not | ||
* be the case if the user has pressed `RETURN` or pasted some content, since | ||
* programatically creating these new blocks and setting the DOM selection | ||
* will miss out on the browser natively scrolling to that position. | ||
* | ||
* To replicate native behavior, if the block overlaps the selection state | ||
* on mount, force the scroll position. Check the scroll state of the scroll | ||
* parent, and adjust it to align the entire block to the bottom of the | ||
* scroll parent. | ||
*/ | ||
}, { | ||
key: 'componentDidMount', | ||
value: function componentDidMount() { | ||
var selection = this.props.selection; | ||
var endKey = selection.getEndKey(); | ||
if (!selection.getHasFocus() || endKey !== this.props.block.getKey()) { | ||
return; | ||
} | ||
var blockNode = ReactDOM.findDOMNode(this); | ||
var scrollParent = Style.getScrollParent(blockNode); | ||
var scrollPosition = getScrollPosition(scrollParent); | ||
var scrollDelta; | ||
var blockNode = ReactDOM.findDOMNode(this); | ||
var scrollParent = Style.getScrollParent(blockNode); | ||
var scrollPosition = getScrollPosition(scrollParent); | ||
var scrollDelta; | ||
if (scrollParent === window) { | ||
var nodePosition = getElementPosition(blockNode); | ||
var nodeBottom = nodePosition.y + nodePosition.height; | ||
var viewportHeight = getViewportDimensions().height; | ||
scrollDelta = nodeBottom - viewportHeight; | ||
if (scrollDelta > 0) { | ||
window.scrollTo(scrollPosition.x, scrollPosition.y + scrollDelta + SCROLL_BUFFER); | ||
} | ||
} else { | ||
var blockBottom = blockNode.offsetHeight + blockNode.offsetTop; | ||
var scrollBottom = scrollParent.offsetHeight + scrollPosition.y; | ||
scrollDelta = blockBottom - scrollBottom; | ||
if (scrollDelta > 0) { | ||
Scroll.setTop(scrollParent, Scroll.getTop(scrollParent) + scrollDelta + SCROLL_BUFFER); | ||
} | ||
if (scrollParent === window) { | ||
var nodePosition = getElementPosition(blockNode); | ||
var nodeBottom = nodePosition.y + nodePosition.height; | ||
var viewportHeight = getViewportDimensions().height; | ||
scrollDelta = nodeBottom - viewportHeight; | ||
if (scrollDelta > 0) { | ||
window.scrollTo(scrollPosition.x, scrollPosition.y + scrollDelta + SCROLL_BUFFER); | ||
} | ||
} else { | ||
var blockBottom = blockNode.offsetHeight + blockNode.offsetTop; | ||
var scrollBottom = scrollParent.offsetHeight + scrollPosition.y; | ||
scrollDelta = blockBottom - scrollBottom; | ||
if (scrollDelta > 0) { | ||
Scroll.setTop(scrollParent, Scroll.getTop(scrollParent) + scrollDelta + SCROLL_BUFFER); | ||
} | ||
} | ||
}, { | ||
key: '_renderChildren', | ||
value: function _renderChildren() { | ||
var _this = this; | ||
}; | ||
var block = this.props.block; | ||
var blockKey = block.getKey(); | ||
var text = block.getText(); | ||
var lastLeafSet = this.props.tree.size - 1; | ||
var hasSelection = isBlockOnSelectionEdge(this.props.selection, blockKey); | ||
DraftEditorBlock.prototype._renderChildren = function _renderChildren() { | ||
var _this2 = this; | ||
return this.props.tree.map(function (leafSet, ii) { | ||
var leavesForLeafSet = leafSet.get('leaves'); | ||
var lastLeaf = leavesForLeafSet.size - 1; | ||
var leaves = leavesForLeafSet.map(function (leaf, jj) { | ||
var offsetKey = DraftOffsetKey.encode(blockKey, ii, jj); | ||
var start = leaf.get('start'); | ||
var end = leaf.get('end'); | ||
return React.createElement(DraftEditorLeaf, { | ||
key: offsetKey, | ||
offsetKey: offsetKey, | ||
blockKey: blockKey, | ||
start: start, | ||
selection: hasSelection ? _this.props.selection : undefined, | ||
forceSelection: _this.props.forceSelection, | ||
text: text.slice(start, end), | ||
styleSet: block.getInlineStyleAt(start), | ||
customStyleMap: _this.props.customStyleMap, | ||
isLast: ii === lastLeafSet && jj === lastLeaf | ||
}); | ||
}).toArray(); | ||
var block = this.props.block; | ||
var blockKey = block.getKey(); | ||
var text = block.getText(); | ||
var lastLeafSet = this.props.tree.size - 1; | ||
var hasSelection = isBlockOnSelectionEdge(this.props.selection, blockKey); | ||
var decoratorKey = leafSet.get('decoratorKey'); | ||
if (decoratorKey == null) { | ||
return leaves; | ||
} | ||
return this.props.tree.map(function (leafSet, ii) { | ||
var leavesForLeafSet = leafSet.get('leaves'); | ||
var lastLeaf = leavesForLeafSet.size - 1; | ||
var leaves = leavesForLeafSet.map(function (leaf, jj) { | ||
var offsetKey = DraftOffsetKey.encode(blockKey, ii, jj); | ||
var start = leaf.get('start'); | ||
var end = leaf.get('end'); | ||
return React.createElement(DraftEditorLeaf, { | ||
key: offsetKey, | ||
offsetKey: offsetKey, | ||
blockKey: blockKey, | ||
start: start, | ||
selection: hasSelection ? _this2.props.selection : undefined, | ||
forceSelection: _this2.props.forceSelection, | ||
text: text.slice(start, end), | ||
styleSet: block.getInlineStyleAt(start), | ||
customStyleMap: _this2.props.customStyleMap, | ||
customStyleFn: _this2.props.customStyleFn, | ||
isLast: ii === lastLeafSet && jj === lastLeaf | ||
}); | ||
}).toArray(); | ||
if (!_this.props.decorator) { | ||
return leaves; | ||
} | ||
var decoratorKey = leafSet.get('decoratorKey'); | ||
if (decoratorKey == null) { | ||
return leaves; | ||
} | ||
var decorator = nullthrows(_this.props.decorator); | ||
if (!_this2.props.decorator) { | ||
return leaves; | ||
} | ||
var DecoratorComponent = decorator.getComponentForKey(decoratorKey); | ||
if (!DecoratorComponent) { | ||
return leaves; | ||
} | ||
var decorator = nullthrows(_this2.props.decorator); | ||
var decoratorProps = decorator.getPropsForKey(decoratorKey); | ||
var decoratorOffsetKey = DraftOffsetKey.encode(blockKey, ii, 0); | ||
var decoratedText = text.slice(leavesForLeafSet.first().get('start'), leavesForLeafSet.last().get('end')); | ||
var DecoratorComponent = decorator.getComponentForKey(decoratorKey); | ||
if (!DecoratorComponent) { | ||
return leaves; | ||
} | ||
// Resetting dir to the same value on a child node makes Chrome/Firefox | ||
// confused on cursor movement. See http://jsfiddle.net/d157kLck/3/ | ||
var dir = UnicodeBidiDirection.getHTMLDirIfDifferent(UnicodeBidi.getDirection(decoratedText), _this.props.direction); | ||
var decoratorProps = decorator.getPropsForKey(decoratorKey); | ||
var decoratorOffsetKey = DraftOffsetKey.encode(blockKey, ii, 0); | ||
var decoratedText = text.slice(leavesForLeafSet.first().get('start'), leavesForLeafSet.last().get('end')); | ||
return React.createElement( | ||
DecoratorComponent, | ||
_extends({}, decoratorProps, { | ||
decoratedText: decoratedText, | ||
dir: dir, | ||
key: decoratorOffsetKey, | ||
entityKey: block.getEntityAt(leafSet.get('start')), | ||
offsetKey: decoratorOffsetKey }), | ||
leaves | ||
); | ||
}).toArray(); | ||
} | ||
}, { | ||
key: 'render', | ||
value: function render() { | ||
var _props = this.props; | ||
var direction = _props.direction; | ||
var offsetKey = _props.offsetKey; | ||
// Resetting dir to the same value on a child node makes Chrome/Firefox | ||
// confused on cursor movement. See http://jsfiddle.net/d157kLck/3/ | ||
var dir = UnicodeBidiDirection.getHTMLDirIfDifferent(UnicodeBidi.getDirection(decoratedText), _this2.props.direction); | ||
var className = cx({ | ||
'public/DraftStyleDefault/block': true, | ||
'public/DraftStyleDefault/ltr': direction === 'LTR', | ||
'public/DraftStyleDefault/rtl': direction === 'RTL' | ||
}); | ||
return React.createElement( | ||
'div', | ||
{ 'data-offset-key': offsetKey, className: className }, | ||
this._renderChildren() | ||
DecoratorComponent, | ||
_extends({}, decoratorProps, { | ||
decoratedText: decoratedText, | ||
dir: dir, | ||
key: decoratorOffsetKey, | ||
entityKey: block.getEntityAt(leafSet.get('start')), | ||
offsetKey: decoratorOffsetKey }), | ||
leaves | ||
); | ||
} | ||
}]); | ||
}).toArray(); | ||
}; | ||
DraftEditorBlock.prototype.render = function render() { | ||
var _props = this.props; | ||
var direction = _props.direction; | ||
var offsetKey = _props.offsetKey; | ||
var className = cx({ | ||
'public/DraftStyleDefault/block': true, | ||
'public/DraftStyleDefault/ltr': direction === 'LTR', | ||
'public/DraftStyleDefault/rtl': direction === 'RTL' | ||
}); | ||
return React.createElement( | ||
'div', | ||
{ 'data-offset-key': offsetKey, className: className }, | ||
this._renderChildren() | ||
); | ||
}; | ||
return DraftEditorBlock; | ||
})(React.Component); | ||
}(React.Component); | ||
/** | ||
* Return whether a block overlaps with either edge of the `SelectionState`. | ||
*/ | ||
function isBlockOnSelectionEdge(selection, key) { | ||
@@ -210,0 +206,0 @@ return selection.getAnchorKey() === key || selection.getFocusKey() === key; |
@@ -21,48 +21,2 @@ /** | ||
* selection state and update the editor state accordingly. | ||
*/ | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
/** | ||
* Self-explanatory. | ||
*/ | ||
/** | ||
* Perform a forward deletion. | ||
*/ | ||
/** | ||
* Perform a forward deletion to the next word boundary after the selection. | ||
*/ | ||
/** | ||
* Perform a backward deletion. | ||
*/ | ||
/** | ||
* Perform a backward deletion to the previous word boundary before the | ||
* selection. | ||
*/ | ||
/** | ||
* Perform a backward deletion to the beginning of the current line. | ||
*/ | ||
/** | ||
* Toggle styles. Commands may be intepreted to modify inline text ranges | ||
* or block types. | ||
*/ | ||
/** | ||
* Split a block in two. | ||
*/ | ||
/** | ||
* Self-explanatory. | ||
*/ | ||
/** | ||
* Commands to support the "secondary" clipboard provided by certain | ||
* browsers and operating systems. | ||
*/ |
@@ -16,11 +16,11 @@ /** | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var _assign = require('object-assign'); | ||
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); | ||
var _extends = _assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } | ||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
@@ -45,4 +45,3 @@ var DraftEditorBlock = require('./DraftEditorBlock.react'); | ||
*/ | ||
var DraftEditorContents = (function (_React$Component) { | ||
var DraftEditorContents = function (_React$Component) { | ||
_inherits(DraftEditorContents, _React$Component); | ||
@@ -53,177 +52,175 @@ | ||
_get(Object.getPrototypeOf(DraftEditorContents.prototype), 'constructor', this).apply(this, arguments); | ||
return _possibleConstructorReturn(this, _React$Component.apply(this, arguments)); | ||
} | ||
/** | ||
* Provide default styling for list items. This way, lists will be styled with | ||
* proper counters and indentation even if the caller does not specify | ||
* their own styling at all. If more than five levels of nesting are needed, | ||
* the necessary CSS classes can be provided via `blockStyleFn` configuration. | ||
*/ | ||
DraftEditorContents.prototype.shouldComponentUpdate = function shouldComponentUpdate(nextProps) { | ||
var prevEditorState = this.props.editorState; | ||
var nextEditorState = nextProps.editorState; | ||
_createClass(DraftEditorContents, [{ | ||
key: 'shouldComponentUpdate', | ||
value: function shouldComponentUpdate(nextProps) { | ||
var prevEditorState = this.props.editorState; | ||
var nextEditorState = nextProps.editorState; | ||
var prevDirectionMap = prevEditorState.getDirectionMap(); | ||
var nextDirectionMap = nextEditorState.getDirectionMap(); | ||
var prevDirectionMap = prevEditorState.getDirectionMap(); | ||
var nextDirectionMap = nextEditorState.getDirectionMap(); | ||
// Text direction has changed for one or more blocks. We must re-render. | ||
if (prevDirectionMap !== nextDirectionMap) { | ||
return true; | ||
} | ||
// Text direction has changed for one or more blocks. We must re-render. | ||
if (prevDirectionMap !== nextDirectionMap) { | ||
return true; | ||
} | ||
var didHaveFocus = prevEditorState.getSelection().getHasFocus(); | ||
var nowHasFocus = nextEditorState.getSelection().getHasFocus(); | ||
var didHaveFocus = prevEditorState.getSelection().getHasFocus(); | ||
var nowHasFocus = nextEditorState.getSelection().getHasFocus(); | ||
if (didHaveFocus !== nowHasFocus) { | ||
return true; | ||
} | ||
if (didHaveFocus !== nowHasFocus) { | ||
return true; | ||
} | ||
var nextNativeContent = nextEditorState.getNativelyRenderedContent(); | ||
var nextNativeContent = nextEditorState.getNativelyRenderedContent(); | ||
var wasComposing = prevEditorState.isInCompositionMode(); | ||
var nowComposing = nextEditorState.isInCompositionMode(); | ||
var wasComposing = prevEditorState.isInCompositionMode(); | ||
var nowComposing = nextEditorState.isInCompositionMode(); | ||
// If the state is unchanged or we're currently rendering a natively | ||
// rendered state, there's nothing new to be done. | ||
if (prevEditorState === nextEditorState || nextNativeContent !== null && nextEditorState.getCurrentContent() === nextNativeContent || wasComposing && nowComposing) { | ||
return false; | ||
} | ||
// If the state is unchanged or we're currently rendering a natively | ||
// rendered state, there's nothing new to be done. | ||
if (prevEditorState === nextEditorState || nextNativeContent !== null && nextEditorState.getCurrentContent() === nextNativeContent || wasComposing && nowComposing) { | ||
return false; | ||
} | ||
var prevContent = prevEditorState.getCurrentContent(); | ||
var nextContent = nextEditorState.getCurrentContent(); | ||
var prevDecorator = prevEditorState.getDecorator(); | ||
var nextDecorator = nextEditorState.getDecorator(); | ||
return wasComposing !== nowComposing || prevContent !== nextContent || prevDecorator !== nextDecorator || nextEditorState.mustForceSelection(); | ||
}; | ||
var prevContent = prevEditorState.getCurrentContent(); | ||
var nextContent = nextEditorState.getCurrentContent(); | ||
var prevDecorator = prevEditorState.getDecorator(); | ||
var nextDecorator = nextEditorState.getDecorator(); | ||
return wasComposing !== nowComposing || prevContent !== nextContent || prevDecorator !== nextDecorator || nextEditorState.mustForceSelection(); | ||
} | ||
}, { | ||
key: 'render', | ||
value: function render() { | ||
var _props = this.props; | ||
var blockRenderMap = _props.blockRenderMap; | ||
var blockRendererFn = _props.blockRendererFn; | ||
var customStyleMap = _props.customStyleMap; | ||
var editorState = _props.editorState; | ||
DraftEditorContents.prototype.render = function render() { | ||
var _props = this.props; | ||
var blockRenderMap = _props.blockRenderMap; | ||
var blockRendererFn = _props.blockRendererFn; | ||
var customStyleMap = _props.customStyleMap; | ||
var customStyleFn = _props.customStyleFn; | ||
var editorState = _props.editorState; | ||
var content = editorState.getCurrentContent(); | ||
var selection = editorState.getSelection(); | ||
var forceSelection = editorState.mustForceSelection(); | ||
var decorator = editorState.getDecorator(); | ||
var directionMap = nullthrows(editorState.getDirectionMap()); | ||
var blocksAsArray = content.getBlocksAsArray(); | ||
var blocks = []; | ||
var currentWrapperElement = null; | ||
var currentWrapperTemplate = null; | ||
var currentDepth = null; | ||
var currentWrappedBlocks = undefined; | ||
var block = undefined, | ||
key = undefined, | ||
blockType = undefined, | ||
child = undefined, | ||
childProps = undefined, | ||
wrapperTemplate = undefined; | ||
var content = editorState.getCurrentContent(); | ||
var selection = editorState.getSelection(); | ||
var forceSelection = editorState.mustForceSelection(); | ||
var decorator = editorState.getDecorator(); | ||
var directionMap = nullthrows(editorState.getDirectionMap()); | ||
for (var ii = 0; ii < blocksAsArray.length; ii++) { | ||
block = blocksAsArray[ii]; | ||
key = block.getKey(); | ||
blockType = block.getType(); | ||
var blocksAsArray = content.getBlocksAsArray(); | ||
var blocks = []; | ||
var currentWrapperElement = null; | ||
var currentWrapperTemplate = null; | ||
var currentDepth = null; | ||
var currentWrappedBlocks = void 0; | ||
var block = void 0, | ||
key = void 0, | ||
blockType = void 0, | ||
child = void 0, | ||
childProps = void 0, | ||
wrapperTemplate = void 0; | ||
var customRenderer = blockRendererFn(block); | ||
var CustomComponent = undefined, | ||
customProps = undefined, | ||
customEditable = undefined; | ||
if (customRenderer) { | ||
CustomComponent = customRenderer.component; | ||
customProps = customRenderer.props; | ||
customEditable = customRenderer.editable; | ||
} | ||
for (var ii = 0; ii < blocksAsArray.length; ii++) { | ||
block = blocksAsArray[ii]; | ||
key = block.getKey(); | ||
blockType = block.getType(); | ||
var direction = directionMap.get(key); | ||
var offsetKey = DraftOffsetKey.encode(key, 0, 0); | ||
var componentProps = { | ||
block: block, | ||
blockProps: customProps, | ||
customStyleMap: customStyleMap, | ||
decorator: decorator, | ||
direction: direction, | ||
forceSelection: forceSelection, | ||
key: key, | ||
offsetKey: offsetKey, | ||
selection: selection, | ||
tree: editorState.getBlockTree(key) | ||
}; | ||
var customRenderer = blockRendererFn(block); | ||
var CustomComponent = void 0, | ||
customProps = void 0, | ||
customEditable = void 0; | ||
if (customRenderer) { | ||
CustomComponent = customRenderer.component; | ||
customProps = customRenderer.props; | ||
customEditable = customRenderer.editable; | ||
} | ||
// Block render map must have a configuration specified for this | ||
// block type. | ||
var configForType = nullthrows(blockRenderMap.get(blockType)); | ||
var direction = directionMap.get(key); | ||
var offsetKey = DraftOffsetKey.encode(key, 0, 0); | ||
var componentProps = { | ||
block: block, | ||
blockProps: customProps, | ||
customStyleMap: customStyleMap, | ||
customStyleFn: customStyleFn, | ||
decorator: decorator, | ||
direction: direction, | ||
forceSelection: forceSelection, | ||
key: key, | ||
offsetKey: offsetKey, | ||
selection: selection, | ||
tree: editorState.getBlockTree(key) | ||
}; | ||
wrapperTemplate = configForType.wrapper; | ||
var configForType = blockRenderMap.get(blockType); | ||
var useNewWrapper = wrapperTemplate !== currentWrapperTemplate; | ||
wrapperTemplate = configForType.wrapper; | ||
var _Element = blockRenderMap.get(blockType).element || blockRenderMap.get('unstyled').element; | ||
var useNewWrapper = wrapperTemplate !== currentWrapperTemplate; | ||
var depth = block.getDepth(); | ||
var className = this.props.blockStyleFn(block); | ||
var _Element = configForType.element || blockRenderMap.get('unstyled').element; | ||
// List items are special snowflakes, since we handle nesting and | ||
// counters manually. | ||
if (_Element === 'li') { | ||
var shouldResetCount = useNewWrapper || currentDepth === null || depth > currentDepth; | ||
className = joinClasses(className, getListItemClasses(blockType, depth, shouldResetCount, direction)); | ||
} | ||
var depth = block.getDepth(); | ||
var className = this.props.blockStyleFn(block); | ||
var Component = CustomComponent || DraftEditorBlock; | ||
childProps = { | ||
className: className, | ||
'data-block': true, | ||
'data-editor': this.props.editorKey, | ||
'data-offset-key': offsetKey, | ||
key: key | ||
}; | ||
if (customEditable !== undefined) { | ||
childProps = _extends({}, childProps, { | ||
contentEditable: customEditable, | ||
suppressContentEditableWarning: true | ||
}); | ||
} | ||
// List items are special snowflakes, since we handle nesting and | ||
// counters manually. | ||
if (_Element === 'li') { | ||
var shouldResetCount = useNewWrapper || currentDepth === null || depth > currentDepth; | ||
className = joinClasses(className, getListItemClasses(blockType, depth, shouldResetCount, direction)); | ||
} | ||
child = React.createElement(_Element, childProps, React.createElement(Component, componentProps)); | ||
var Component = CustomComponent || DraftEditorBlock; | ||
childProps = { | ||
className: className, | ||
'data-block': true, | ||
'data-editor': this.props.editorKey, | ||
'data-offset-key': offsetKey, | ||
key: key | ||
}; | ||
if (customEditable !== undefined) { | ||
childProps = _extends({}, childProps, { | ||
contentEditable: customEditable, | ||
suppressContentEditableWarning: true | ||
}); | ||
} | ||
if (wrapperTemplate) { | ||
if (useNewWrapper) { | ||
currentWrappedBlocks = []; | ||
currentWrapperElement = React.cloneElement(wrapperTemplate, { | ||
key: key + '-wrap', | ||
'data-offset-key': offsetKey | ||
}, currentWrappedBlocks); | ||
currentWrapperTemplate = wrapperTemplate; | ||
blocks.push(currentWrapperElement); | ||
} | ||
currentDepth = block.getDepth(); | ||
nullthrows(currentWrappedBlocks).push(child); | ||
} else { | ||
currentWrappedBlocks = null; | ||
currentWrapperElement = null; | ||
currentWrapperTemplate = null; | ||
currentDepth = null; | ||
blocks.push(child); | ||
child = React.createElement(_Element, childProps, React.createElement(Component, componentProps)); | ||
if (wrapperTemplate) { | ||
if (useNewWrapper) { | ||
currentWrappedBlocks = []; | ||
currentWrapperElement = React.cloneElement(wrapperTemplate, { | ||
key: key + '-wrap', | ||
'data-offset-key': offsetKey | ||
}, currentWrappedBlocks); | ||
currentWrapperTemplate = wrapperTemplate; | ||
blocks.push(currentWrapperElement); | ||
} | ||
currentDepth = block.getDepth(); | ||
nullthrows(currentWrappedBlocks).push(child); | ||
} else { | ||
currentWrappedBlocks = null; | ||
currentWrapperElement = null; | ||
currentWrapperTemplate = null; | ||
currentDepth = null; | ||
blocks.push(child); | ||
} | ||
return React.createElement( | ||
'div', | ||
{ 'data-contents': 'true' }, | ||
blocks | ||
); | ||
} | ||
}]); | ||
return React.createElement( | ||
'div', | ||
{ 'data-contents': 'true' }, | ||
blocks | ||
); | ||
}; | ||
return DraftEditorContents; | ||
})(React.Component); | ||
}(React.Component); | ||
/** | ||
* Provide default styling for list items. This way, lists will be styled with | ||
* proper counters and indentation even if the caller does not specify | ||
* their own styling at all. If more than five levels of nesting are needed, | ||
* the necessary CSS classes can be provided via `blockStyleFn` configuration. | ||
*/ | ||
function getListItemClasses(type, depth, shouldResetCount, direction) { | ||
@@ -230,0 +227,0 @@ return cx({ |
@@ -14,5 +14,2 @@ /** | ||
/** | ||
* Get a SelectionState for the supplied mouse event. | ||
*/ | ||
'use strict'; | ||
@@ -29,2 +26,5 @@ | ||
/** | ||
* Get a SelectionState for the supplied mouse event. | ||
*/ | ||
function getSelectionForEvent(event, editorState) { | ||
@@ -31,0 +31,0 @@ var node = null; |
@@ -16,9 +16,9 @@ /** | ||
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); | ||
var _assign = require('object-assign'); | ||
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } | ||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
@@ -41,4 +41,3 @@ var DraftEditorTextNode = require('./DraftEditorTextNode.react'); | ||
*/ | ||
var DraftEditorLeaf = (function (_React$Component) { | ||
var DraftEditorLeaf = function (_React$Component) { | ||
_inherits(DraftEditorLeaf, _React$Component); | ||
@@ -49,131 +48,115 @@ | ||
_get(Object.getPrototypeOf(DraftEditorLeaf.prototype), 'constructor', this).apply(this, arguments); | ||
return _possibleConstructorReturn(this, _React$Component.apply(this, arguments)); | ||
} | ||
_createClass(DraftEditorLeaf, [{ | ||
key: '_setSelection', | ||
/** | ||
* By making individual leaf instances aware of their context within | ||
* the text of the editor, we can set our selection range more | ||
* easily than we could in the non-React world. | ||
* | ||
* Note that this depends on our maintaining tight control over the | ||
* DOM structure of the TextEditor component. If leaves had multiple | ||
* text nodes, this would be harder. | ||
*/ | ||
DraftEditorLeaf.prototype._setSelection = function _setSelection() { | ||
var selection = this.props.selection; | ||
/** | ||
* By making individual leaf instances aware of their context within | ||
* the text of the editor, we can set our selection range more | ||
* easily than we could in the non-React world. | ||
* | ||
* Note that this depends on our maintaining tight control over the | ||
* DOM structure of the TextEditor component. If leaves had multiple | ||
* text nodes, this would be harder. | ||
*/ | ||
value: function _setSelection() { | ||
var selection = this.props.selection; | ||
// If selection state is irrelevant to the parent block, no-op. | ||
// If selection state is irrelevant to the parent block, no-op. | ||
if (selection == null || !selection.getHasFocus()) { | ||
return; | ||
} | ||
if (selection == null || !selection.getHasFocus()) { | ||
return; | ||
} | ||
var _props = this.props; | ||
var blockKey = _props.blockKey; | ||
var start = _props.start; | ||
var text = _props.text; | ||
var _props = this.props; | ||
var blockKey = _props.blockKey; | ||
var start = _props.start; | ||
var text = _props.text; | ||
var end = start + text.length; | ||
if (!selection.hasEdgeWithin(blockKey, start, end)) { | ||
return; | ||
} | ||
var end = start + text.length; | ||
if (!selection.hasEdgeWithin(blockKey, start, end)) { | ||
return; | ||
} | ||
// Determine the appropriate target node for selection. If the child | ||
// is not a text node, it is a <br /> spacer. In this case, use the | ||
// <span> itself as the selection target. | ||
var node = ReactDOM.findDOMNode(this); | ||
var child = node.firstChild; | ||
var targetNode = undefined; | ||
// Determine the appropriate target node for selection. If the child | ||
// is not a text node, it is a <br /> spacer. In this case, use the | ||
// <span> itself as the selection target. | ||
var node = ReactDOM.findDOMNode(this); | ||
var child = node.firstChild; | ||
var targetNode = void 0; | ||
if (child.nodeType === Node.TEXT_NODE) { | ||
targetNode = child; | ||
} else if (child.tagName === 'BR') { | ||
targetNode = node; | ||
} else { | ||
targetNode = child.firstChild; | ||
} | ||
setDraftEditorSelection(selection, targetNode, blockKey, start, end); | ||
if (child.nodeType === Node.TEXT_NODE) { | ||
targetNode = child; | ||
} else if (child.tagName === 'BR') { | ||
targetNode = node; | ||
} else { | ||
targetNode = child.firstChild; | ||
} | ||
}, { | ||
key: 'shouldComponentUpdate', | ||
value: function shouldComponentUpdate(nextProps) { | ||
return ReactDOM.findDOMNode(this.refs.leaf).textContent !== nextProps.text || nextProps.styleSet !== this.props.styleSet || nextProps.forceSelection; | ||
} | ||
}, { | ||
key: 'componentDidUpdate', | ||
value: function componentDidUpdate() { | ||
this._setSelection(); | ||
} | ||
}, { | ||
key: 'componentDidMount', | ||
value: function componentDidMount() { | ||
this._setSelection(); | ||
} | ||
}, { | ||
key: 'render', | ||
value: function render() { | ||
var text = this.props.text; | ||
// If the leaf is at the end of its block and ends in a soft newline, append | ||
// an extra line feed character. Browsers collapse trailing newline | ||
// characters, which leaves the cursor in the wrong place after a | ||
// shift+enter. The extra character repairs this. | ||
if (text.endsWith('\n') && this.props.isLast) { | ||
text += '\n'; | ||
} | ||
setDraftEditorSelection(selection, targetNode, blockKey, start, end); | ||
}; | ||
var _props2 = this.props; | ||
var customStyleMap = _props2.customStyleMap; | ||
var offsetKey = _props2.offsetKey; | ||
var styleSet = _props2.styleSet; | ||
DraftEditorLeaf.prototype.shouldComponentUpdate = function shouldComponentUpdate(nextProps) { | ||
return ReactDOM.findDOMNode(this.refs.leaf).textContent !== nextProps.text || nextProps.styleSet !== this.props.styleSet || nextProps.forceSelection; | ||
}; | ||
var styleObj = styleSet.reduce(function (map, styleName) { | ||
var mergedStyles = {}; | ||
var style = customStyleMap[styleName]; | ||
DraftEditorLeaf.prototype.componentDidUpdate = function componentDidUpdate() { | ||
this._setSelection(); | ||
}; | ||
if (style !== undefined && map.textDecoration !== style.textDecoration) { | ||
mergedStyles.textDecoration = [map.textDecoration, style.textDecoration].join(' '); | ||
} | ||
DraftEditorLeaf.prototype.componentDidMount = function componentDidMount() { | ||
this._setSelection(); | ||
}; | ||
return Object.assign(map, style, mergedStyles); | ||
}, {}); | ||
DraftEditorLeaf.prototype.render = function render() { | ||
var text = this.props.text; | ||
return React.createElement( | ||
'span', | ||
{ | ||
'data-offset-key': offsetKey, | ||
ref: 'leaf', | ||
style: styleObj }, | ||
React.createElement( | ||
DraftEditorTextNode, | ||
null, | ||
text | ||
) | ||
); | ||
// If the leaf is at the end of its block and ends in a soft newline, append | ||
// an extra line feed character. Browsers collapse trailing newline | ||
// characters, which leaves the cursor in the wrong place after a | ||
// shift+enter. The extra character repairs this. | ||
if (text.endsWith('\n') && this.props.isLast) { | ||
text += '\n'; | ||
} | ||
}]); | ||
return DraftEditorLeaf; | ||
})(React.Component); | ||
var _props2 = this.props; | ||
var customStyleMap = _props2.customStyleMap; | ||
var customStyleFn = _props2.customStyleFn; | ||
var offsetKey = _props2.offsetKey; | ||
var styleSet = _props2.styleSet; | ||
module.exports = DraftEditorLeaf; | ||
var styleObj = styleSet.reduce(function (map, styleName) { | ||
var mergedStyles = {}; | ||
var style = customStyleMap[styleName]; | ||
// A function passed through from the the top level to define a cx | ||
// style map for the provided style value. | ||
if (style !== undefined && map.textDecoration !== style.textDecoration) { | ||
// .trim() is necessary for IE9/10/11 and Edge | ||
mergedStyles.textDecoration = [map.textDecoration, style.textDecoration].join(' ').trim(); | ||
} | ||
// Mapping of style names to CSS declarations. | ||
return _assign(map, style, mergedStyles); | ||
}, {}); | ||
// Whether to force the DOM selection after render. | ||
if (customStyleFn) { | ||
var newStyles = customStyleFn(styleSet); | ||
styleObj = _assign(styleObj, newStyles); | ||
} | ||
// Whether this leaf is the last in its block. Used for a DOM hack. | ||
return React.createElement( | ||
'span', | ||
{ | ||
'data-offset-key': offsetKey, | ||
ref: 'leaf', | ||
style: styleObj }, | ||
React.createElement( | ||
DraftEditorTextNode, | ||
null, | ||
text | ||
) | ||
); | ||
}; | ||
// The current `SelectionState`, used to | ||
return DraftEditorLeaf; | ||
}(React.Component); | ||
// The offset of this string within its block. | ||
// The set of style(s) names to apply to the node. | ||
// The full text to be rendered within this node. | ||
module.exports = DraftEditorLeaf; |
@@ -13,29 +13,2 @@ /** | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
/** | ||
* `edit` is the most common mode for text entry. This includes most typing, | ||
* deletion, cut/copy/paste, and other behaviors. | ||
*/ | ||
/** | ||
* `composite` mode handles IME text entry. | ||
*/ | ||
/** | ||
* `drag` mode handles editor behavior while a drag event is occurring. | ||
*/ | ||
/** | ||
* `cut` mode allows us to effectively ignore all edit behaviors while the` | ||
* browser performs a native `cut` operation on the DOM. | ||
*/ | ||
/** | ||
* `render` mode is the normal "null" mode, during which no edit behavior is | ||
* expected or observed. | ||
*/ | ||
'use strict'; |
@@ -16,10 +16,8 @@ /** | ||
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; | ||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
var React = require('react'); | ||
@@ -35,4 +33,3 @@ | ||
*/ | ||
var DraftEditorPlaceholder = (function (_React$Component) { | ||
var DraftEditorPlaceholder = function (_React$Component) { | ||
_inherits(DraftEditorPlaceholder, _React$Component); | ||
@@ -43,37 +40,33 @@ | ||
_get(Object.getPrototypeOf(DraftEditorPlaceholder.prototype), 'constructor', this).apply(this, arguments); | ||
return _possibleConstructorReturn(this, _React$Component.apply(this, arguments)); | ||
} | ||
_createClass(DraftEditorPlaceholder, [{ | ||
key: 'shouldComponentUpdate', | ||
value: function shouldComponentUpdate(nextProps) { | ||
return this.props.text !== nextProps.text || this.props.editorState.getSelection().getHasFocus() !== nextProps.editorState.getSelection().getHasFocus(); | ||
} | ||
}, { | ||
key: 'render', | ||
value: function render() { | ||
var hasFocus = this.props.editorState.getSelection().getHasFocus(); | ||
DraftEditorPlaceholder.prototype.shouldComponentUpdate = function shouldComponentUpdate(nextProps) { | ||
return this.props.text !== nextProps.text || this.props.editorState.getSelection().getHasFocus() !== nextProps.editorState.getSelection().getHasFocus(); | ||
}; | ||
var className = cx({ | ||
'public/DraftEditorPlaceholder/root': true, | ||
'public/DraftEditorPlaceholder/hasFocus': hasFocus | ||
}); | ||
DraftEditorPlaceholder.prototype.render = function render() { | ||
var hasFocus = this.props.editorState.getSelection().getHasFocus(); | ||
return React.createElement( | ||
var className = cx({ | ||
'public/DraftEditorPlaceholder/root': true, | ||
'public/DraftEditorPlaceholder/hasFocus': hasFocus | ||
}); | ||
return React.createElement( | ||
'div', | ||
{ className: className }, | ||
React.createElement( | ||
'div', | ||
{ className: className }, | ||
React.createElement( | ||
'div', | ||
{ | ||
className: cx('public/DraftEditorPlaceholder/inner'), | ||
id: this.props.accessibilityID }, | ||
this.props.text | ||
) | ||
); | ||
} | ||
}]); | ||
{ | ||
className: cx('public/DraftEditorPlaceholder/inner'), | ||
id: this.props.accessibilityID }, | ||
this.props.text | ||
) | ||
); | ||
}; | ||
return DraftEditorPlaceholder; | ||
})(React.Component); | ||
}(React.Component); | ||
module.exports = DraftEditorPlaceholder; |
@@ -13,73 +13,2 @@ /** | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
/** | ||
* The two most critical props are `editorState` and `onChange`. | ||
* | ||
* The `editorState` prop defines the entire state of the editor, while the | ||
* `onChange` prop is the method in which all state changes are propagated | ||
* upward to higher-level components. | ||
* | ||
* These props are analagous to `value` and `onChange` in controlled React | ||
* text inputs. | ||
*/ | ||
// Specify whether text alignment should be forced in a direction | ||
// regardless of input characters. | ||
// For a given `ContentBlock` object, return an object that specifies | ||
// a custom block component and/or props. If no object is returned, | ||
// the default `TextEditorBlock` is used. | ||
// Function that returns a cx map corresponding to block-level styles. | ||
// A function that accepts a synthetic key event and returns | ||
// the matching DraftEditorCommand constant, or null if no command should | ||
// be invoked. | ||
// Set whether the `DraftEditor` component should be editable. Useful for | ||
// temporarily disabling edit behavior or allowing `DraftEditor` rendering | ||
// to be used for consumption purposes. | ||
// Note: spellcheck is always disabled for IE. If enabled in Safari, OSX | ||
// autocorrect is enabled as well. | ||
// Set whether to remove all style information from pasted content. If your | ||
// use case should not have any block or inline styles, it is recommended | ||
// that you set this to `true`. | ||
/** | ||
* Cancelable event handlers, handled from the top level down. A handler | ||
* that returns true will be the last handler to execute for that event. | ||
*/ | ||
// Useful for managing special behavior for pressing the `Return` key. E.g. | ||
// removing the style from an empty list item. | ||
// Map a key command string provided by your key binding function to a | ||
// specified behavior. | ||
// Handle intended text insertion before the insertion occurs. This may be | ||
// useful in cases where the user has entered characters that you would like | ||
// to trigger some special behavior. E.g. immediately converting `:)` to an | ||
// emoji Unicode character, or replacing ASCII quote characters with smart | ||
// quotes. | ||
// Handle dropped files | ||
// Handle other drops to prevent default text movement/insertion behaviour | ||
/** | ||
* Non-cancelable event triggers. | ||
*/ | ||
// Provide a map of inline style names corresponding to CSS style objects | ||
// that will be rendered for matching ranges. | ||
// Provide a map of block rendering configurations. Each block type maps to | ||
// an element tag and am optional react element wrapper. This configuration | ||
// is used for both rendering and paste processing. | ||
'use strict'; |
@@ -16,10 +16,8 @@ /** | ||
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; | ||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
var React = require('react'); | ||
@@ -70,4 +68,3 @@ var ReactDOM = require('react-dom'); | ||
*/ | ||
var DraftEditorTextNode = (function (_React$Component) { | ||
var DraftEditorTextNode = function (_React$Component) { | ||
_inherits(DraftEditorTextNode, _React$Component); | ||
@@ -78,40 +75,37 @@ | ||
_get(Object.getPrototypeOf(DraftEditorTextNode.prototype), 'constructor', this).call(this, props); | ||
this._forceFlag = false; | ||
var _this = _possibleConstructorReturn(this, _React$Component.call(this, props)); | ||
_this._forceFlag = false; | ||
return _this; | ||
} | ||
_createClass(DraftEditorTextNode, [{ | ||
key: 'shouldComponentUpdate', | ||
value: function shouldComponentUpdate(nextProps) { | ||
var node = ReactDOM.findDOMNode(this); | ||
var shouldBeNewline = nextProps.children === ''; | ||
if (shouldBeNewline) { | ||
return !isNewline(node); | ||
} | ||
return node.textContent !== nextProps.children; | ||
DraftEditorTextNode.prototype.shouldComponentUpdate = function shouldComponentUpdate(nextProps) { | ||
var node = ReactDOM.findDOMNode(this); | ||
var shouldBeNewline = nextProps.children === ''; | ||
if (shouldBeNewline) { | ||
return !isNewline(node); | ||
} | ||
}, { | ||
key: 'componentWillUpdate', | ||
value: function componentWillUpdate() { | ||
// By flipping this flag, we also keep flipping keys which forces | ||
// React to remount this node every time it rerenders. | ||
this._forceFlag = !this._forceFlag; | ||
return node.textContent !== nextProps.children; | ||
}; | ||
DraftEditorTextNode.prototype.componentWillUpdate = function componentWillUpdate() { | ||
// By flipping this flag, we also keep flipping keys which forces | ||
// React to remount this node every time it rerenders. | ||
this._forceFlag = !this._forceFlag; | ||
}; | ||
DraftEditorTextNode.prototype.render = function render() { | ||
if (this.props.children === '') { | ||
return this._forceFlag ? NEWLINE_A : NEWLINE_B; | ||
} | ||
}, { | ||
key: 'render', | ||
value: function render() { | ||
if (this.props.children === '') { | ||
return this._forceFlag ? NEWLINE_A : NEWLINE_B; | ||
} | ||
return React.createElement( | ||
'span', | ||
{ key: this._forceFlag ? 'A' : 'B', 'data-text': 'true' }, | ||
this.props.children | ||
); | ||
} | ||
}]); | ||
return React.createElement( | ||
'span', | ||
{ key: this._forceFlag ? 'A' : 'B', 'data-text': 'true' }, | ||
this.props.children | ||
); | ||
}; | ||
return DraftEditorTextNode; | ||
})(React.Component); | ||
}(React.Component); | ||
module.exports = DraftEditorTextNode; |
@@ -0,1 +1,7 @@ | ||
'use strict'; | ||
var _assign = require('object-assign'); | ||
var _extends = _assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
/** | ||
@@ -14,6 +20,2 @@ * Copyright (c) 2013-present, Facebook, Inc. | ||
'use strict'; | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var DraftEntityInstance = require('./DraftEntityInstance'); | ||
@@ -26,2 +28,3 @@ var Immutable = require('immutable'); | ||
var instances = Map(); | ||
@@ -70,3 +73,3 @@ var instanceKey = 0; | ||
var instance = instances.get(key); | ||
!!!instance ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Unknown DraftEntity key.') : invariant(false) : undefined; | ||
!!!instance ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Unknown DraftEntity key.') : invariant(false) : void 0; | ||
return instance; | ||
@@ -73,0 +76,0 @@ }, |
@@ -15,10 +15,8 @@ /** | ||
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; | ||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
var Immutable = require('immutable'); | ||
@@ -28,2 +26,3 @@ | ||
var DraftEntityInstanceRecord = Record({ | ||
@@ -47,4 +46,4 @@ type: 'TOKEN', | ||
var DraftEntityInstance = (function (_DraftEntityInstanceRecord) { | ||
_inherits(DraftEntityInstance, _DraftEntityInstanceRecord); | ||
var DraftEntityInstance = function (_DraftEntityInstanceR) { | ||
_inherits(DraftEntityInstance, _DraftEntityInstanceR); | ||
@@ -54,25 +53,20 @@ function DraftEntityInstance() { | ||
_get(Object.getPrototypeOf(DraftEntityInstance.prototype), 'constructor', this).apply(this, arguments); | ||
return _possibleConstructorReturn(this, _DraftEntityInstanceR.apply(this, arguments)); | ||
} | ||
_createClass(DraftEntityInstance, [{ | ||
key: 'getType', | ||
value: function getType() { | ||
return this.get('type'); | ||
} | ||
}, { | ||
key: 'getMutability', | ||
value: function getMutability() { | ||
return this.get('mutability'); | ||
} | ||
}, { | ||
key: 'getData', | ||
value: function getData() { | ||
return this.get('data'); | ||
} | ||
}]); | ||
DraftEntityInstance.prototype.getType = function getType() { | ||
return this.get('type'); | ||
}; | ||
DraftEntityInstance.prototype.getMutability = function getMutability() { | ||
return this.get('mutability'); | ||
}; | ||
DraftEntityInstance.prototype.getData = function getData() { | ||
return this.get('data'); | ||
}; | ||
return DraftEntityInstance; | ||
})(DraftEntityInstanceRecord); | ||
}(DraftEntityInstanceRecord); | ||
module.exports = DraftEntityInstance; |
@@ -15,5 +15,2 @@ /** | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
var ComposedEntityMutability = require('./ComposedEntityMutability'); | ||
@@ -20,0 +17,0 @@ |
@@ -14,2 +14,4 @@ /** | ||
'use strict'; | ||
/** | ||
@@ -38,4 +40,2 @@ * Identify the range to delete from a segmented entity. | ||
*/ | ||
'use strict'; | ||
var DraftEntitySegments = { | ||
@@ -42,0 +42,0 @@ getRemovalRange: function getRemovalRange(selectionStart, selectionEnd, text, entityStart, direction) { |
@@ -13,6 +13,2 @@ /** | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
'use strict'; |
@@ -13,6 +13,2 @@ /** | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
'use strict'; |
@@ -14,12 +14,2 @@ /** | ||
/** | ||
* `DraftModifier` provides a set of convenience methods that apply | ||
* modifications to a `ContentState` object based on a target `SelectionState`. | ||
* | ||
* Any change to a `ContentState` should be decomposable into a series of | ||
* transaction functions that apply the required changes and return output | ||
* `ContentState` objects. | ||
* | ||
* These functions encapsulate some of the most common transaction sequences. | ||
*/ | ||
'use strict'; | ||
@@ -29,7 +19,4 @@ | ||
var ContentStateInlineStyle = require('./ContentStateInlineStyle'); | ||
var Immutable = require('immutable'); | ||
var _require = require('immutable'); | ||
var OrderedSet = _require.OrderedSet; | ||
var applyEntityToContentState = require('./applyEntityToContentState'); | ||
@@ -41,7 +28,20 @@ var getCharacterRemovalRange = require('./getCharacterRemovalRange'); | ||
var invariant = require('fbjs/lib/invariant'); | ||
var modifyBlockForContentState = require('./modifyBlockForContentState'); | ||
var removeEntitiesAtEdges = require('./removeEntitiesAtEdges'); | ||
var removeRangeFromContentState = require('./removeRangeFromContentState'); | ||
var setBlockTypeForContentState = require('./setBlockTypeForContentState'); | ||
var splitBlockInContentState = require('./splitBlockInContentState'); | ||
var OrderedSet = Immutable.OrderedSet; | ||
/** | ||
* `DraftModifier` provides a set of convenience methods that apply | ||
* modifications to a `ContentState` object based on a target `SelectionState`. | ||
* | ||
* Any change to a `ContentState` should be decomposable into a series of | ||
* transaction functions that apply the required changes and return output | ||
* `ContentState` objects. | ||
* | ||
* These functions encapsulate some of the most common transaction sequences. | ||
*/ | ||
var DraftModifier = { | ||
@@ -61,3 +61,3 @@ replaceText: function replaceText(contentState, rangeToReplace, text, inlineStyle, entityKey) { | ||
insertText: function insertText(contentState, targetRange, text, inlineStyle, entityKey) { | ||
!targetRange.isCollapsed() ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Target range must be collapsed for `insertText`.') : invariant(false) : undefined; | ||
!targetRange.isCollapsed() ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Target range must be collapsed for `insertText`.') : invariant(false) : void 0; | ||
return DraftModifier.replaceText(contentState, targetRange, text, inlineStyle, entityKey); | ||
@@ -118,5 +118,19 @@ }, | ||
setBlockType: function setBlockType(contentState, selectionState, blockType) { | ||
return setBlockTypeForContentState(contentState, selectionState, blockType); | ||
return modifyBlockForContentState(contentState, selectionState, function (block) { | ||
return block.merge({ type: blockType, depth: 0 }); | ||
}); | ||
}, | ||
setBlockData: function setBlockData(contentState, selectionState, blockData) { | ||
return modifyBlockForContentState(contentState, selectionState, function (block) { | ||
return block.merge({ data: blockData }); | ||
}); | ||
}, | ||
mergeBlockData: function mergeBlockData(contentState, selectionState, blockData) { | ||
return modifyBlockForContentState(contentState, selectionState, function (block) { | ||
return block.merge({ data: block.getData().merge(blockData) }); | ||
}); | ||
}, | ||
applyEntity: function applyEntity(contentState, selectionState, entityKey) { | ||
@@ -123,0 +137,0 @@ var withoutEntities = removeEntitiesAtEdges(contentState, selectionState); |
@@ -15,4 +15,2 @@ /** | ||
var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })(); | ||
var KEY_DELIMITER = '-'; | ||
@@ -28,8 +26,6 @@ | ||
var _offsetKey$split2 = _slicedToArray(_offsetKey$split, 3); | ||
var blockKey = _offsetKey$split[0]; | ||
var decoratorKey = _offsetKey$split[1]; | ||
var leafKey = _offsetKey$split[2]; | ||
var blockKey = _offsetKey$split2[0]; | ||
var decoratorKey = _offsetKey$split2[1]; | ||
var leafKey = _offsetKey$split2[2]; | ||
return { | ||
@@ -36,0 +32,0 @@ blockKey: blockKey, |
@@ -13,6 +13,2 @@ /** | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
'use strict'; |
@@ -28,2 +28,3 @@ /** | ||
var DraftPasteProcessor = { | ||
@@ -33,3 +34,2 @@ processHTML: function processHTML(html, blockRenderMap) { | ||
}, | ||
processText: function processText(textBlocks, character) { | ||
@@ -36,0 +36,0 @@ return textBlocks.map(function (textLine) { |
@@ -13,6 +13,2 @@ /** | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
'use strict'; |
@@ -20,5 +20,2 @@ /** | ||
* around to indicate whether a deletion is forward or backward. | ||
*/ | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
*/ |
@@ -13,6 +13,2 @@ /** | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
'use strict'; |
@@ -13,6 +13,2 @@ /** | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
'use strict'; |
@@ -13,9 +13,2 @@ /** | ||
// When nothing is focused, Firefox regards two characters, `'` and `/`, as | ||
// commands that should open and focus the "quickfind" search bar. This should | ||
// *never* happen while a contenteditable is focused, but as of v28, it | ||
// sometimes does, even when the keypress event target is the contenteditable. | ||
// This breaks the input. Special case these characters to ensure that when | ||
// they are typed, we prevent default on the event to make sure not to | ||
// trigger quickfind. | ||
'use strict'; | ||
@@ -32,2 +25,9 @@ | ||
// When nothing is focused, Firefox regards two characters, `'` and `/`, as | ||
// commands that should open and focus the "quickfind" search bar. This should | ||
// *never* happen while a contenteditable is focused, but as of v28, it | ||
// sometimes does, even when the keypress event target is the contenteditable. | ||
// This breaks the input. Special case these characters to ensure that when | ||
// they are typed, we prevent default on the event to make sure not to | ||
// trigger quickfind. | ||
var FF_QUICKFIND_CHAR = '\''; | ||
@@ -34,0 +34,0 @@ var FF_QUICKFIND_LINK_CHAR = '\/'; |
@@ -52,2 +52,3 @@ /** | ||
var fragment = getFragmentFromSelection(editorState); | ||
@@ -54,0 +55,0 @@ this.setClipboard(fragment); |
@@ -18,2 +18,3 @@ /** | ||
*/ | ||
function editOnDragOver(e) { | ||
@@ -20,0 +21,0 @@ this._internalDrag = false; |
@@ -18,2 +18,3 @@ /** | ||
*/ | ||
function editOnDragStart() { | ||
@@ -20,0 +21,0 @@ this._internalDrag = true; |
@@ -55,13 +55,14 @@ /** | ||
var _DraftOffsetKey$decode = DraftOffsetKey.decode(offsetKey); | ||
var _DraftOffsetKey$decod = DraftOffsetKey.decode(offsetKey); | ||
var blockKey = _DraftOffsetKey$decode.blockKey; | ||
var decoratorKey = _DraftOffsetKey$decode.decoratorKey; | ||
var leafKey = _DraftOffsetKey$decode.leafKey; | ||
var blockKey = _DraftOffsetKey$decod.blockKey; | ||
var decoratorKey = _DraftOffsetKey$decod.decoratorKey; | ||
var leafKey = _DraftOffsetKey$decod.leafKey; | ||
var _editorState$getBlockTree$getIn = editorState.getBlockTree(blockKey).getIn([decoratorKey, 'leaves', leafKey]); | ||
var _editorState$getBlock = editorState.getBlockTree(blockKey).getIn([decoratorKey, 'leaves', leafKey]); | ||
var start = _editorState$getBlockTree$getIn.start; | ||
var end = _editorState$getBlockTree$getIn.end; | ||
var start = _editorState$getBlock.start; | ||
var end = _editorState$getBlock.end; | ||
var content = editorState.getCurrentContent(); | ||
@@ -68,0 +69,0 @@ var block = content.getBlockForKey(blockKey); |
@@ -13,5 +13,2 @@ /** | ||
/** | ||
* Paste content. | ||
*/ | ||
'use strict'; | ||
@@ -30,2 +27,5 @@ | ||
/** | ||
* Paste content. | ||
*/ | ||
function editOnPaste(e) { | ||
@@ -107,2 +107,8 @@ var _this = this; | ||
} | ||
} else if (internalClipboard && data.types.includes('com.apple.webarchive') && !data.types.includes('text/html') && areTextBlocksAndClipboardEqual(textBlocks, internalClipboard)) { | ||
// Safari does not properly store text/html in some cases. | ||
// Use the internalClipboard if present and equal to what is on | ||
// the clipboard. See https://bugs.webkit.org/show_bug.cgi?id=19893. | ||
this.update(insertFragment(this.props.editorState, internalClipboard)); | ||
return; | ||
} | ||
@@ -119,2 +125,3 @@ | ||
} | ||
// Otherwise, create a new fragment from our pasted text. Also | ||
@@ -145,2 +152,8 @@ // empty the internal clipboard, since it's no longer valid. | ||
function areTextBlocksAndClipboardEqual(textBlocks, blockMap) { | ||
return textBlocks.length === blockMap.size && blockMap.valueSeq().every(function (block, ii) { | ||
return block.getText() === textBlocks[ii]; | ||
}); | ||
} | ||
module.exports = editOnPaste; |
@@ -23,2 +23,3 @@ /** | ||
var bidiService; | ||
@@ -25,0 +26,0 @@ |
@@ -15,6 +15,2 @@ /** | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
'use strict'; |
@@ -15,7 +15,7 @@ /** | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var _assign = require('object-assign'); | ||
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); | ||
var _extends = _assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
@@ -32,2 +32,3 @@ var BlockTree = require('./BlockTree'); | ||
var defaultRecord = { | ||
@@ -51,394 +52,373 @@ allowUndo: true, | ||
var EditorState = (function () { | ||
_createClass(EditorState, [{ | ||
key: 'toJS', | ||
value: function toJS() { | ||
return this.getImmutable().toJS(); | ||
} | ||
}, { | ||
key: 'getAllowUndo', | ||
value: function getAllowUndo() { | ||
return this.getImmutable().get('allowUndo'); | ||
} | ||
}, { | ||
key: 'getCurrentContent', | ||
value: function getCurrentContent() { | ||
return this.getImmutable().get('currentContent'); | ||
} | ||
}, { | ||
key: 'getUndoStack', | ||
value: function getUndoStack() { | ||
return this.getImmutable().get('undoStack'); | ||
} | ||
}, { | ||
key: 'getRedoStack', | ||
value: function getRedoStack() { | ||
return this.getImmutable().get('redoStack'); | ||
} | ||
}, { | ||
key: 'getSelection', | ||
value: function getSelection() { | ||
return this.getImmutable().get('selection'); | ||
} | ||
}, { | ||
key: 'getDecorator', | ||
value: function getDecorator() { | ||
return this.getImmutable().get('decorator'); | ||
} | ||
}, { | ||
key: 'isInCompositionMode', | ||
value: function isInCompositionMode() { | ||
return this.getImmutable().get('inCompositionMode'); | ||
} | ||
}, { | ||
key: 'mustForceSelection', | ||
value: function mustForceSelection() { | ||
return this.getImmutable().get('forceSelection'); | ||
} | ||
}, { | ||
key: 'getNativelyRenderedContent', | ||
value: function getNativelyRenderedContent() { | ||
return this.getImmutable().get('nativelyRenderedContent'); | ||
} | ||
}, { | ||
key: 'getLastChangeType', | ||
value: function getLastChangeType() { | ||
return this.getImmutable().get('lastChangeType'); | ||
} | ||
var EditorState = function () { | ||
EditorState.createEmpty = function createEmpty(decorator) { | ||
return EditorState.createWithContent(ContentState.createFromText(''), decorator); | ||
}; | ||
/** | ||
* While editing, the user may apply inline style commands with a collapsed | ||
* cursor, intending to type text that adopts the specified style. In this | ||
* case, we track the specified style as an "override" that takes precedence | ||
* over the inline style of the text adjacent to the cursor. | ||
* | ||
* If null, there is no override in place. | ||
*/ | ||
}, { | ||
key: 'getInlineStyleOverride', | ||
value: function getInlineStyleOverride() { | ||
return this.getImmutable().get('inlineStyleOverride'); | ||
} | ||
}, { | ||
key: 'getCurrentInlineStyle', | ||
EditorState.createWithContent = function createWithContent(contentState, decorator) { | ||
var firstKey = contentState.getBlockMap().first().getKey(); | ||
return EditorState.create({ | ||
currentContent: contentState, | ||
undoStack: Stack(), | ||
redoStack: Stack(), | ||
decorator: decorator || null, | ||
selection: SelectionState.createEmpty(firstKey) | ||
}); | ||
}; | ||
/** | ||
* Get the appropriate inline style for the editor state. If an | ||
* override is in place, use it. Otherwise, the current style is | ||
* based on the location of the selection state. | ||
*/ | ||
value: function getCurrentInlineStyle() { | ||
var override = this.getInlineStyleOverride(); | ||
if (override != null) { | ||
return override; | ||
EditorState.create = function create(config) { | ||
var currentContent = config.currentContent; | ||
var decorator = config.decorator; | ||
var recordConfig = _extends({}, config, { | ||
treeMap: generateNewTreeMap(currentContent, decorator), | ||
directionMap: EditorBidiService.getDirectionMap(currentContent) | ||
}); | ||
return new EditorState(new EditorStateRecord(recordConfig)); | ||
}; | ||
EditorState.set = function set(editorState, put) { | ||
var map = editorState.getImmutable().withMutations(function (state) { | ||
var existingDecorator = state.get('decorator'); | ||
var decorator = existingDecorator; | ||
if (put.decorator === null) { | ||
decorator = null; | ||
} else if (put.decorator) { | ||
decorator = put.decorator; | ||
} | ||
var content = this.getCurrentContent(); | ||
var selection = this.getSelection(); | ||
var newContent = put.currentContent || editorState.getCurrentContent(); | ||
if (selection.isCollapsed()) { | ||
return getInlineStyleForCollapsedSelection(content, selection); | ||
if (decorator !== existingDecorator) { | ||
var treeMap = state.get('treeMap'); | ||
var newTreeMap; | ||
if (decorator && existingDecorator) { | ||
newTreeMap = regenerateTreeForNewDecorator(newContent.getBlockMap(), treeMap, decorator, existingDecorator); | ||
} else { | ||
newTreeMap = generateNewTreeMap(newContent, decorator); | ||
} | ||
state.merge({ | ||
decorator: decorator, | ||
treeMap: newTreeMap, | ||
nativelyRenderedContent: null | ||
}); | ||
return; | ||
} | ||
return getInlineStyleForNonCollapsedSelection(content, selection); | ||
} | ||
}, { | ||
key: 'getBlockTree', | ||
value: function getBlockTree(blockKey) { | ||
return this.getImmutable().getIn(['treeMap', blockKey]); | ||
} | ||
}, { | ||
key: 'isSelectionAtStartOfContent', | ||
value: function isSelectionAtStartOfContent() { | ||
var firstKey = this.getCurrentContent().getBlockMap().first().getKey(); | ||
return this.getSelection().hasEdgeWithin(firstKey, 0, 0); | ||
} | ||
}, { | ||
key: 'isSelectionAtEndOfContent', | ||
value: function isSelectionAtEndOfContent() { | ||
var content = this.getCurrentContent(); | ||
var blockMap = content.getBlockMap(); | ||
var last = blockMap.last(); | ||
var end = last.getLength(); | ||
return this.getSelection().hasEdgeWithin(last.getKey(), end, end); | ||
} | ||
}, { | ||
key: 'getDirectionMap', | ||
value: function getDirectionMap() { | ||
return this.getImmutable().get('directionMap'); | ||
} | ||
var existingContent = editorState.getCurrentContent(); | ||
if (newContent !== existingContent) { | ||
state.set('treeMap', regenerateTreeForNewBlocks(editorState, newContent.getBlockMap(), decorator)); | ||
} | ||
/** | ||
* Incorporate native DOM selection changes into the EditorState. This | ||
* method can be used when we simply want to accept whatever the DOM | ||
* has given us to represent selection, and we do not need to re-render | ||
* the editor. | ||
* | ||
* To forcibly move the DOM selection, see `EditorState.forceSelection`. | ||
*/ | ||
}], [{ | ||
key: 'createEmpty', | ||
value: function createEmpty(decorator) { | ||
return EditorState.createWithContent(ContentState.createFromText(''), decorator); | ||
} | ||
}, { | ||
key: 'createWithContent', | ||
value: function createWithContent(contentState, decorator) { | ||
var firstKey = contentState.getBlockMap().first().getKey(); | ||
return EditorState.create({ | ||
currentContent: contentState, | ||
undoStack: Stack(), | ||
redoStack: Stack(), | ||
decorator: decorator || null, | ||
selection: SelectionState.createEmpty(firstKey) | ||
}); | ||
} | ||
}, { | ||
key: 'create', | ||
value: function create(config) { | ||
var currentContent = config.currentContent; | ||
var decorator = config.decorator; | ||
state.merge(put); | ||
}); | ||
var recordConfig = _extends({}, config, { | ||
treeMap: generateNewTreeMap(currentContent, decorator), | ||
directionMap: EditorBidiService.getDirectionMap(currentContent) | ||
}); | ||
return new EditorState(new EditorStateRecord(recordConfig)); | ||
} | ||
}, { | ||
key: 'set', | ||
value: function set(editorState, put) { | ||
var map = editorState.getImmutable().withMutations(function (state) { | ||
var existingDecorator = state.get('decorator'); | ||
var decorator = existingDecorator; | ||
if (put.decorator === null) { | ||
decorator = null; | ||
} else if (put.decorator) { | ||
decorator = put.decorator; | ||
} | ||
return new EditorState(map); | ||
}; | ||
var newContent = put.currentContent || editorState.getCurrentContent(); | ||
EditorState.prototype.toJS = function toJS() { | ||
return this.getImmutable().toJS(); | ||
}; | ||
if (decorator !== existingDecorator) { | ||
var treeMap = state.get('treeMap'); | ||
var newTreeMap; | ||
if (decorator && existingDecorator) { | ||
newTreeMap = regenerateTreeForNewDecorator(newContent.getBlockMap(), treeMap, decorator, existingDecorator); | ||
} else { | ||
newTreeMap = generateNewTreeMap(newContent, decorator); | ||
} | ||
EditorState.prototype.getAllowUndo = function getAllowUndo() { | ||
return this.getImmutable().get('allowUndo'); | ||
}; | ||
state.merge({ | ||
decorator: decorator, | ||
treeMap: newTreeMap, | ||
nativelyRenderedContent: null | ||
}); | ||
return; | ||
} | ||
EditorState.prototype.getCurrentContent = function getCurrentContent() { | ||
return this.getImmutable().get('currentContent'); | ||
}; | ||
var existingContent = editorState.getCurrentContent(); | ||
if (newContent !== existingContent) { | ||
state.set('treeMap', regenerateTreeForNewBlocks(editorState, newContent.getBlockMap(), decorator)); | ||
} | ||
EditorState.prototype.getUndoStack = function getUndoStack() { | ||
return this.getImmutable().get('undoStack'); | ||
}; | ||
state.merge(put); | ||
}); | ||
EditorState.prototype.getRedoStack = function getRedoStack() { | ||
return this.getImmutable().get('redoStack'); | ||
}; | ||
return new EditorState(map); | ||
} | ||
}, { | ||
key: 'setInlineStyleOverride', | ||
value: function setInlineStyleOverride(editorState, inlineStyleOverride) { | ||
return EditorState.set(editorState, { inlineStyleOverride: inlineStyleOverride }); | ||
} | ||
}, { | ||
key: 'acceptSelection', | ||
value: function acceptSelection(editorState, selection) { | ||
return updateSelection(editorState, selection, false); | ||
} | ||
EditorState.prototype.getSelection = function getSelection() { | ||
return this.getImmutable().get('selection'); | ||
}; | ||
/** | ||
* At times, we need to force the DOM selection to be where we | ||
* need it to be. This can occur when the anchor or focus nodes | ||
* are non-text nodes, for instance. In this case, we want to trigger | ||
* a re-render of the editor, which in turn forces selection into | ||
* the correct place in the DOM. The `forceSelection` method | ||
* accomplishes this. | ||
* | ||
* This method should be used in cases where you need to explicitly | ||
* move the DOM selection from one place to another without a change | ||
* in ContentState. | ||
*/ | ||
}, { | ||
key: 'forceSelection', | ||
value: function forceSelection(editorState, selection) { | ||
if (!selection.getHasFocus()) { | ||
selection = selection.set('hasFocus', true); | ||
} | ||
return updateSelection(editorState, selection, true); | ||
EditorState.prototype.getDecorator = function getDecorator() { | ||
return this.getImmutable().get('decorator'); | ||
}; | ||
EditorState.prototype.isInCompositionMode = function isInCompositionMode() { | ||
return this.getImmutable().get('inCompositionMode'); | ||
}; | ||
EditorState.prototype.mustForceSelection = function mustForceSelection() { | ||
return this.getImmutable().get('forceSelection'); | ||
}; | ||
EditorState.prototype.getNativelyRenderedContent = function getNativelyRenderedContent() { | ||
return this.getImmutable().get('nativelyRenderedContent'); | ||
}; | ||
EditorState.prototype.getLastChangeType = function getLastChangeType() { | ||
return this.getImmutable().get('lastChangeType'); | ||
}; | ||
/** | ||
* While editing, the user may apply inline style commands with a collapsed | ||
* cursor, intending to type text that adopts the specified style. In this | ||
* case, we track the specified style as an "override" that takes precedence | ||
* over the inline style of the text adjacent to the cursor. | ||
* | ||
* If null, there is no override in place. | ||
*/ | ||
EditorState.prototype.getInlineStyleOverride = function getInlineStyleOverride() { | ||
return this.getImmutable().get('inlineStyleOverride'); | ||
}; | ||
EditorState.setInlineStyleOverride = function setInlineStyleOverride(editorState, inlineStyleOverride) { | ||
return EditorState.set(editorState, { inlineStyleOverride: inlineStyleOverride }); | ||
}; | ||
/** | ||
* Get the appropriate inline style for the editor state. If an | ||
* override is in place, use it. Otherwise, the current style is | ||
* based on the location of the selection state. | ||
*/ | ||
EditorState.prototype.getCurrentInlineStyle = function getCurrentInlineStyle() { | ||
var override = this.getInlineStyleOverride(); | ||
if (override != null) { | ||
return override; | ||
} | ||
/** | ||
* Move selection to the end of the editor without forcing focus. | ||
*/ | ||
}, { | ||
key: 'moveSelectionToEnd', | ||
value: function moveSelectionToEnd(editorState) { | ||
var content = editorState.getCurrentContent(); | ||
var lastBlock = content.getLastBlock(); | ||
var lastKey = lastBlock.getKey(); | ||
var length = lastBlock.getLength(); | ||
var content = this.getCurrentContent(); | ||
var selection = this.getSelection(); | ||
return EditorState.acceptSelection(editorState, new SelectionState({ | ||
anchorKey: lastKey, | ||
anchorOffset: length, | ||
focusKey: lastKey, | ||
focusOffset: length, | ||
isBackward: false | ||
})); | ||
if (selection.isCollapsed()) { | ||
return getInlineStyleForCollapsedSelection(content, selection); | ||
} | ||
/** | ||
* Force focus to the end of the editor. This is useful in scenarios | ||
* where we want to programmatically focus the input and it makes sense | ||
* to allow the user to continue working seamlessly. | ||
*/ | ||
}, { | ||
key: 'moveFocusToEnd', | ||
value: function moveFocusToEnd(editorState) { | ||
var afterSelectionMove = EditorState.moveSelectionToEnd(editorState); | ||
return EditorState.forceSelection(afterSelectionMove, afterSelectionMove.getSelection()); | ||
return getInlineStyleForNonCollapsedSelection(content, selection); | ||
}; | ||
EditorState.prototype.getBlockTree = function getBlockTree(blockKey) { | ||
return this.getImmutable().getIn(['treeMap', blockKey]); | ||
}; | ||
EditorState.prototype.isSelectionAtStartOfContent = function isSelectionAtStartOfContent() { | ||
var firstKey = this.getCurrentContent().getBlockMap().first().getKey(); | ||
return this.getSelection().hasEdgeWithin(firstKey, 0, 0); | ||
}; | ||
EditorState.prototype.isSelectionAtEndOfContent = function isSelectionAtEndOfContent() { | ||
var content = this.getCurrentContent(); | ||
var blockMap = content.getBlockMap(); | ||
var last = blockMap.last(); | ||
var end = last.getLength(); | ||
return this.getSelection().hasEdgeWithin(last.getKey(), end, end); | ||
}; | ||
EditorState.prototype.getDirectionMap = function getDirectionMap() { | ||
return this.getImmutable().get('directionMap'); | ||
}; | ||
/** | ||
* Incorporate native DOM selection changes into the EditorState. This | ||
* method can be used when we simply want to accept whatever the DOM | ||
* has given us to represent selection, and we do not need to re-render | ||
* the editor. | ||
* | ||
* To forcibly move the DOM selection, see `EditorState.forceSelection`. | ||
*/ | ||
EditorState.acceptSelection = function acceptSelection(editorState, selection) { | ||
return updateSelection(editorState, selection, false); | ||
}; | ||
/** | ||
* At times, we need to force the DOM selection to be where we | ||
* need it to be. This can occur when the anchor or focus nodes | ||
* are non-text nodes, for instance. In this case, we want to trigger | ||
* a re-render of the editor, which in turn forces selection into | ||
* the correct place in the DOM. The `forceSelection` method | ||
* accomplishes this. | ||
* | ||
* This method should be used in cases where you need to explicitly | ||
* move the DOM selection from one place to another without a change | ||
* in ContentState. | ||
*/ | ||
EditorState.forceSelection = function forceSelection(editorState, selection) { | ||
if (!selection.getHasFocus()) { | ||
selection = selection.set('hasFocus', true); | ||
} | ||
return updateSelection(editorState, selection, true); | ||
}; | ||
/** | ||
* Push the current ContentState onto the undo stack if it should be | ||
* considered a boundary state, and set the provided ContentState as the | ||
* new current content. | ||
*/ | ||
}, { | ||
key: 'push', | ||
value: function push(editorState, contentState, changeType) { | ||
if (editorState.getCurrentContent() === contentState) { | ||
return editorState; | ||
} | ||
/** | ||
* Move selection to the end of the editor without forcing focus. | ||
*/ | ||
var forceSelection = changeType !== 'insert-characters'; | ||
var directionMap = EditorBidiService.getDirectionMap(contentState, editorState.getDirectionMap()); | ||
if (!editorState.getAllowUndo()) { | ||
return EditorState.set(editorState, { | ||
currentContent: contentState, | ||
directionMap: directionMap, | ||
lastChangeType: changeType, | ||
selection: contentState.getSelectionAfter(), | ||
forceSelection: forceSelection, | ||
inlineStyleOverride: null | ||
}); | ||
} | ||
EditorState.moveSelectionToEnd = function moveSelectionToEnd(editorState) { | ||
var content = editorState.getCurrentContent(); | ||
var lastBlock = content.getLastBlock(); | ||
var lastKey = lastBlock.getKey(); | ||
var length = lastBlock.getLength(); | ||
var selection = editorState.getSelection(); | ||
var currentContent = editorState.getCurrentContent(); | ||
var undoStack = editorState.getUndoStack(); | ||
var newContent = contentState; | ||
return EditorState.acceptSelection(editorState, new SelectionState({ | ||
anchorKey: lastKey, | ||
anchorOffset: length, | ||
focusKey: lastKey, | ||
focusOffset: length, | ||
isBackward: false | ||
})); | ||
}; | ||
if (selection !== currentContent.getSelectionAfter() || mustBecomeBoundary(editorState, changeType)) { | ||
undoStack = undoStack.push(currentContent); | ||
newContent = newContent.set('selectionBefore', selection); | ||
} else if (changeType === 'insert-characters' || changeType === 'backspace-character' || changeType === 'delete-character') { | ||
// Preserve the previous selection. | ||
newContent = newContent.set('selectionBefore', currentContent.getSelectionBefore()); | ||
} | ||
/** | ||
* Force focus to the end of the editor. This is useful in scenarios | ||
* where we want to programmatically focus the input and it makes sense | ||
* to allow the user to continue working seamlessly. | ||
*/ | ||
var inlineStyleOverride = editorState.getInlineStyleOverride(); | ||
// Don't discard inline style overrides on block type or depth changes. | ||
if (changeType !== 'adjust-depth' && changeType !== 'change-block-type') { | ||
inlineStyleOverride = null; | ||
} | ||
EditorState.moveFocusToEnd = function moveFocusToEnd(editorState) { | ||
var afterSelectionMove = EditorState.moveSelectionToEnd(editorState); | ||
return EditorState.forceSelection(afterSelectionMove, afterSelectionMove.getSelection()); | ||
}; | ||
var editorStateChanges = { | ||
currentContent: newContent, | ||
/** | ||
* Push the current ContentState onto the undo stack if it should be | ||
* considered a boundary state, and set the provided ContentState as the | ||
* new current content. | ||
*/ | ||
EditorState.push = function push(editorState, contentState, changeType) { | ||
if (editorState.getCurrentContent() === contentState) { | ||
return editorState; | ||
} | ||
var forceSelection = changeType !== 'insert-characters'; | ||
var directionMap = EditorBidiService.getDirectionMap(contentState, editorState.getDirectionMap()); | ||
if (!editorState.getAllowUndo()) { | ||
return EditorState.set(editorState, { | ||
currentContent: contentState, | ||
directionMap: directionMap, | ||
undoStack: undoStack, | ||
redoStack: Stack(), | ||
lastChangeType: changeType, | ||
selection: contentState.getSelectionAfter(), | ||
forceSelection: forceSelection, | ||
inlineStyleOverride: inlineStyleOverride | ||
}; | ||
inlineStyleOverride: null | ||
}); | ||
} | ||
return EditorState.set(editorState, editorStateChanges); | ||
var selection = editorState.getSelection(); | ||
var currentContent = editorState.getCurrentContent(); | ||
var undoStack = editorState.getUndoStack(); | ||
var newContent = contentState; | ||
if (selection !== currentContent.getSelectionAfter() || mustBecomeBoundary(editorState, changeType)) { | ||
undoStack = undoStack.push(currentContent); | ||
newContent = newContent.set('selectionBefore', selection); | ||
} else if (changeType === 'insert-characters' || changeType === 'backspace-character' || changeType === 'delete-character') { | ||
// Preserve the previous selection. | ||
newContent = newContent.set('selectionBefore', currentContent.getSelectionBefore()); | ||
} | ||
/** | ||
* Make the top ContentState in the undo stack the new current content and | ||
* push the current content onto the redo stack. | ||
*/ | ||
}, { | ||
key: 'undo', | ||
value: function undo(editorState) { | ||
if (!editorState.getAllowUndo()) { | ||
return editorState; | ||
} | ||
var inlineStyleOverride = editorState.getInlineStyleOverride(); | ||
var undoStack = editorState.getUndoStack(); | ||
var newCurrentContent = undoStack.peek(); | ||
if (!newCurrentContent) { | ||
return editorState; | ||
} | ||
// Don't discard inline style overrides on block type or depth changes. | ||
if (changeType !== 'adjust-depth' && changeType !== 'change-block-type') { | ||
inlineStyleOverride = null; | ||
} | ||
var currentContent = editorState.getCurrentContent(); | ||
var directionMap = EditorBidiService.getDirectionMap(newCurrentContent, editorState.getDirectionMap()); | ||
var editorStateChanges = { | ||
currentContent: newContent, | ||
directionMap: directionMap, | ||
undoStack: undoStack, | ||
redoStack: Stack(), | ||
lastChangeType: changeType, | ||
selection: contentState.getSelectionAfter(), | ||
forceSelection: forceSelection, | ||
inlineStyleOverride: inlineStyleOverride | ||
}; | ||
return EditorState.set(editorState, { | ||
currentContent: newCurrentContent, | ||
directionMap: directionMap, | ||
undoStack: undoStack.shift(), | ||
redoStack: editorState.getRedoStack().push(currentContent), | ||
forceSelection: true, | ||
inlineStyleOverride: null, | ||
lastChangeType: 'undo', | ||
nativelyRenderedContent: null, | ||
selection: currentContent.getSelectionBefore() | ||
}); | ||
return EditorState.set(editorState, editorStateChanges); | ||
}; | ||
/** | ||
* Make the top ContentState in the undo stack the new current content and | ||
* push the current content onto the redo stack. | ||
*/ | ||
EditorState.undo = function undo(editorState) { | ||
if (!editorState.getAllowUndo()) { | ||
return editorState; | ||
} | ||
/** | ||
* Make the top ContentState in the redo stack the new current content and | ||
* push the current content onto the undo stack. | ||
*/ | ||
}, { | ||
key: 'redo', | ||
value: function redo(editorState) { | ||
if (!editorState.getAllowUndo()) { | ||
return editorState; | ||
} | ||
var undoStack = editorState.getUndoStack(); | ||
var newCurrentContent = undoStack.peek(); | ||
if (!newCurrentContent) { | ||
return editorState; | ||
} | ||
var redoStack = editorState.getRedoStack(); | ||
var newCurrentContent = redoStack.peek(); | ||
if (!newCurrentContent) { | ||
return editorState; | ||
} | ||
var currentContent = editorState.getCurrentContent(); | ||
var directionMap = EditorBidiService.getDirectionMap(newCurrentContent, editorState.getDirectionMap()); | ||
var currentContent = editorState.getCurrentContent(); | ||
var directionMap = EditorBidiService.getDirectionMap(newCurrentContent, editorState.getDirectionMap()); | ||
return EditorState.set(editorState, { | ||
currentContent: newCurrentContent, | ||
directionMap: directionMap, | ||
undoStack: undoStack.shift(), | ||
redoStack: editorState.getRedoStack().push(currentContent), | ||
forceSelection: true, | ||
inlineStyleOverride: null, | ||
lastChangeType: 'undo', | ||
nativelyRenderedContent: null, | ||
selection: currentContent.getSelectionBefore() | ||
}); | ||
}; | ||
return EditorState.set(editorState, { | ||
currentContent: newCurrentContent, | ||
directionMap: directionMap, | ||
undoStack: editorState.getUndoStack().push(currentContent), | ||
redoStack: redoStack.shift(), | ||
forceSelection: true, | ||
inlineStyleOverride: null, | ||
lastChangeType: 'redo', | ||
nativelyRenderedContent: null, | ||
selection: newCurrentContent.getSelectionAfter() | ||
}); | ||
/** | ||
* Make the top ContentState in the redo stack the new current content and | ||
* push the current content onto the undo stack. | ||
*/ | ||
EditorState.redo = function redo(editorState) { | ||
if (!editorState.getAllowUndo()) { | ||
return editorState; | ||
} | ||
/** | ||
* Not for public consumption. | ||
*/ | ||
}]); | ||
var redoStack = editorState.getRedoStack(); | ||
var newCurrentContent = redoStack.peek(); | ||
if (!newCurrentContent) { | ||
return editorState; | ||
} | ||
var currentContent = editorState.getCurrentContent(); | ||
var directionMap = EditorBidiService.getDirectionMap(newCurrentContent, editorState.getDirectionMap()); | ||
return EditorState.set(editorState, { | ||
currentContent: newCurrentContent, | ||
directionMap: directionMap, | ||
undoStack: editorState.getUndoStack().push(currentContent), | ||
redoStack: redoStack.shift(), | ||
forceSelection: true, | ||
inlineStyleOverride: null, | ||
lastChangeType: 'redo', | ||
nativelyRenderedContent: null, | ||
selection: newCurrentContent.getSelectionAfter() | ||
}); | ||
}; | ||
/** | ||
* Not for public consumption. | ||
*/ | ||
function EditorState(immutable) { | ||
@@ -451,20 +431,19 @@ _classCallCheck(this, EditorState); | ||
/** | ||
* Set the supplied SelectionState as the new current selection, and set | ||
* the `force` flag to trigger manual selection placement by the view. | ||
*/ | ||
/** | ||
* Not for public consumption. | ||
*/ | ||
_createClass(EditorState, [{ | ||
key: 'getImmutable', | ||
value: function getImmutable() { | ||
return this._immutable; | ||
} | ||
}]); | ||
EditorState.prototype.getImmutable = function getImmutable() { | ||
return this._immutable; | ||
}; | ||
return EditorState; | ||
})(); | ||
}(); | ||
/** | ||
* Set the supplied SelectionState as the new current selection, and set | ||
* the `force` flag to trigger manual selection placement by the view. | ||
*/ | ||
function updateSelection(editorState, selection, forceSelection) { | ||
@@ -471,0 +450,0 @@ return EditorState.set(editorState, { |
@@ -13,6 +13,2 @@ /** | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
'use strict'; |
@@ -24,2 +24,3 @@ /** | ||
*/ | ||
function encodeEntityRanges(block, storageMap) { | ||
@@ -26,0 +27,0 @@ var encoded = []; |
@@ -20,5 +20,2 @@ /** | ||
* a `ComposedText` object, not for use with `DraftEntity.get()`. | ||
*/ | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
*/ |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
/** | ||
@@ -14,4 +16,2 @@ * Copyright (c) 2013-present, Facebook, Inc. | ||
'use strict'; | ||
var UnicodeUtils = require('fbjs/lib/UnicodeUtils'); | ||
@@ -105,3 +105,3 @@ | ||
function expandRangeToStartOfLine(range) { | ||
!range.collapsed ? process.env.NODE_ENV !== 'production' ? invariant(false, 'expandRangeToStartOfLine: Provided range is not collapsed.') : invariant(false) : undefined; | ||
!range.collapsed ? process.env.NODE_ENV !== 'production' ? invariant(false, 'expandRangeToStartOfLine: Provided range is not collapsed.') : invariant(false) : void 0; | ||
range = range.cloneRange(); | ||
@@ -133,3 +133,3 @@ | ||
bestOffset = range.startOffset; | ||
!bestContainer.parentNode ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Found unexpected detached subtree when traversing.') : invariant(false) : undefined; | ||
!bestContainer.parentNode ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Found unexpected detached subtree when traversing.') : invariant(false) : void 0; | ||
range.setStartBefore(bestContainer); | ||
@@ -136,0 +136,0 @@ if (bestContainer.nodeType === 1 && getComputedStyle(bestContainer).display !== 'inline') { |
@@ -22,8 +22,9 @@ /** | ||
function findAncestorOffsetKey(node) { | ||
while (node && node !== document.documentElement) { | ||
var key = getSelectionOffsetKeyForNode(node); | ||
var searchNode = node; | ||
while (searchNode && searchNode !== document.documentElement) { | ||
var key = getSelectionOffsetKeyForNode(searchNode); | ||
if (key != null) { | ||
return key; | ||
} | ||
node = node.parentNode; | ||
searchNode = searchNode.parentNode; | ||
} | ||
@@ -30,0 +31,0 @@ return null; |
@@ -13,2 +13,4 @@ /** | ||
'use strict'; | ||
/** | ||
@@ -21,4 +23,2 @@ * Search through an array to find contiguous stretches of elements that | ||
*/ | ||
'use strict'; | ||
function findRangesImmutable(haystack, areEqualFn, filterFn, foundFn) { | ||
@@ -32,3 +32,5 @@ if (!haystack.size) { | ||
haystack.reduce(function (value, nextValue, nextIndex) { | ||
/* $FlowFixMe(>=0.28.0): `value` could be undefined! */ | ||
if (!areEqualFn(value, nextValue)) { | ||
/* $FlowFixMe(>=0.28.0): `value` could be undefined! */ | ||
if (filterFn(value)) { | ||
@@ -35,0 +37,0 @@ foundFn(cursor, nextIndex); |
@@ -20,3 +20,3 @@ /** | ||
function generateRandomKey() { | ||
var key = undefined; | ||
var key = void 0; | ||
while (key === undefined || seenKeys.hasOwnProperty(key) || !isNaN(+key)) { | ||
@@ -23,0 +23,0 @@ key = Math.floor(Math.random() * MULTIPLIER).toString(32); |
@@ -14,2 +14,10 @@ /** | ||
'use strict'; | ||
var DraftEntity = require('./DraftEntity'); | ||
var DraftEntitySegments = require('./DraftEntitySegments'); | ||
var getRangesForDraftEntity = require('./getRangesForDraftEntity'); | ||
var invariant = require('fbjs/lib/invariant'); | ||
/** | ||
@@ -24,10 +32,2 @@ * Given a SelectionState and a removal direction, determine the entire range | ||
*/ | ||
'use strict'; | ||
var DraftEntity = require('./DraftEntity'); | ||
var DraftEntitySegments = require('./DraftEntitySegments'); | ||
var getRangesForDraftEntity = require('./getRangesForDraftEntity'); | ||
var invariant = require('fbjs/lib/invariant'); | ||
function getCharacterRemovalRange(block, selectionState, direction) { | ||
@@ -55,3 +55,3 @@ var start = selectionState.getStartOffset(); | ||
!(entityRanges.length == 1) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'There should only be one entity range within this removal range.') : invariant(false) : undefined; | ||
!(entityRanges.length == 1) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'There should only be one entity range within this removal range.') : invariant(false) : void 0; | ||
@@ -58,0 +58,0 @@ var entityRange = entityRanges[0]; |
@@ -31,2 +31,3 @@ /** | ||
function shouldRemoveWord(e) { | ||
@@ -40,5 +41,6 @@ return isOSX && e.altKey || isCtrlKeyCommand(e); | ||
function getZCommand(e) { | ||
if (hasCommandModifier(e)) { | ||
return e.shiftKey ? 'redo' : 'undo'; | ||
if (!hasCommandModifier(e)) { | ||
return null; | ||
} | ||
return e.shiftKey ? 'redo' : 'undo'; | ||
} | ||
@@ -45,0 +47,0 @@ |
@@ -14,2 +14,6 @@ /** | ||
'use strict'; | ||
var getDraftEditorSelectionWithNodes = require('./getDraftEditorSelectionWithNodes'); | ||
/** | ||
@@ -19,6 +23,2 @@ * Convert the current selection range to an anchor/focus pair of offset keys | ||
*/ | ||
'use strict'; | ||
var getDraftEditorSelectionWithNodes = require('./getDraftEditorSelectionWithNodes'); | ||
function getDraftEditorSelection(editorState, root) { | ||
@@ -25,0 +25,0 @@ var selection = global.getSelection(); |
@@ -83,3 +83,3 @@ /** | ||
if (anchorNode === focusNode && anchorOffset === focusOffset) { | ||
needsRecovery = anchorNode.firstChild.nodeName !== 'BR'; | ||
needsRecovery = !!anchorNode.firstChild && anchorNode.firstChild.nodeName !== 'BR'; | ||
} | ||
@@ -114,6 +114,7 @@ } | ||
function getPointForNonTextNode(editorRoot, node, childOffset) { | ||
function getPointForNonTextNode(editorRoot, startNode, childOffset) { | ||
var node = startNode; | ||
var offsetKey = findAncestorOffsetKey(node); | ||
!(offsetKey != null || editorRoot && (editorRoot === node || editorRoot.firstChild === node)) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Unknown node in selection range.') : invariant(false) : undefined; | ||
!(offsetKey != null || editorRoot && (editorRoot === node || editorRoot.firstChild === node)) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Unknown node in selection range.') : invariant(false) : void 0; | ||
@@ -124,3 +125,3 @@ // If the editorRoot is the selection, step downward into the content | ||
node = node.firstChild; | ||
!(node instanceof Element && node.getAttribute('data-contents') === 'true') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Invalid DraftEditorContents structure.') : invariant(false) : undefined; | ||
!(node instanceof Element && node.getAttribute('data-contents') === 'true') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Invalid DraftEditorContents structure.') : invariant(false) : void 0; | ||
if (childOffset > 0) { | ||
@@ -127,0 +128,0 @@ childOffset = node.childNodes.length; |
@@ -14,2 +14,6 @@ /** | ||
'use strict'; | ||
var DraftEntity = require('./DraftEntity'); | ||
/** | ||
@@ -20,6 +24,2 @@ * Return the entity key that should be used when inserting text for the | ||
*/ | ||
'use strict'; | ||
var DraftEntity = require('./DraftEntity'); | ||
function getEntityKeyForSelection(contentState, targetSelection) { | ||
@@ -26,0 +26,0 @@ var entityKey; |
@@ -19,7 +19,10 @@ /** | ||
var selectionState = editorState.getSelection(); | ||
if (!selectionState.isCollapsed()) { | ||
return getContentStateFragment(editorState.getCurrentContent(), selectionState); | ||
if (selectionState.isCollapsed()) { | ||
return null; | ||
} | ||
return getContentStateFragment(editorState.getCurrentContent(), selectionState); | ||
} | ||
module.exports = getFragmentFromSelection; |
@@ -16,5 +16,2 @@ /** | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
var getRangeClientRects = require('./getRangeClientRects'); | ||
@@ -37,7 +34,7 @@ | ||
if (rects.length) { | ||
var _rects$0 = rects[0]; | ||
top = _rects$0.top; | ||
right = _rects$0.right; | ||
bottom = _rects$0.bottom; | ||
left = _rects$0.left; | ||
var _rects$ = rects[0]; | ||
top = _rects$.top; | ||
right = _rects$.right; | ||
bottom = _rects$.bottom; | ||
left = _rects$.left; | ||
@@ -44,0 +41,0 @@ for (var ii = 1; ii < rects.length; ii++) { |
@@ -27,2 +27,3 @@ /** | ||
// https://code.google.com/p/chromium/issues/detail?id=324437 | ||
/* eslint-disable consistent-return */ | ||
function getRangeClientRectsChrome(range) { | ||
@@ -52,4 +53,5 @@ var tempRange = range.cloneRange(); | ||
!false ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Found an unexpected detached subtree when getting range client rects.') : invariant(false) : undefined; | ||
!false ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Found an unexpected detached subtree when getting range client rects.') : invariant(false) : void 0; | ||
} | ||
/* eslint-enable consistent-return */ | ||
@@ -56,0 +58,0 @@ /** |
@@ -14,2 +14,6 @@ /** | ||
'use strict'; | ||
var invariant = require('fbjs/lib/invariant'); | ||
/** | ||
@@ -23,6 +27,2 @@ * Obtain the start and end positions of the range that has the | ||
*/ | ||
'use strict'; | ||
var invariant = require('fbjs/lib/invariant'); | ||
function getRangesForDraftEntity(block, key) { | ||
@@ -36,3 +36,3 @@ var ranges = []; | ||
!!!ranges.length ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Entity key not found in this range.') : invariant(false) : undefined; | ||
!!!ranges.length ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Entity key not found in this range.') : invariant(false) : void 0; | ||
@@ -39,0 +39,0 @@ return ranges; |
@@ -17,8 +17,22 @@ /** | ||
/** | ||
* Get offset key from a node. | ||
* Get offset key from a node or it's child nodes. Return the first offset key | ||
* found on the DOM tree of given node. | ||
*/ | ||
function getSelectionOffsetKeyForNode(node) { | ||
return node instanceof Element ? node.getAttribute('data-offset-key') : null; | ||
if (node instanceof Element) { | ||
var offsetKey = node.getAttribute('data-offset-key'); | ||
if (offsetKey) { | ||
return offsetKey; | ||
} | ||
for (var ii = 0; ii < node.childNodes.length; ii++) { | ||
var childOffsetKey = getSelectionOffsetKeyForNode(node.childNodes[ii]); | ||
if (childOffsetKey) { | ||
return childOffsetKey; | ||
} | ||
} | ||
} | ||
return null; | ||
} | ||
module.exports = getSelectionOffsetKeyForNode; |
@@ -14,2 +14,4 @@ /** | ||
'use strict'; | ||
/** | ||
@@ -19,4 +21,2 @@ * Find the string of text between the previous entity and the specified | ||
*/ | ||
'use strict'; | ||
function getTextAfterNearestEntity(block, offset) { | ||
@@ -23,0 +23,0 @@ var start = offset; |
@@ -14,2 +14,6 @@ /** | ||
'use strict'; | ||
var getRangeBoundingClientRect = require('./getRangeBoundingClientRect'); | ||
/** | ||
@@ -20,6 +24,2 @@ * Return the bounding ClientRect for the visible DOM selection, if any. | ||
*/ | ||
'use strict'; | ||
var getRangeBoundingClientRect = require('./getRangeBoundingClientRect'); | ||
function getVisibleSelectionRect(global) { | ||
@@ -41,2 +41,3 @@ var selection = global.getSelection(); | ||
// bounding rect. Discard this state. | ||
if (top === 0 && right === 0 && bottom === 0 && left === 0) { | ||
@@ -43,0 +44,0 @@ return null; |
@@ -17,5 +17,2 @@ /** | ||
* A plain object representation of an inline style range. | ||
*/ | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
*/ |
@@ -23,3 +23,3 @@ /** | ||
function insertFragmentIntoContentState(contentState, selectionState, fragment) { | ||
!selectionState.isCollapsed() ? process.env.NODE_ENV !== 'production' ? invariant(false, '`insertFragment` should only be called with a collapsed selection state.') : invariant(false) : undefined; | ||
!selectionState.isCollapsed() ? process.env.NODE_ENV !== 'production' ? invariant(false, '`insertFragment` should only be called with a collapsed selection state.') : invariant(false) : void 0; | ||
@@ -43,3 +43,4 @@ var targetKey = selectionState.getStartKey(); | ||
text: text.slice(0, targetOffset) + pastedBlock.getText() + text.slice(targetOffset), | ||
characterList: insertIntoList(chars, pastedBlock.getCharacterList(), targetOffset) | ||
characterList: insertIntoList(chars, pastedBlock.getCharacterList(), targetOffset), | ||
data: pastedBlock.getData() | ||
}); | ||
@@ -84,3 +85,5 @@ | ||
text: headText + appendToHead.getText(), | ||
characterList: headCharacters.concat(appendToHead.getCharacterList()) | ||
characterList: headCharacters.concat(appendToHead.getCharacterList()), | ||
type: headText ? block.getType() : appendToHead.getType(), | ||
data: appendToHead.getData() | ||
}); | ||
@@ -104,3 +107,4 @@ | ||
text: prependToTail.getText() + tailText, | ||
characterList: prependToTail.getCharacterList().concat(tailCharacters) | ||
characterList: prependToTail.getCharacterList().concat(tailCharacters), | ||
data: prependToTail.getData() | ||
}); | ||
@@ -107,0 +111,0 @@ |
@@ -13,7 +13,7 @@ /** | ||
'use strict'; | ||
/** | ||
* Maintain persistence for target list when appending and prepending. | ||
*/ | ||
'use strict'; | ||
function insertIntoList(targetList, toInsert, offset) { | ||
@@ -20,0 +20,0 @@ if (offset === targetList.count()) { |
@@ -23,4 +23,5 @@ /** | ||
function insertTextIntoContentState(contentState, selectionState, text, characterMetadata) { | ||
!selectionState.isCollapsed() ? process.env.NODE_ENV !== 'production' ? invariant(false, '`insertText` should only be called with a collapsed range.') : invariant(false) : undefined; | ||
!selectionState.isCollapsed() ? process.env.NODE_ENV !== 'production' ? invariant(false, '`insertText` should only be called with a collapsed range.') : invariant(false) : void 0; | ||
@@ -27,0 +28,0 @@ var len = text.length; |
@@ -37,5 +37,4 @@ /** | ||
} | ||
if (offset < leafStart) { | ||
return false; | ||
} | ||
return false; | ||
}); | ||
@@ -42,0 +41,0 @@ } |
@@ -13,2 +13,4 @@ /** | ||
'use strict'; | ||
/** | ||
@@ -22,4 +24,2 @@ * Given a collapsed selection, move the focus `maxDistance` backward within | ||
*/ | ||
'use strict'; | ||
function moveSelectionBackward(editorState, maxDistance) { | ||
@@ -26,0 +26,0 @@ var selection = editorState.getSelection(); |
@@ -13,2 +13,4 @@ /** | ||
'use strict'; | ||
/** | ||
@@ -22,4 +24,2 @@ * Given a collapsed selection, move the focus `maxDistance` forward within | ||
*/ | ||
'use strict'; | ||
function moveSelectionForward(editorState, maxDistance) { | ||
@@ -26,0 +26,0 @@ var selection = editorState.getSelection(); |
@@ -13,10 +13,2 @@ /** | ||
/** | ||
* A plain object representation of a ContentBlock, with all style and entity | ||
* attribution repackaged as range objects. | ||
*/ | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
'use strict'; |
@@ -13,15 +13,2 @@ /** | ||
/** | ||
* A type that represents a composed document as vanilla JavaScript objects, | ||
* with all styles and entities represented as ranges. Corresponding entity | ||
* objects are packaged as objects as well. | ||
* | ||
* This object is especially useful when sending the document state to the | ||
* server for storage, as its representation is more concise than our | ||
* immutable objects. | ||
*/ | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
'use strict'; |
@@ -13,9 +13,2 @@ /** | ||
/** | ||
* A plain object representation of an EntityInstance. | ||
*/ | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); | ||
'use strict'; |
@@ -69,3 +69,3 @@ /** | ||
}); | ||
!(typeof removalRange === 'object') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Removal range must exist within character list.') : invariant(false) : undefined; | ||
!(typeof removalRange === 'object') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Removal range must exist within character list.') : invariant(false) : void 0; | ||
return removalRange; | ||
@@ -72,0 +72,0 @@ } |
@@ -13,2 +13,6 @@ /** | ||
'use strict'; | ||
var DraftModifier = require('./DraftModifier'); | ||
/** | ||
@@ -18,6 +22,2 @@ * For a collapsed selection state, remove text based on the specified strategy. | ||
*/ | ||
'use strict'; | ||
var DraftModifier = require('./DraftModifier'); | ||
function removeTextWithStrategy(editorState, strategy, direction) { | ||
@@ -24,0 +24,0 @@ var selection = editorState.getSelection(); |
@@ -19,2 +19,3 @@ /** | ||
module.exports = { | ||
@@ -21,0 +22,0 @@ BOLD: OrderedSet.of('BOLD'), |
@@ -16,10 +16,8 @@ /** | ||
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; | ||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
var Immutable = require('immutable'); | ||
@@ -29,2 +27,3 @@ | ||
var defaultRecord = { | ||
@@ -41,3 +40,3 @@ anchorKey: '', | ||
var SelectionState = (function (_SelectionStateRecord) { | ||
var SelectionState = function (_SelectionStateRecord) { | ||
_inherits(SelectionState, _SelectionStateRecord); | ||
@@ -48,107 +47,92 @@ | ||
_get(Object.getPrototypeOf(SelectionState.prototype), 'constructor', this).apply(this, arguments); | ||
return _possibleConstructorReturn(this, _SelectionStateRecord.apply(this, arguments)); | ||
} | ||
_createClass(SelectionState, [{ | ||
key: 'serialize', | ||
value: function serialize() { | ||
return 'Anchor: ' + this.getAnchorKey() + ':' + this.getAnchorOffset() + ', ' + 'Focus: ' + this.getFocusKey() + ':' + this.getFocusOffset() + ', ' + 'Is Backward: ' + String(this.getIsBackward()) + ', ' + 'Has Focus: ' + String(this.getHasFocus()); | ||
} | ||
}, { | ||
key: 'getAnchorKey', | ||
value: function getAnchorKey() { | ||
return this.get('anchorKey'); | ||
} | ||
}, { | ||
key: 'getAnchorOffset', | ||
value: function getAnchorOffset() { | ||
return this.get('anchorOffset'); | ||
} | ||
}, { | ||
key: 'getFocusKey', | ||
value: function getFocusKey() { | ||
return this.get('focusKey'); | ||
} | ||
}, { | ||
key: 'getFocusOffset', | ||
value: function getFocusOffset() { | ||
return this.get('focusOffset'); | ||
} | ||
}, { | ||
key: 'getIsBackward', | ||
value: function getIsBackward() { | ||
return this.get('isBackward'); | ||
} | ||
}, { | ||
key: 'getHasFocus', | ||
value: function getHasFocus() { | ||
return this.get('hasFocus'); | ||
} | ||
SelectionState.prototype.serialize = function serialize() { | ||
return 'Anchor: ' + this.getAnchorKey() + ':' + this.getAnchorOffset() + ', ' + 'Focus: ' + this.getFocusKey() + ':' + this.getFocusOffset() + ', ' + 'Is Backward: ' + String(this.getIsBackward()) + ', ' + 'Has Focus: ' + String(this.getHasFocus()); | ||
}; | ||
/** | ||
* Return whether the specified range overlaps with an edge of the | ||
* SelectionState. | ||
*/ | ||
}, { | ||
key: 'hasEdgeWithin', | ||
value: function hasEdgeWithin(blockKey, start, end) { | ||
var anchorKey = this.getAnchorKey(); | ||
var focusKey = this.getFocusKey(); | ||
SelectionState.prototype.getAnchorKey = function getAnchorKey() { | ||
return this.get('anchorKey'); | ||
}; | ||
if (anchorKey === focusKey && anchorKey === blockKey) { | ||
var selectionStart = this.getStartOffset(); | ||
var selectionEnd = this.getEndOffset(); | ||
return start <= selectionEnd && selectionStart <= end; | ||
} | ||
SelectionState.prototype.getAnchorOffset = function getAnchorOffset() { | ||
return this.get('anchorOffset'); | ||
}; | ||
if (blockKey !== anchorKey && blockKey !== focusKey) { | ||
return false; | ||
} | ||
SelectionState.prototype.getFocusKey = function getFocusKey() { | ||
return this.get('focusKey'); | ||
}; | ||
var offsetToCheck = blockKey === anchorKey ? this.getAnchorOffset() : this.getFocusOffset(); | ||
SelectionState.prototype.getFocusOffset = function getFocusOffset() { | ||
return this.get('focusOffset'); | ||
}; | ||
return start <= offsetToCheck && end >= offsetToCheck; | ||
SelectionState.prototype.getIsBackward = function getIsBackward() { | ||
return this.get('isBackward'); | ||
}; | ||
SelectionState.prototype.getHasFocus = function getHasFocus() { | ||
return this.get('hasFocus'); | ||
}; | ||
/** | ||
* Return whether the specified range overlaps with an edge of the | ||
* SelectionState. | ||
*/ | ||
SelectionState.prototype.hasEdgeWithin = function hasEdgeWithin(blockKey, start, end) { | ||
var anchorKey = this.getAnchorKey(); | ||
var focusKey = this.getFocusKey(); | ||
if (anchorKey === focusKey && anchorKey === blockKey) { | ||
var selectionStart = this.getStartOffset(); | ||
var selectionEnd = this.getEndOffset(); | ||
return start <= selectionEnd && selectionStart <= end; | ||
} | ||
}, { | ||
key: 'isCollapsed', | ||
value: function isCollapsed() { | ||
return this.getAnchorKey() === this.getFocusKey() && this.getAnchorOffset() === this.getFocusOffset(); | ||
if (blockKey !== anchorKey && blockKey !== focusKey) { | ||
return false; | ||
} | ||
}, { | ||
key: 'getStartKey', | ||
value: function getStartKey() { | ||
return this.getIsBackward() ? this.getFocusKey() : this.getAnchorKey(); | ||
} | ||
}, { | ||
key: 'getStartOffset', | ||
value: function getStartOffset() { | ||
return this.getIsBackward() ? this.getFocusOffset() : this.getAnchorOffset(); | ||
} | ||
}, { | ||
key: 'getEndKey', | ||
value: function getEndKey() { | ||
return this.getIsBackward() ? this.getAnchorKey() : this.getFocusKey(); | ||
} | ||
}, { | ||
key: 'getEndOffset', | ||
value: function getEndOffset() { | ||
return this.getIsBackward() ? this.getAnchorOffset() : this.getFocusOffset(); | ||
} | ||
}], [{ | ||
key: 'createEmpty', | ||
value: function createEmpty(key) { | ||
return new SelectionState({ | ||
anchorKey: key, | ||
anchorOffset: 0, | ||
focusKey: key, | ||
focusOffset: 0, | ||
isBackward: false, | ||
hasFocus: false | ||
}); | ||
} | ||
}]); | ||
var offsetToCheck = blockKey === anchorKey ? this.getAnchorOffset() : this.getFocusOffset(); | ||
return start <= offsetToCheck && end >= offsetToCheck; | ||
}; | ||
SelectionState.prototype.isCollapsed = function isCollapsed() { | ||
return this.getAnchorKey() === this.getFocusKey() && this.getAnchorOffset() === this.getFocusOffset(); | ||
}; | ||
SelectionState.prototype.getStartKey = function getStartKey() { | ||
return this.getIsBackward() ? this.getFocusKey() : this.getAnchorKey(); | ||
}; | ||
SelectionState.prototype.getStartOffset = function getStartOffset() { | ||
return this.getIsBackward() ? this.getFocusOffset() : this.getAnchorOffset(); | ||
}; | ||
SelectionState.prototype.getEndKey = function getEndKey() { | ||
return this.getIsBackward() ? this.getAnchorKey() : this.getFocusKey(); | ||
}; | ||
SelectionState.prototype.getEndOffset = function getEndOffset() { | ||
return this.getIsBackward() ? this.getAnchorOffset() : this.getFocusOffset(); | ||
}; | ||
SelectionState.createEmpty = function createEmpty(key) { | ||
return new SelectionState({ | ||
anchorKey: key, | ||
anchorOffset: 0, | ||
focusKey: key, | ||
focusOffset: 0, | ||
isBackward: false, | ||
hasFocus: false | ||
}); | ||
}; | ||
return SelectionState; | ||
})(SelectionStateRecord); | ||
}(SelectionStateRecord); | ||
module.exports = SelectionState; |
@@ -14,2 +14,7 @@ /** | ||
'use strict'; | ||
var containsNode = require('fbjs/lib/containsNode'); | ||
var getActiveElement = require('fbjs/lib/getActiveElement'); | ||
/** | ||
@@ -24,7 +29,2 @@ * In modern non-IE browsers, we can support both forward and backward | ||
*/ | ||
'use strict'; | ||
var containsNode = require('fbjs/lib/containsNode'); | ||
var getActiveElement = require('fbjs/lib/getActiveElement'); | ||
function setDraftEditorSelection(selectionState, node, blockKey, nodeStart, nodeEnd) { | ||
@@ -31,0 +31,0 @@ // It's possible that the editor has been removed from the DOM but |
@@ -16,7 +16,12 @@ /** | ||
var Immutable = require('immutable'); | ||
var generateRandomKey = require('./generateRandomKey'); | ||
var invariant = require('fbjs/lib/invariant'); | ||
var Map = Immutable.Map; | ||
function splitBlockInContentState(contentState, selectionState) { | ||
!selectionState.isCollapsed() ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Selection range must be collapsed.') : invariant(false) : undefined; | ||
!selectionState.isCollapsed() ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Selection range must be collapsed.') : invariant(false) : void 0; | ||
@@ -40,3 +45,4 @@ var key = selectionState.getAnchorKey(); | ||
text: text.slice(offset), | ||
characterList: chars.slice(offset) | ||
characterList: chars.slice(offset), | ||
data: Map() | ||
}); | ||
@@ -43,0 +49,0 @@ |
{ | ||
"name": "draft-js", | ||
"description": "A React framework for building text editors.", | ||
"version": "0.7.0", | ||
"version": "0.8.0", | ||
"keywords": [ | ||
@@ -26,2 +26,3 @@ "draftjs", | ||
"build": "gulp", | ||
"postbuild": "node node_modules/fbjs-scripts/node/check-lib-requires.js lib", | ||
"lint": "eslint .", | ||
@@ -33,4 +34,4 @@ "flow": "flow src", | ||
"dependencies": { | ||
"fbjs": "^0.8.1", | ||
"immutable": "^3.7.4" | ||
"fbjs": "^0.8.3", | ||
"immutable": "~3.7.4" | ||
}, | ||
@@ -42,13 +43,17 @@ "peerDependencies": { | ||
"devDependencies": { | ||
"babel-core": "^5.8.35", | ||
"babel-eslint": "^4.1.3", | ||
"babel-core": "^6.8.0", | ||
"babel-eslint": "^6.1.2", | ||
"babel-preset-fbjs": "^2.0.0", | ||
"del": "^2.2.0", | ||
"envify": "^3.4.0", | ||
"es6-shim": "^0.34.4", | ||
"eslint": "^1.5.1", | ||
"eslint-plugin-react": "^3.2.2", | ||
"fbjs-scripts": "^0.6.0-alpha.1", | ||
"flow-bin": "^0.23.0", | ||
"eslint": "^3.0.1", | ||
"eslint-config-fbjs": "^1.0.0", | ||
"eslint-plugin-babel": "^3.3.0", | ||
"eslint-plugin-flow-vars": "^0.4.0", | ||
"eslint-plugin-react": "^5.2.2", | ||
"fbjs-scripts": "^0.7.0", | ||
"flow-bin": "^0.28.0", | ||
"gulp": "^3.9.0", | ||
"gulp-babel": "^5.1.0", | ||
"gulp-babel": "^6.1.2", | ||
"gulp-browserify-thin": "^0.1.5", | ||
@@ -59,6 +64,7 @@ "gulp-clean-css": "^2.0.3", | ||
"gulp-flatten": "^0.2.0", | ||
"gulp-header": "^1.7.1", | ||
"gulp-header": "1.8.2", | ||
"gulp-rename": "^1.2.2", | ||
"gulp-uglify": "^1.2.0", | ||
"gulp-util": "^3.0.6", | ||
"jest-cli": "^11.0.2", | ||
"jest": "^12.1.1", | ||
"object-assign": "^4.0.1", | ||
@@ -73,4 +79,4 @@ "react": "^15.0.0-rc.1", | ||
"devEngines": { | ||
"node": "4.x", | ||
"npm": "2.x" | ||
"node": "4.x || 6.x", | ||
"npm": "2.x || 3.x" | ||
}, | ||
@@ -98,2 +104,3 @@ "jest": { | ||
"<rootDir>/node_modules/immutable/", | ||
"<rootDir>/node_modules/object-assign/", | ||
"<rootDir>/node_modules/react/", | ||
@@ -100,0 +107,0 @@ "<rootDir>/node_modules/react-dom/" |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1174563
274
32
18791
+ Addedimmutable@3.7.6(transitive)
- Removedimmutable@3.8.2(transitive)
Updatedfbjs@^0.8.3
Updatedimmutable@~3.7.4