@thoughtbot/superglue 0.30.0 → 0.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/action_creators/requests.js +11 -1
- package/components/Nav.js +100 -27
- package/components/RailsTag.js +2 -9
- package/index.js +2 -10
- package/package.json +5 -4
- package/utils/helpers.js +3 -1
package/README.md
CHANGED
|
@@ -60,7 +60,7 @@ A popular ask of SPAs is page-to-page navigation without reloading. This is
|
|
|
60
60
|
easily done with Superglue's own UJS attributes inspired by Turbolinks:
|
|
61
61
|
|
|
62
62
|
```jsx
|
|
63
|
-
<a href='/posts' data-
|
|
63
|
+
<a href='/posts' data-sg-visit={true} />
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
The above will request for `/posts` with an `accept` of `application/json`, and
|
|
@@ -70,8 +70,8 @@ component the response asks for, and `pushState` on history.
|
|
|
70
70
|
|
|
71
71
|
#### Partial updates
|
|
72
72
|
Some features rely on updating some parts of the existing page. In
|
|
73
|
-
addition to `data-
|
|
74
|
-
also provides `data-
|
|
73
|
+
addition to `data-sg-visit` and it's equivalent `this.props.visit`, Superglue
|
|
74
|
+
also provides `data-sg-remote` or `this.props.remote`, which you can use to
|
|
75
75
|
update parts of your page in async fashion without changing `window.history`.
|
|
76
76
|
|
|
77
77
|
Imagine having to implement search, where you enter some text, hit enter, and
|
|
@@ -121,7 +121,9 @@ function visit(path, _temp2) {
|
|
|
121
121
|
_ref4$beforeSave = _ref4.beforeSave,
|
|
122
122
|
beforeSave = _ref4$beforeSave === void 0 ? function (prevPage, receivedPage) {
|
|
123
123
|
return receivedPage;
|
|
124
|
-
} : _ref4$beforeSave
|
|
124
|
+
} : _ref4$beforeSave,
|
|
125
|
+
_ref4$revisit = _ref4.revisit,
|
|
126
|
+
revisit = _ref4$revisit === void 0 ? false : _ref4$revisit;
|
|
125
127
|
|
|
126
128
|
path = (0, _utils.withoutBusters)(path);
|
|
127
129
|
var pageKey = (0, _utils.urlToPageKey)(path);
|
|
@@ -183,6 +185,14 @@ function visit(path, _temp2) {
|
|
|
183
185
|
meta.suggestedAction = 'replace';
|
|
184
186
|
}
|
|
185
187
|
|
|
188
|
+
if (revisit && fetchArgs[1].method == 'GET') {
|
|
189
|
+
if (rsp.redirected) {
|
|
190
|
+
meta.suggestedAction = 'replace';
|
|
191
|
+
} else {
|
|
192
|
+
meta.suggestedAction = 'none';
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
186
196
|
if (method !== 'GET') {
|
|
187
197
|
var contentLocation = rsp.headers.get('content-location');
|
|
188
198
|
|
package/components/Nav.js
CHANGED
|
@@ -9,8 +9,6 @@ var _utils = require("../utils");
|
|
|
9
9
|
|
|
10
10
|
var _actions = require("../actions");
|
|
11
11
|
|
|
12
|
-
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
13
|
-
|
|
14
12
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
15
13
|
|
|
16
14
|
function _extends() { _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; }; return _extends.apply(this, arguments); }
|
|
@@ -33,11 +31,13 @@ var Nav = /*#__PURE__*/function (_React$Component) {
|
|
|
33
31
|
initialPageKey = _this$props.initialPageKey;
|
|
34
32
|
_this.history = history;
|
|
35
33
|
_this.navigateTo = _this.navigateTo.bind(_assertThisInitialized(_this));
|
|
34
|
+
_this.scrollTo = _this.scrollTo.bind(_assertThisInitialized(_this));
|
|
36
35
|
_this.onHistoryChange = _this.onHistoryChange.bind(_assertThisInitialized(_this));
|
|
37
36
|
_this.state = {
|
|
38
37
|
pageKey: initialPageKey,
|
|
39
38
|
ownProps: {}
|
|
40
39
|
};
|
|
40
|
+
_this.hasWindow = typeof window !== 'undefined';
|
|
41
41
|
return _this;
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -59,21 +59,39 @@ var Nav = /*#__PURE__*/function (_React$Component) {
|
|
|
59
59
|
action = _ref.action,
|
|
60
60
|
ownProps = _ref.ownProps;
|
|
61
61
|
|
|
62
|
+
if (action === 'none') {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
|
|
62
66
|
path = (0, _utils.pathWithoutBZParams)(path);
|
|
63
67
|
var nextPageKey = (0, _utils.urlToPageKey)(path);
|
|
64
68
|
var store = this.props.store;
|
|
65
69
|
var hasPage = !!store.getState().pages[nextPageKey];
|
|
66
70
|
|
|
67
71
|
if (hasPage) {
|
|
68
|
-
var
|
|
72
|
+
var location = this.history.location;
|
|
73
|
+
var prevPageKey = location.state.pageKey;
|
|
69
74
|
var historyArgs = [path, {
|
|
70
75
|
pageKey: nextPageKey,
|
|
71
|
-
superglue: true
|
|
76
|
+
superglue: true,
|
|
77
|
+
posY: 0,
|
|
78
|
+
posX: 0
|
|
72
79
|
}];
|
|
73
80
|
|
|
74
81
|
if (action === 'push') {
|
|
75
82
|
var _this$history;
|
|
76
83
|
|
|
84
|
+
if (this.hasWindow) {
|
|
85
|
+
this.history.replace({
|
|
86
|
+
pathname: location.pathname,
|
|
87
|
+
search: location.search,
|
|
88
|
+
hash: location.hash
|
|
89
|
+
}, Object.assign({}, location.state, {
|
|
90
|
+
posY: window.pageYOffset,
|
|
91
|
+
posX: window.pageXOffset
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
|
|
77
95
|
(_this$history = this.history).push.apply(_this$history, historyArgs);
|
|
78
96
|
}
|
|
79
97
|
|
|
@@ -87,6 +105,7 @@ var Nav = /*#__PURE__*/function (_React$Component) {
|
|
|
87
105
|
pageKey: nextPageKey,
|
|
88
106
|
ownProps: ownProps
|
|
89
107
|
});
|
|
108
|
+
this.scrollTo(0, 0);
|
|
90
109
|
|
|
91
110
|
if (action === 'replace' && prevPageKey && prevPageKey !== nextPageKey) {
|
|
92
111
|
store.dispatch({
|
|
@@ -104,8 +123,18 @@ var Nav = /*#__PURE__*/function (_React$Component) {
|
|
|
104
123
|
}
|
|
105
124
|
};
|
|
106
125
|
|
|
107
|
-
_proto.
|
|
108
|
-
|
|
126
|
+
_proto.scrollTo = function scrollTo(posX, posY) {
|
|
127
|
+
this.hasWindow && window.scrollTo(posX, posY);
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
_proto.onHistoryChange = function onHistoryChange(_ref2) {
|
|
131
|
+
var _this2 = this;
|
|
132
|
+
|
|
133
|
+
var location = _ref2.location,
|
|
134
|
+
action = _ref2.action;
|
|
135
|
+
var _this$props2 = this.props,
|
|
136
|
+
store = _this$props2.store,
|
|
137
|
+
visit = _this$props2.visit;
|
|
109
138
|
var pathname = location.pathname,
|
|
110
139
|
search = location.search,
|
|
111
140
|
hash = location.hash,
|
|
@@ -120,23 +149,75 @@ var Nav = /*#__PURE__*/function (_React$Component) {
|
|
|
120
149
|
hash: hash
|
|
121
150
|
}
|
|
122
151
|
});
|
|
123
|
-
|
|
152
|
+
|
|
153
|
+
if (action !== 'POP') {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
var pageKey = state.pageKey,
|
|
158
|
+
posX = state.posX,
|
|
159
|
+
posY = state.posY;
|
|
124
160
|
var containsKey = !!store.getState().pages[pageKey];
|
|
125
161
|
|
|
126
162
|
if (containsKey) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
163
|
+
var restoreStrategy = store.getState().pages[pageKey].restoreStrategy;
|
|
164
|
+
|
|
165
|
+
switch (restoreStrategy) {
|
|
166
|
+
case 'fromCacheOnly':
|
|
167
|
+
this.setState({
|
|
168
|
+
pageKey: pageKey
|
|
169
|
+
});
|
|
170
|
+
this.scrollTo(posX, posY);
|
|
171
|
+
break;
|
|
172
|
+
|
|
173
|
+
case 'fromCacheAndRevisitInBackground':
|
|
174
|
+
this.setState({
|
|
175
|
+
pageKey: pageKey
|
|
176
|
+
});
|
|
177
|
+
this.scrollTo(posX, posY);
|
|
178
|
+
visit(pageKey, {
|
|
179
|
+
revisit: true
|
|
180
|
+
});
|
|
181
|
+
break;
|
|
182
|
+
|
|
183
|
+
case 'revisitOnly':
|
|
184
|
+
default:
|
|
185
|
+
visit(pageKey, {
|
|
186
|
+
revisit: true
|
|
187
|
+
}).then(function (meta) {
|
|
188
|
+
if (meta === undefined) {
|
|
189
|
+
console.warn("scoll restoration was skipped. Your visit's then funtion\n should return the meta object it recieved if you want your\n application to restore the page's previous scroll.");
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (!!meta && meta.suggestedAction === 'none') {
|
|
193
|
+
_this2.setState({
|
|
194
|
+
pageKey: pageKey
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
_this2.scrollTo(posX, posY);
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
}
|
|
130
201
|
} else {
|
|
131
|
-
|
|
202
|
+
visit(pageKey, {
|
|
203
|
+
revisit: true
|
|
204
|
+
}).then(function (meta) {
|
|
205
|
+
if (meta === undefined) {
|
|
206
|
+
console.warn("scoll restoration was skipped. Your visit's then funtion\n should return the meta object it recieved if you want your\n application to restore the page's previous scroll.");
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (!!meta && meta.suggestedAction === 'none') {
|
|
210
|
+
_this2.setState({
|
|
211
|
+
pageKey: pageKey
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
_this2.scrollTo(posX, posY);
|
|
215
|
+
}
|
|
216
|
+
});
|
|
132
217
|
}
|
|
133
218
|
}
|
|
134
219
|
};
|
|
135
220
|
|
|
136
|
-
_proto.reloadPage = function reloadPage() {
|
|
137
|
-
window.location.reload();
|
|
138
|
-
};
|
|
139
|
-
|
|
140
221
|
_proto.notFound = function notFound(identifier) {
|
|
141
222
|
var reminder = '';
|
|
142
223
|
|
|
@@ -149,10 +230,10 @@ var Nav = /*#__PURE__*/function (_React$Component) {
|
|
|
149
230
|
};
|
|
150
231
|
|
|
151
232
|
_proto.render = function render() {
|
|
152
|
-
var _this$
|
|
153
|
-
store = _this$
|
|
154
|
-
visit = _this$
|
|
155
|
-
remote = _this$
|
|
233
|
+
var _this$props3 = this.props,
|
|
234
|
+
store = _this$props3.store,
|
|
235
|
+
visit = _this$props3.visit,
|
|
236
|
+
remote = _this$props3.remote;
|
|
156
237
|
var _this$state = this.state,
|
|
157
238
|
pageKey = _this$state.pageKey,
|
|
158
239
|
ownProps = _this$state.ownProps;
|
|
@@ -174,13 +255,5 @@ var Nav = /*#__PURE__*/function (_React$Component) {
|
|
|
174
255
|
return Nav;
|
|
175
256
|
}(_react["default"].Component);
|
|
176
257
|
|
|
177
|
-
Nav.propTypes = {
|
|
178
|
-
store: _propTypes["default"].object,
|
|
179
|
-
history: _propTypes["default"].object,
|
|
180
|
-
mapping: _propTypes["default"].object,
|
|
181
|
-
visit: _propTypes["default"].func,
|
|
182
|
-
remote: _propTypes["default"].func,
|
|
183
|
-
initialPageKey: _propTypes["default"].string
|
|
184
|
-
};
|
|
185
258
|
var _default = Nav;
|
|
186
259
|
exports["default"] = _default;
|
package/components/RailsTag.js
CHANGED
|
@@ -7,10 +7,6 @@ var _react = _interopRequireDefault(require("react"));
|
|
|
7
7
|
|
|
8
8
|
var _htmlReactParser = _interopRequireWildcard(require("html-react-parser"));
|
|
9
9
|
|
|
10
|
-
var _attributesToProps = _interopRequireDefault(require("html-react-parser/lib/attributes-to-props"));
|
|
11
|
-
|
|
12
|
-
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
13
|
-
|
|
14
10
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
15
11
|
|
|
16
12
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
@@ -48,7 +44,7 @@ var RailsTag = /*#__PURE__*/function (_React$Component) {
|
|
|
48
44
|
children = domNode.children;
|
|
49
45
|
|
|
50
46
|
if (!parent && type === 'tag') {
|
|
51
|
-
var nextProps = Object.assign({}, this.props, (0,
|
|
47
|
+
var nextProps = Object.assign({}, this.props, (0, _htmlReactParser.attributesToProps)(attribs), {
|
|
52
48
|
children: (0, _htmlReactParser.domToReact)(children)
|
|
53
49
|
});
|
|
54
50
|
delete nextProps.html;
|
|
@@ -65,7 +61,4 @@ var RailsTag = /*#__PURE__*/function (_React$Component) {
|
|
|
65
61
|
return RailsTag;
|
|
66
62
|
}(_react["default"].Component);
|
|
67
63
|
|
|
68
|
-
exports["default"] = RailsTag;
|
|
69
|
-
RailsTag.propTypes = {
|
|
70
|
-
html: _propTypes["default"].string
|
|
71
|
-
};
|
|
64
|
+
exports["default"] = RailsTag;
|
package/index.js
CHANGED
|
@@ -34,8 +34,6 @@ var _history = require("history");
|
|
|
34
34
|
|
|
35
35
|
var _Nav = _interopRequireDefault(require("./components/Nav"));
|
|
36
36
|
|
|
37
|
-
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
38
|
-
|
|
39
37
|
var _react2 = require("./utils/react");
|
|
40
38
|
|
|
41
39
|
exports.mapStateToProps = _react2.mapStateToProps;
|
|
@@ -198,7 +196,7 @@ var ApplicationBase = /*#__PURE__*/function (_React$Component) {
|
|
|
198
196
|
visit: this.visit,
|
|
199
197
|
remote: this.remote,
|
|
200
198
|
store: this.store,
|
|
201
|
-
ujsAttributePrefix: 'data-
|
|
199
|
+
ujsAttributePrefix: 'data-sg'
|
|
202
200
|
});
|
|
203
201
|
var _this$ujsHandlers = this.ujsHandlers,
|
|
204
202
|
onClick = _this$ujsHandlers.onClick,
|
|
@@ -254,10 +252,4 @@ var ApplicationBase = /*#__PURE__*/function (_React$Component) {
|
|
|
254
252
|
return ApplicationBase;
|
|
255
253
|
}(_react["default"].Component);
|
|
256
254
|
|
|
257
|
-
exports.ApplicationBase = ApplicationBase;
|
|
258
|
-
ApplicationBase.propTypes = {
|
|
259
|
-
initialPage: _propTypes["default"].object,
|
|
260
|
-
baseUrl: _propTypes["default"].string,
|
|
261
|
-
path: _propTypes["default"].string,
|
|
262
|
-
appEl: _propTypes["default"].object
|
|
263
|
-
};
|
|
255
|
+
exports.ApplicationBase = ApplicationBase;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thoughtbot/superglue",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.41.0",
|
|
4
4
|
"description": "Use a vanilla Rails with React and Redux",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"eslint-plugin-react": "^7.24.0",
|
|
27
27
|
"fetch-headers": "^2.0.0",
|
|
28
28
|
"fetch-mock": "^9.11.0",
|
|
29
|
-
"history": "^
|
|
29
|
+
"history": "^5.3.0",
|
|
30
30
|
"html-react-parser": "^1.2.6",
|
|
31
31
|
"jest": "^27.0.4",
|
|
32
32
|
"node-fetch": "^2.6.1",
|
|
@@ -40,15 +40,16 @@
|
|
|
40
40
|
"redux-thunk": "^2.3.0"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
|
+
"history": "^5.3.0",
|
|
43
44
|
"html-react-parser": ">=1.2.6",
|
|
44
45
|
"react": ">=16",
|
|
45
|
-
"redux": ">=4.1",
|
|
46
|
-
"history": "^4.7.1",
|
|
47
46
|
"react-redux": ">=7.2",
|
|
47
|
+
"redux": ">=4.1",
|
|
48
48
|
"redux-thunk": ">=2.3"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"abortcontroller-polyfill": "^1.7.3",
|
|
52
|
+
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
|
|
52
53
|
"url-parse": "^1.5.1"
|
|
53
54
|
}
|
|
54
55
|
}
|