brew-js-react 0.4.2 → 0.4.4
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/dialog.d.ts +1 -1
- package/dialog.js +22 -10
- package/dist/brew-js-react.js +120 -65
- package/dist/brew-js-react.js.map +1 -1
- package/dist/brew-js-react.min.js +2 -2
- package/dist/brew-js-react.min.js.map +1 -1
- package/hooks.js +7 -6
- package/mixins/FlyoutMixin.js +1 -10
- package/mixins/FlyoutToggleMixin.js +9 -6
- package/mixins/FocusStateMixin.d.ts +12 -1
- package/mixins/FocusStateMixin.js +23 -2
- package/mixins/ScrollableMixin.d.ts +3 -2
- package/mixins/ScrollableMixin.js +2 -0
- package/mixins/StatefulMixin.js +2 -2
- package/package.json +1 -1
- package/view.js +36 -17
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
import React from "react";
|
|
1
2
|
import ClassNameMixin from "./ClassNameMixin";
|
|
2
3
|
|
|
3
|
-
export default class FocusStateMixin extends ClassNameMixin {
|
|
4
|
+
export default class FocusStateMixin extends ClassNameMixin {
|
|
5
|
+
/**
|
|
6
|
+
* Sets focus state based on another element.
|
|
7
|
+
*
|
|
8
|
+
* If the element with this mixin gain focus, the target element will also gain focus.
|
|
9
|
+
* Likewise, if the target element lost focus, the element with this mixin will also lose focus.
|
|
10
|
+
*
|
|
11
|
+
* @param target A CSS selector or a ref object.
|
|
12
|
+
*/
|
|
13
|
+
for(target: string | React.RefObject<Element>): this;
|
|
14
|
+
}
|
|
@@ -10,20 +10,41 @@ export default function FocusStateMixin() {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
definePrototype(FocusStateMixin, StatefulMixin, {
|
|
13
|
+
for: function (ref) {
|
|
14
|
+
this.state.ref = ref;
|
|
15
|
+
return this;
|
|
16
|
+
},
|
|
13
17
|
initElement: function (element, state) {
|
|
14
18
|
FocusStateMixinSuper.initElement.call(this, element, state);
|
|
19
|
+
var checkTarget = function (callback, arg) {
|
|
20
|
+
var ref = state.ref;
|
|
21
|
+
var target = ref && (typeof ref === 'string' ? element.querySelector(ref) : ref.current);
|
|
22
|
+
if (target && !dom.focused(target)) {
|
|
23
|
+
callback(arg || target);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
15
26
|
this.onDispose(dom.on(element, {
|
|
16
27
|
focusin: function (e) {
|
|
17
|
-
state.focused =
|
|
28
|
+
state.focused = e.source;
|
|
18
29
|
setClass(element, 'focused', e.source);
|
|
30
|
+
checkTarget(dom.focus);
|
|
19
31
|
},
|
|
20
32
|
focusout: function () {
|
|
21
33
|
state.focused = false;
|
|
22
34
|
setClass(element, 'focused', false);
|
|
35
|
+
},
|
|
36
|
+
focuschange: function () {
|
|
37
|
+
checkTarget(dom.blur, element);
|
|
23
38
|
}
|
|
24
39
|
}));
|
|
25
40
|
},
|
|
26
41
|
getClassNames: function () {
|
|
27
|
-
|
|
42
|
+
var classes = {};
|
|
43
|
+
var focused = this.state.focused;
|
|
44
|
+
if (focused) {
|
|
45
|
+
classes.focused = true;
|
|
46
|
+
classes['focused-' + focused] = true;
|
|
47
|
+
}
|
|
48
|
+
return [classes];
|
|
28
49
|
}
|
|
29
50
|
});
|
|
@@ -8,6 +8,7 @@ export interface ScrollableMixinOptions {
|
|
|
8
8
|
handle?: 'auto' | 'scrollbar' | 'content';
|
|
9
9
|
paged?: 'always' | 'landscape' | 'portrait';
|
|
10
10
|
pagedItemSelector?: string;
|
|
11
|
+
persistScroll?: boolean;
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
export default class ScrollableMixin extends ClassNameMixin implements JQueryScrollable {
|
|
@@ -31,6 +32,6 @@ export default class ScrollableMixin extends ClassNameMixin implements JQueryScr
|
|
|
31
32
|
scrollTo(x: number, y: number, duration?: number, callback?: () => void): Promise<void>;
|
|
32
33
|
scrollByPage(x: number, y: number, duration?: number, callback?: () => void): Promise<void>;
|
|
33
34
|
scrollToPage(x: number, y: number, duration?: number, callback?: () => void): Promise<void>;
|
|
34
|
-
scrollToElement(target: Element, targetOrigin: string, duration: number, callback?: () => void): Promise<void>;
|
|
35
|
-
scrollToElement(target: Element, targetOrigin?: string, wrapperOrigin?: string, duration?: number, callback?: () => void): Promise<void>;
|
|
35
|
+
scrollToElement(target: Element | string, targetOrigin: string, duration: number, callback?: () => void): Promise<void>;
|
|
36
|
+
scrollToElement(target: Element | string, targetOrigin?: string, wrapperOrigin?: string, duration?: number, callback?: () => void): Promise<void>;
|
|
36
37
|
}
|
|
@@ -28,6 +28,8 @@ definePrototype(ScrollableMixin, ClassNameMixin, {
|
|
|
28
28
|
'scroller-snap-page': options.paged,
|
|
29
29
|
'scroller-page': options.pagedItemSelector,
|
|
30
30
|
'scroller-state': 'pageIndex'
|
|
31
|
+
}, options.persistScroll && {
|
|
32
|
+
'persist-scroll': ''
|
|
31
33
|
});
|
|
32
34
|
},
|
|
33
35
|
onPageIndexChanged: function (callback) {
|
package/mixins/StatefulMixin.js
CHANGED
|
@@ -16,7 +16,7 @@ definePrototype(MixinRefImpl, {
|
|
|
16
16
|
export default function StatefulMixin() {
|
|
17
17
|
Mixin.call(this);
|
|
18
18
|
_(this, {
|
|
19
|
-
elements: new
|
|
19
|
+
elements: new WeakSet(),
|
|
20
20
|
flush: watch(this, false),
|
|
21
21
|
dispose: [],
|
|
22
22
|
states: {},
|
|
@@ -84,7 +84,7 @@ definePrototype(StatefulMixin, Mixin, {
|
|
|
84
84
|
var states = state.states;
|
|
85
85
|
combineFn(state.dispose.splice(0))();
|
|
86
86
|
state.flush();
|
|
87
|
-
state.elements
|
|
87
|
+
state.elements = new WeakSet();
|
|
88
88
|
each(states, function (i, v) {
|
|
89
89
|
delete states[i];
|
|
90
90
|
});
|
package/package.json
CHANGED
package/view.js
CHANGED
|
@@ -2,20 +2,21 @@ import React from "react";
|
|
|
2
2
|
import { useAsync } from "zeta-dom-react";
|
|
3
3
|
import dom from "./include/zeta-dom/dom.js";
|
|
4
4
|
import { notifyAsync } from "./include/zeta-dom/domLock.js";
|
|
5
|
-
import { bind } from "./include/zeta-dom/domUtil.js";
|
|
6
5
|
import { ZetaEventContainer } from "./include/zeta-dom/events.js";
|
|
7
|
-
import { any, combineFn, defineObservableProperty, defineOwnProperty, definePrototype, each, exclude, executeOnce, extend, freeze, grep, isFunction, isThenable, isUndefinedOrNull, keys, makeArray, map, noop, pick, randomId, setImmediate, single, throwNotFunction, watch } from "./include/zeta-dom/util.js";
|
|
6
|
+
import { any, catchAsync, combineFn, createPrivateStore, defineObservableProperty, defineOwnProperty, definePrototype, each, exclude, executeOnce, extend, freeze, grep, isFunction, isThenable, isUndefinedOrNull, keys, makeArray, map, noop, pick, randomId, setImmediate, single, throwNotFunction, watch } from "./include/zeta-dom/util.js";
|
|
8
7
|
import { animateIn, animateOut } from "./include/brew-js/anim.js";
|
|
9
8
|
import { removeQueryAndHash } from "./include/brew-js/util/path.js";
|
|
10
9
|
import { app, onAppInit } from "./app.js";
|
|
11
10
|
import { ViewStateContainer } from "./hooks.js";
|
|
12
11
|
|
|
12
|
+
const _ = createPrivateStore();
|
|
13
13
|
const root = dom.root;
|
|
14
14
|
const routeMap = new Map();
|
|
15
15
|
const usedParams = {};
|
|
16
16
|
const sortedViews = [];
|
|
17
17
|
const emitter = new ZetaEventContainer();
|
|
18
|
-
const
|
|
18
|
+
const rootContext = freeze(extend(new ViewContext(null, null), { container: root }));
|
|
19
|
+
const StateContext = React.createContext(rootContext);
|
|
19
20
|
|
|
20
21
|
var errorView;
|
|
21
22
|
/** @type {Partial<Zeta.ZetaEventType<"beforepageload", Brew.RouterEventMap, Element>>} */
|
|
@@ -24,11 +25,20 @@ var event = {};
|
|
|
24
25
|
onAppInit(function () {
|
|
25
26
|
app.on('beforepageload', function (e) {
|
|
26
27
|
event = e;
|
|
28
|
+
_(rootContext).setPage(app.page);
|
|
27
29
|
});
|
|
28
30
|
});
|
|
29
31
|
|
|
30
|
-
function ViewContext(view) {
|
|
31
|
-
|
|
32
|
+
function ViewContext(view, page) {
|
|
33
|
+
var self = this;
|
|
34
|
+
defineOwnProperty(self, 'view', view, true);
|
|
35
|
+
_(self, {
|
|
36
|
+
setPage: defineObservableProperty(self, 'page', page, true),
|
|
37
|
+
setActive: defineObservableProperty(self, 'active', true, true)
|
|
38
|
+
});
|
|
39
|
+
watch(self, 'page', function (page, previousPage) {
|
|
40
|
+
emitter.emit('pagechange', self, { previousPage });
|
|
41
|
+
});
|
|
32
42
|
}
|
|
33
43
|
|
|
34
44
|
definePrototype(ViewContext, {
|
|
@@ -78,6 +88,7 @@ function ViewContainer() {
|
|
|
78
88
|
React.Component.apply(this, arguments);
|
|
79
89
|
this.stateId = history.state;
|
|
80
90
|
}
|
|
91
|
+
ViewContainer.contextType = StateContext;
|
|
81
92
|
|
|
82
93
|
definePrototype(ViewContainer, React.Component, {
|
|
83
94
|
componentDidMount: function () {
|
|
@@ -85,32 +96,41 @@ definePrototype(ViewContainer, React.Component, {
|
|
|
85
96
|
var self = this;
|
|
86
97
|
self.componentWillUnmount = combineFn(
|
|
87
98
|
watch(app.route, function () {
|
|
88
|
-
self.setActive(self.getViewComponent() === self.currentViewComponent);
|
|
99
|
+
(self.setActive || noop)(self.getViewComponent() === self.currentViewComponent);
|
|
89
100
|
}),
|
|
90
101
|
app.on('beforepageload', function () {
|
|
91
102
|
self.stateId = history.state;
|
|
92
|
-
self.
|
|
93
|
-
|
|
103
|
+
if (self.context === rootContext || self.updateOnNext) {
|
|
104
|
+
event.waitFor(new Promise(function (resolve) {
|
|
105
|
+
self.onRender = resolve;
|
|
106
|
+
}));
|
|
107
|
+
self.updateView();
|
|
108
|
+
self.forceUpdate();
|
|
109
|
+
}
|
|
94
110
|
})
|
|
95
111
|
);
|
|
96
112
|
},
|
|
97
113
|
render: function () {
|
|
98
114
|
/** @type {any} */
|
|
99
115
|
var self = this;
|
|
100
|
-
if (history.state === self.stateId) {
|
|
116
|
+
if (history.state === self.stateId && self.context.active) {
|
|
101
117
|
self.updateView();
|
|
102
118
|
}
|
|
119
|
+
(self.onRender || noop)();
|
|
103
120
|
return React.createElement(React.Fragment, null, self.prevView, self.currentView);
|
|
104
121
|
},
|
|
105
122
|
updateView: function () {
|
|
106
123
|
var self = this;
|
|
107
124
|
var V = self.getViewComponent();
|
|
125
|
+
self.updateOnNext = false;
|
|
108
126
|
if (V) {
|
|
109
127
|
// ensure the current path actually corresponds to the matched view
|
|
110
128
|
// when some views are not included in the list of allowed views
|
|
111
129
|
var targetPath = resolvePath(V, getCurrentParams(V, true));
|
|
112
130
|
if (targetPath !== removeQueryAndHash(app.path)) {
|
|
113
131
|
app.navigate(targetPath, true);
|
|
132
|
+
self.updateOnNext = true;
|
|
133
|
+
return;
|
|
114
134
|
}
|
|
115
135
|
}
|
|
116
136
|
if (V && V !== self.currentViewComponent) {
|
|
@@ -125,6 +145,8 @@ definePrototype(ViewContainer, React.Component, {
|
|
|
125
145
|
self.forceUpdate();
|
|
126
146
|
});
|
|
127
147
|
}
|
|
148
|
+
(self.cancelPrevious || noop)();
|
|
149
|
+
|
|
128
150
|
var onComponentLoaded;
|
|
129
151
|
var promise = new Promise(function (resolve) {
|
|
130
152
|
onComponentLoaded = resolve;
|
|
@@ -138,7 +160,7 @@ definePrototype(ViewContainer, React.Component, {
|
|
|
138
160
|
});
|
|
139
161
|
notifyAsync(element, promise);
|
|
140
162
|
});
|
|
141
|
-
var state = new ViewContext(V);
|
|
163
|
+
var state = new ViewContext(V, app.page);
|
|
142
164
|
var viewProps = freeze({
|
|
143
165
|
navigationType: event.navigationType,
|
|
144
166
|
viewContext: state,
|
|
@@ -148,15 +170,11 @@ definePrototype(ViewContainer, React.Component, {
|
|
|
148
170
|
React.createElement(ViewStateContainer, null,
|
|
149
171
|
React.createElement('div', extend({}, self.props.rootProps, { ref: initElement }),
|
|
150
172
|
React.createElement(ErrorBoundary, { onComponentLoaded, viewProps }))));
|
|
151
|
-
extend(self, {
|
|
173
|
+
extend(self, _(state), {
|
|
174
|
+
cancelPrevious: onComponentLoaded,
|
|
152
175
|
currentPath: app.path,
|
|
153
176
|
currentView: view,
|
|
154
|
-
currentViewComponent: V
|
|
155
|
-
setPage: defineObservableProperty(state, 'page', app.page, true),
|
|
156
|
-
setActive: defineObservableProperty(state, 'active', true, true)
|
|
157
|
-
});
|
|
158
|
-
watch(state, 'page', function (page, previousPage) {
|
|
159
|
-
emitter.emit('pagechange', state, { previousPage });
|
|
177
|
+
currentViewComponent: V
|
|
160
178
|
});
|
|
161
179
|
(event.waitFor || noop)(promise);
|
|
162
180
|
}
|
|
@@ -224,6 +242,7 @@ function createViewComponent(factory) {
|
|
|
224
242
|
if (isThenable(children)) {
|
|
225
243
|
promise = children;
|
|
226
244
|
children = null;
|
|
245
|
+
catchAsync(promise);
|
|
227
246
|
}
|
|
228
247
|
var state = useAsync(function () {
|
|
229
248
|
return promise.then(function (s) {
|