pager-widget 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,142 @@
1
+ import * as PropTypes from 'prop-types';
2
+ import * as React from 'react';
3
+
4
+ // import deepEqual from 'fast-deep-equal';
5
+
6
+ function normalizeHtml(str) {
7
+ return str && str.replace(/&nbsp;|\u202F|\u00A0/g, ' ').replace(/<br \/>/g, '<br>');
8
+ }
9
+
10
+ function replaceCaret(el) {
11
+ // Place the caret at the end of the element
12
+ const target = document.createTextNode('');
13
+ el.appendChild(target);
14
+ // do not move caret if element was not focused
15
+ const isTargetFocused = document.activeElement === el;
16
+ if (target !== null && target.nodeValue !== null && isTargetFocused) {
17
+ var sel = window.getSelection();
18
+ if (sel !== null) {
19
+ var range = document.createRange();
20
+ range.setStart(target, target.nodeValue.length);
21
+ range.collapse(true);
22
+ sel.removeAllRanges();
23
+ sel.addRange(range);
24
+ }
25
+ if (el instanceof HTMLElement) el.focus();
26
+ }
27
+ }
28
+
29
+ /**
30
+ * A simple component for an html element with editable contents.
31
+ */
32
+ export default class ContentEditable extends React.Component {
33
+ lastHtml = this.props.html;
34
+ el = typeof this.props.innerRef === 'function' ? { current: null } : React.createRef();
35
+
36
+ getEl = () => (this.props.innerRef && typeof this.props.innerRef !== 'function' ? this.props.innerRef : this.el).current;
37
+
38
+ render() {
39
+ const { tagName, html, innerRef, ...props } = this.props;
40
+ // console.log("lastHtml",this.lastHtml)
41
+
42
+ return React.createElement(
43
+ tagName || 'div',
44
+ {
45
+ ...props,
46
+ ref: typeof innerRef === 'function' ? (current) => {
47
+ innerRef(current)
48
+ this.el.current = current
49
+ } : innerRef || this.el,
50
+ onInput: this.emitChange,
51
+ onBlur: this.props.onBlur || this.emitChange,
52
+ onKeyUp: this.props.onKeyUp || this.emitChange,
53
+ onKeyDown: this.props.onKeyDown || this.emitChange,
54
+ contentEditable: !this.props.disabled,
55
+ dangerouslySetInnerHTML: { __html: html }
56
+ },
57
+ this.props.children);
58
+ }
59
+
60
+ shouldComponentUpdate(nextProps) {
61
+ console.log("shouldComponentUpdate",nextProps)
62
+ const { props } = this;
63
+ const el = this.getEl();
64
+
65
+ // We need not rerender if the change of props simply reflects the user's edits.
66
+ // Rerendering in this case would make the cursor/caret jump
67
+ console.log("element",el)
68
+ // Rerender if there is no element yet... (somehow?)
69
+ if (!el) return true;
70
+ console.log("shouldUpdate",normalizeHtml(nextProps.html),normalizeHtml(el.innerHTML) )
71
+
72
+ // ...or if html really changed... (programmatically, not by user edit)
73
+ if (
74
+ normalizeHtml(nextProps.html) !== normalizeHtml(el.innerHTML)
75
+ ) {
76
+
77
+ return true;
78
+ }
79
+
80
+ const shouldUpdate = props.disabled !== nextProps.disabled ||
81
+ props.tagName !== nextProps.tagName ||
82
+ props.className !== nextProps.className ||
83
+ props.innerRef !== nextProps.innerRef ||
84
+ props.placeholder !== nextProps.placeholder
85
+
86
+ console.log("shouldUpdate",shouldUpdate)
87
+
88
+ // Handle additional properties
89
+ return shouldUpdate
90
+ // !deepEqual(props.style, nextProps.style);
91
+ }
92
+
93
+ componentDidUpdate() {
94
+ const el = this.getEl();
95
+ if (!el) return;
96
+
97
+ // Perhaps React (whose VDOM gets outdated because we often prevent
98
+ // rerendering) did not update the DOM. So we update it manually now.
99
+ if (this.props.html !== el.innerHTML) {
100
+ el.innerHTML = this.props.html;
101
+ }
102
+ this.lastHtml = this.props.html;
103
+ replaceCaret(el);
104
+ }
105
+
106
+ emitChange = (originalEvt) => {
107
+
108
+ const el = this.getEl();
109
+ if (!el) return;
110
+
111
+ let html = el.innerHTML;
112
+ html = html.replace(/<div>/g, '');
113
+ html = html.replace(/<\/div>/g, '');
114
+ html = html.replace(/<br>/g, '');
115
+ // console.log("emit change called",html)
116
+ if (this.props.onChange && html !== this.lastHtml) {
117
+ // Clone event with Object.assign to avoid
118
+ // "Cannot assign to read only property 'target' of object"
119
+ const evt = Object.assign({}, originalEvt, {
120
+ target: {
121
+ value: html
122
+ }
123
+ });
124
+ this.props.onChange(evt);
125
+ }
126
+ this.lastHtml = html;
127
+ // this.forceUpdate();
128
+ }
129
+
130
+ static propTypes = {
131
+ html: PropTypes.string.isRequired,
132
+ onChange: PropTypes.func,
133
+ disabled: PropTypes.bool,
134
+ tagName: PropTypes.string,
135
+ className: PropTypes.string,
136
+ style: PropTypes.object,
137
+ innerRef: PropTypes.oneOfType([
138
+ PropTypes.object,
139
+ PropTypes.func,
140
+ ])
141
+ }
142
+ }