brew-js-react 0.5.7 → 0.6.1

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.
@@ -1,4 +1,4 @@
1
- /*! brew-js-react v0.5.7 | (c) misonou | https://misonou.github.io */
1
+ /*! brew-js-react v0.6.1 | (c) misonou | https://misonou.github.io */
2
2
  (function webpackUniversalModuleDefinition(root, factory) {
3
3
  if(typeof exports === 'object' && typeof module === 'object')
4
4
  module.exports = factory(require("zeta-dom"), require("react"), require("react-dom"), require("brew-js"), require("zeta-dom-react"), require("waterpipe"), require("jquery"));
@@ -249,12 +249,10 @@ var _lib$util = external_commonjs_zeta_dom_commonjs2_zeta_dom_amd_zeta_dom_root_
249
249
  util_keys = _lib$util.keys,
250
250
  kv = _lib$util.kv,
251
251
  makeArray = _lib$util.makeArray,
252
- makeAsync = _lib$util.makeAsync,
253
252
  map = _lib$util.map,
254
253
  mapObject = _lib$util.mapObject,
255
254
  noop = _lib$util.noop,
256
255
  pick = _lib$util.pick,
257
- pipe = _lib$util.pipe,
258
256
  randomId = _lib$util.randomId,
259
257
  resolve = _lib$util.resolve,
260
258
  resolveAll = _lib$util.resolveAll,
@@ -262,6 +260,7 @@ var _lib$util = external_commonjs_zeta_dom_commonjs2_zeta_dom_amd_zeta_dom_root_
262
260
  setImmediateOnce = _lib$util.setImmediateOnce,
263
261
  single = _lib$util.single,
264
262
  throwNotFunction = _lib$util.throwNotFunction,
263
+ _throws = _lib$util["throws"],
265
264
  watch = _lib$util.watch,
266
265
  watchable = _lib$util.watchable;
267
266
 
@@ -271,6 +270,7 @@ var external_commonjs_react_commonjs2_react_amd_react_root_React_ = __webpack_re
271
270
 
272
271
  var Component = external_commonjs_react_commonjs2_react_amd_react_root_React_.Component,
273
272
  Fragment = external_commonjs_react_commonjs2_react_amd_react_root_React_.Fragment,
273
+ StrictMode = external_commonjs_react_commonjs2_react_amd_react_root_React_.StrictMode,
274
274
  createContext = external_commonjs_react_commonjs2_react_amd_react_root_React_.createContext,
275
275
  createElement = external_commonjs_react_commonjs2_react_amd_react_root_React_.createElement,
276
276
  useContext = external_commonjs_react_commonjs2_react_amd_react_root_React_.useContext,
@@ -296,12 +296,15 @@ var domUtil_lib$util = external_commonjs_zeta_dom_commonjs2_zeta_dom_amd_zeta_do
296
296
 
297
297
  var dom = external_commonjs_zeta_dom_commonjs2_zeta_dom_amd_zeta_dom_root_zeta_.dom;
298
298
  /* harmony default export */ const zeta_dom_dom = (dom);
299
+ var reportError = dom.reportError;
300
+
299
301
  ;// CONCATENATED MODULE: ./|umd|/zeta-dom/domLock.js
300
302
 
301
303
  var _lib$dom = external_commonjs_zeta_dom_commonjs2_zeta_dom_amd_zeta_dom_root_zeta_.dom,
302
304
  lock = _lib$dom.lock,
303
305
  notifyAsync = _lib$dom.notifyAsync,
304
306
  preventLeave = _lib$dom.preventLeave,
307
+ runAsync = _lib$dom.runAsync,
305
308
  subscribeAsync = _lib$dom.subscribeAsync;
306
309
 
307
310
  // EXTERNAL MODULE: external {"commonjs":"brew-js","commonjs2":"brew-js","amd":"brew-js","root":"brew"}
@@ -309,6 +312,7 @@ var external_commonjs_brew_js_commonjs2_brew_js_amd_brew_js_root_brew_ = __webpa
309
312
  ;// CONCATENATED MODULE: ./|umd|/brew-js/domAction.js
310
313
 
311
314
  var closeFlyout = external_commonjs_brew_js_commonjs2_brew_js_amd_brew_js_root_brew_.closeFlyout,
315
+ isFlyoutOpen = external_commonjs_brew_js_commonjs2_brew_js_amd_brew_js_root_brew_.isFlyoutOpen,
312
316
  openFlyout = external_commonjs_brew_js_commonjs2_brew_js_amd_brew_js_root_brew_.openFlyout,
313
317
  toggleFlyout = external_commonjs_brew_js_commonjs2_brew_js_amd_brew_js_root_brew_.toggleFlyout;
314
318
 
@@ -328,7 +332,7 @@ var closeFlyout = external_commonjs_brew_js_commonjs2_brew_js_amd_brew_js_root_b
328
332
  function createDialog(props) {
329
333
  var root = document.createElement('div');
330
334
  var reactRoot = fallback.createRoot(root);
331
- var _closeDialog = closeFlyout.bind(0, root);
335
+ var closeDialog = closeFlyout.bind(0, root);
332
336
  var promise;
333
337
  zeta_dom_dom.on(root, {
334
338
  flyoutshow: function flyoutshow() {
@@ -347,32 +351,30 @@ function createDialog(props) {
347
351
  subscribeAsync(root, true);
348
352
  return {
349
353
  root: root,
350
- close: _closeDialog,
354
+ close: closeDialog,
351
355
  open: function open() {
352
356
  if (promise) {
353
357
  return promise;
354
358
  }
355
359
  root.className = props.className || '';
356
360
  document.body.appendChild(root);
357
- zeta_dom_dom.retainFocus(zeta_dom_dom.activeElement, root);
358
361
  if (props.modal) {
359
362
  root.setAttribute('is-modal', '');
360
363
  }
361
364
  if (props.onRender) {
362
365
  var dialogProps = extend({}, props, {
363
- closeDialog: function closeDialog(value) {
364
- var promise = makeAsync(props.onCommit || pipe)(value);
365
- notifyAsync(zeta_dom_dom.activeElement, promise);
366
- return promise.then(_closeDialog);
367
- }
366
+ closeDialog: props.onCommit ? function (value) {
367
+ return runAsync(zeta_dom_dom.activeElement, props.onCommit.bind(this, value)).then(closeDialog);
368
+ } : closeDialog
368
369
  });
369
370
  var content = /*#__PURE__*/createElement(props.onRender, dialogProps);
370
371
  if (props.wrapper) {
371
372
  content = /*#__PURE__*/createElement(props.wrapper, dialogProps, content);
372
373
  }
373
- reactRoot.render(content);
374
+ reactRoot.render( /*#__PURE__*/createElement(StrictMode, null, content));
374
375
  }
375
376
  promise = resolve().then(function () {
377
+ zeta_dom_dom.retainFocus(zeta_dom_dom.activeElement, root);
376
378
  return openFlyout(root, null, pick(props, ['focus']));
377
379
  });
378
380
  if (props.preventLeave) {
@@ -419,7 +421,7 @@ var ViewStateProvider = external_commonjs_zeta_dom_react_commonjs2_zeta_dom_reac
419
421
  useMemoizedFunction = external_commonjs_zeta_dom_react_commonjs2_zeta_dom_react_amd_zeta_dom_react_root_zeta_react_.useMemoizedFunction,
420
422
  useObservableProperty = external_commonjs_zeta_dom_react_commonjs2_zeta_dom_react_amd_zeta_dom_react_root_zeta_react_.useObservableProperty,
421
423
  useSingleton = external_commonjs_zeta_dom_react_commonjs2_zeta_dom_react_amd_zeta_dom_react_root_zeta_react_.useSingleton,
422
- useUpdateTrigger = external_commonjs_zeta_dom_react_commonjs2_zeta_dom_react_amd_zeta_dom_react_root_zeta_react_.useUpdateTrigger;
424
+ useValueTrigger = external_commonjs_zeta_dom_react_commonjs2_zeta_dom_react_amd_zeta_dom_react_root_zeta_react_.useValueTrigger;
423
425
 
424
426
  ;// CONCATENATED MODULE: ./|umd|/zeta-dom/events.js
425
427
 
@@ -496,23 +498,16 @@ onAppInit(function () {
496
498
  rootState.setPage(app_app.page);
497
499
  rootState.setActive(true);
498
500
  view_event = e;
499
- e.waitFor(new Promise(function (resolve) {
500
- (function updateViewRecursive(next) {
501
- if (!next[0]) {
502
- return resolve();
503
- }
504
- resolveAll(map(next, function (v) {
505
- return new Promise(function (resolve) {
506
- v.onRender = resolve;
507
- v.forceUpdate();
508
- });
509
- })).then(function () {
510
- updateViewRecursive(map(next, function (v) {
511
- return v.children;
512
- }));
513
- });
514
- })(rootState.children);
515
- }));
501
+ (function updateViewRecursive(next) {
502
+ each(next.children, function (i, v) {
503
+ e.waitFor(new Promise(function (resolve) {
504
+ v.onRender = resolve;
505
+ v.forceUpdate();
506
+ }).then(function () {
507
+ updateViewRecursive(v);
508
+ }));
509
+ });
510
+ })(rootState);
516
511
  });
517
512
  });
518
513
  function ViewContext(view, page, parent) {
@@ -536,7 +531,7 @@ function ViewContext(view, page, parent) {
536
531
  definePrototype(ViewContext, {
537
532
  getChildren: function getChildren() {
538
533
  return map(_(this).children, function (v) {
539
- return v.currentState;
534
+ return v.currentContext;
540
535
  });
541
536
  },
542
537
  on: function on(event, handler) {
@@ -559,9 +554,7 @@ definePrototype(ErrorBoundary, Component, {
559
554
  // emit error in next tick as ref callback may yet to be invoked
560
555
  // if error is thrown synchronously in first render
561
556
  setImmediate(function () {
562
- zeta_dom_dom.emit('error', self.context.container, {
563
- error: error
564
- }, true);
557
+ reportError(error, self.context.container);
565
558
  });
566
559
  // ensure promise sent to beforepageload event is resolved
567
560
  self.props.onComponentLoaded();
@@ -609,7 +602,7 @@ definePrototype(ViewContainer, Component, {
609
602
  arrRemove(parent, self);
610
603
  unwatch();
611
604
  setImmediate(function () {
612
- if (self.unmountView && !self.currentState.active) {
605
+ if (self.unmountView && !self.currentContext.active) {
613
606
  self.unmountView();
614
607
  }
615
608
  });
@@ -641,20 +634,21 @@ definePrototype(ViewContainer, Component, {
641
634
  }
642
635
  if (V && viewChanged) {
643
636
  (self.unmountView || noop)(true);
644
- var state = new ViewContext(V, app_app.page, self.context);
637
+ var context = new ViewContext(V, app_app.page, self.context);
638
+ var state = routeMap.get(V);
645
639
  var onComponentLoaded;
646
640
  var promise = new Promise(function (resolve) {
647
641
  onComponentLoaded = resolve;
648
642
  });
649
643
  var unmountView = onComponentLoaded;
650
644
  var initElement = executeOnce(function (element) {
651
- state.container = element;
645
+ context.container = element;
652
646
  promise.then(function () {
653
- if (self.currentState === state) {
647
+ if (self.currentContext === context) {
654
648
  unmountView = function unmountView() {
655
649
  self.prevView = self.currentView;
656
650
  app_app.emit('pageleave', element, {
657
- pathname: state.page.path,
651
+ pathname: context.page.path,
658
652
  view: V
659
653
  }, true);
660
654
  animateOut(element, 'show').then(function () {
@@ -664,21 +658,23 @@ definePrototype(ViewContainer, Component, {
664
658
  };
665
659
  animateIn(element, 'show', '[brew-view]', true);
666
660
  app_app.emit('pageenter', element, {
667
- pathname: state.page.path,
661
+ pathname: context.page.path,
668
662
  view: V
669
663
  }, true);
670
664
  }
671
665
  });
672
666
  notifyAsync(element, promise);
673
667
  });
674
- var viewProps = freeze({
675
- navigationType: view_event.navigationType,
676
- viewContext: state,
677
- viewData: view_event.data || {}
678
- });
668
+ var viewProps = function viewProps() {
669
+ return freeze({
670
+ navigationType: view_event.navigationType,
671
+ viewContext: context,
672
+ viewData: context.page.data || {}
673
+ });
674
+ };
679
675
  var view = /*#__PURE__*/createElement(StateContext.Provider, {
680
- key: routeMap.get(V).id,
681
- value: state
676
+ key: state.id,
677
+ value: context
682
678
  }, /*#__PURE__*/createElement(ViewStateContainer, null, /*#__PURE__*/createElement('div', extend({}, self.props.rootProps, {
683
679
  ref: initElement,
684
680
  'brew-view': ''
@@ -686,17 +682,17 @@ definePrototype(ViewContainer, Component, {
686
682
  onComponentLoaded: onComponentLoaded,
687
683
  viewProps: viewProps
688
684
  }))));
689
- extend(self, _(state), {
690
- currentState: state,
685
+ extend(self, _(context), {
686
+ currentContext: context,
691
687
  currentView: view,
692
688
  currentViewComponent: V,
693
689
  unmountView: executeOnce(function () {
694
690
  self.setActive(false);
695
- routeMap.get(V).rendered--;
691
+ state.rendered--;
696
692
  unmountView();
697
693
  })
698
694
  });
699
- routeMap.get(V).rendered++;
695
+ state.rendered++;
700
696
  (view_event.waitFor || noop)(promise);
701
697
  }
702
698
  (self.setPage || noop)(app_app.page);
@@ -756,19 +752,24 @@ function createViewComponent(factory) {
756
752
  factory = createElement.bind(null, factory);
757
753
  }
758
754
  return function fn(props) {
759
- var viewProps = props.viewProps;
760
- var children = !promise && factory(viewProps);
755
+ var viewContext = useContext(StateContext);
756
+ var viewProps = useState(props.viewProps);
757
+ var children = !promise && factory(viewProps[0]);
761
758
  if (isThenable(children)) {
762
759
  promise = children;
763
760
  children = null;
764
761
  catchAsync(promise);
765
762
  }
766
763
  var state = useAsync(function () {
767
- return promise.then(function (s) {
768
- return /*#__PURE__*/createElement(s["default"], viewProps);
769
- });
764
+ return promise;
770
765
  }, !!promise)[1];
771
766
  var loaded = !promise || !state.loading;
767
+ useEffect(function () {
768
+ // listen to property directly so that it is invoked after pagechange event handlers in actual component
769
+ return watch(viewContext, 'page', function () {
770
+ viewProps[1](props.viewProps);
771
+ });
772
+ }, []);
772
773
  useEffect(function () {
773
774
  if (loaded) {
774
775
  setImmediate(props.onComponentLoaded);
@@ -777,7 +778,7 @@ function createViewComponent(factory) {
777
778
  if (state.error) {
778
779
  throw state.error;
779
780
  }
780
- return children || state.value || /*#__PURE__*/createElement(Fragment);
781
+ return children || (state.value ? /*#__PURE__*/createElement(state.value["default"], viewProps[0]) : null);
781
782
  };
782
783
  }
783
784
  function useViewContext() {
@@ -936,20 +937,15 @@ function useRouteParam(name, defaultValue) {
936
937
  var container = useViewContext();
937
938
  var params = container.page.params;
938
939
  var value = params[name] || '';
939
- var ref = useRef(value);
940
- var forceUpdate = useUpdateTrigger();
940
+ var notifyChange = useValueTrigger(value);
941
941
  useEffect(function () {
942
942
  var setValue = function setValue() {
943
- var current = container.page.params[name] || '';
944
- if (current !== ref.current) {
945
- forceUpdate();
946
- }
943
+ notifyChange(container.page.params[name] || '');
947
944
  };
948
945
  // route parameter might be changed after state initialization and before useEffect hook is called
949
946
  setValue();
950
947
  return container.on('pagechange', setValue);
951
948
  }, [name]);
952
- ref.current = value;
953
949
  if (defaultValue && container.active && (!value || name === 'remainingSegments' && value === '/')) {
954
950
  app_app.navigate(app_app.route.getPath(extend({}, params, kv(name, defaultValue))), true);
955
951
  }
@@ -979,22 +975,20 @@ function useQueryParam(key, value, snapshotOnUpdate) {
979
975
  }
980
976
  var container = useViewContext();
981
977
  var getParams = function getParams() {
982
- return mapObject(key === false ? value : kv(key, value), function (v, i) {
978
+ return freeze(mapObject(key === false ? value : kv(key, value), function (v, i) {
983
979
  return getQueryParam(i, app_app.path) || v || '';
984
- });
980
+ }));
985
981
  };
986
- var state = useState([]);
982
+ var ref = useRef({});
987
983
  useMemo(function () {
988
- state[0].splice(0, 2, getParams());
984
+ ref.current = getParams();
989
985
  }, [key]);
990
- var current = state[0][0];
991
- var trackChanges = function trackChanges(values) {
992
- if (!equal(values, current)) {
993
- extend(current, values);
994
- state[1]([current]);
995
- }
996
- };
986
+ var current = ref.current;
987
+ var notifyChange = useValueTrigger(current, function (current, params) {
988
+ return equal(current, params) || !(ref.current = params);
989
+ });
997
990
  var setParams = useMemoizedFunction(function (values) {
991
+ var current = ref.current;
998
992
  if (key !== false) {
999
993
  values = kv(key, isFunction(values) ? values(current[key]) : values);
1000
994
  } else if (isFunction(values)) {
@@ -1009,19 +1003,19 @@ function useQueryParam(key, value, snapshotOnUpdate) {
1009
1003
  if (snapshotOnUpdate) {
1010
1004
  app_app.snapshot();
1011
1005
  }
1012
- catchAsync(app_app.navigate(search + url.hash, true));
1013
- trackChanges(getParams());
1006
+ catchAsync(app_app.navigate((search || '?') + url.hash, true));
1007
+ notifyChange(getParams());
1014
1008
  }
1015
1009
  }
1016
1010
  });
1017
1011
  useEffect(function () {
1018
1012
  return app_app.watch('path', function () {
1019
1013
  if (container.active) {
1020
- trackChanges(getParams());
1014
+ notifyChange(getParams());
1021
1015
  }
1022
1016
  });
1023
1017
  }, [key]);
1024
- return [key !== false ? current[key] : state[0][1] || (state[0][1] = freeze(extend({}, current))), setParams];
1018
+ return [key !== false ? current[key] : current, setParams];
1025
1019
  }
1026
1020
  function ViewStateContainer(props) {
1027
1021
  var cache = useState({})[0];
@@ -1221,6 +1215,22 @@ var observe_lib$dom = external_commonjs_zeta_dom_commonjs2_zeta_dom_amd_zeta_dom
1221
1215
 
1222
1216
 
1223
1217
  var StatefulMixin_ = createPrivateStore();
1218
+ var unmounted = new Set();
1219
+ function disposeUnmountedStates() {
1220
+ each(unmounted, function (i, v) {
1221
+ combineFn(StatefulMixin_(v).splice(0))();
1222
+ });
1223
+ unmounted.clear();
1224
+ }
1225
+ function MixinState(parent, element) {
1226
+ StatefulMixin_(this, [parent["delete"].bind(parent, element)]);
1227
+ parent.set(element, this);
1228
+ }
1229
+ definePrototype(MixinState, {
1230
+ onDispose: function onDispose(callback) {
1231
+ StatefulMixin_(this).push(throwNotFunction(callback));
1232
+ }
1233
+ });
1224
1234
  function MixinRefImpl(mixin) {
1225
1235
  this.mixin = mixin;
1226
1236
  }
@@ -1233,8 +1243,8 @@ function StatefulMixin() {
1233
1243
  Mixin.call(this);
1234
1244
  StatefulMixin_(this, {
1235
1245
  pending: {},
1236
- elements: new Set(),
1237
- states: new WeakMap(),
1246
+ elements: [],
1247
+ states: new Map(),
1238
1248
  flush: watch(this, false),
1239
1249
  dispose: []
1240
1250
  });
@@ -1259,36 +1269,37 @@ definePrototype(StatefulMixin, Mixin, {
1259
1269
  var self = this;
1260
1270
  var obj = StatefulMixin_(self);
1261
1271
  var newState = obj.pending;
1262
- var state;
1272
+ var element, state;
1263
1273
  return function (current) {
1264
1274
  if (current) {
1265
- state = obj.states.get(current) || extend(self.initState(), newState);
1266
- if (state.element !== current) {
1267
- state.element = current;
1268
- self.initElement(current, state);
1269
- obj.states.set(current, state);
1275
+ element = current;
1276
+ state = obj.states.get(element) || new MixinState(obj.states, element);
1277
+ obj.elements.push(element);
1278
+ if (!state.element) {
1279
+ self.initElement(element, extend(state, self.initState(), newState, {
1280
+ element: element
1281
+ }));
1270
1282
  } else if (util_keys(newState)[0]) {
1271
- self.mergeState(current, state, newState);
1283
+ self.mergeState(element, state, newState);
1272
1284
  }
1273
- self.onLayoutEffect(current, state);
1274
- obj.elements.add(current);
1285
+ self.onLayoutEffect(element, state);
1286
+ unmounted["delete"](state);
1275
1287
  } else if (state) {
1276
- var prev = state.element;
1277
- self.onBeforeUpdate(prev, state);
1278
- obj.elements["delete"](prev);
1288
+ unmounted.add(state);
1289
+ self.onBeforeUpdate(element, state);
1290
+ arrRemove(obj.elements, element);
1279
1291
  }
1292
+ setImmediateOnce(disposeUnmountedStates);
1280
1293
  };
1281
1294
  },
1282
1295
  elements: function elements() {
1283
- return map(StatefulMixin_(this).elements, pipe);
1296
+ return StatefulMixin_(this).elements.slice();
1284
1297
  },
1285
1298
  onDispose: function onDispose(callback) {
1286
1299
  StatefulMixin_(this).dispose.push(callback);
1287
1300
  },
1288
1301
  initState: function initState() {
1289
- return {
1290
- element: null
1291
- };
1302
+ return {};
1292
1303
  },
1293
1304
  initElement: function initElement(element, state) {},
1294
1305
  mergeState: function mergeState(element, state, newState) {
@@ -1301,9 +1312,12 @@ definePrototype(StatefulMixin, Mixin, {
1301
1312
  },
1302
1313
  dispose: function dispose() {
1303
1314
  var state = StatefulMixin_(this);
1315
+ each(state.states, function (i, v) {
1316
+ unmounted.add(v);
1317
+ });
1318
+ setImmediateOnce(disposeUnmountedStates);
1304
1319
  combineFn(state.dispose.splice(0))();
1305
1320
  state.flush();
1306
- state.states = {};
1307
1321
  state.pending = {};
1308
1322
  }
1309
1323
  });
@@ -1328,18 +1342,13 @@ function ClassNameMixin(classNames) {
1328
1342
  this.classNames = classNames || [];
1329
1343
  }
1330
1344
  definePrototype(ClassNameMixin, StatefulMixin, {
1331
- initState: function initState() {
1332
- return {
1333
- element: null,
1334
- classNames: fill(this.classNames, false)
1335
- };
1336
- },
1337
1345
  initElement: function initElement(element, state) {
1338
1346
  var self = this;
1347
+ state.classNames = fill(self.classNames, false);
1339
1348
  checkState(self, element, state);
1340
- watchOwnAttributes(element, 'class', function () {
1349
+ state.onDispose(watchOwnAttributes(element, 'class', function () {
1341
1350
  checkState(self, element, state, true);
1342
- });
1351
+ }).dispose);
1343
1352
  },
1344
1353
  onLayoutEffect: function onLayoutEffect(element, state) {
1345
1354
  setClass(element, state.classNames);
@@ -1432,9 +1441,9 @@ definePrototype(AnimateSequenceMixin, AnimateMixin, {
1432
1441
  var self = this;
1433
1442
  AnimateSequenceMixinSuper.initElement.call(self, element, state);
1434
1443
  if (self.selector) {
1435
- self.onDispose(watchElements(element, self.selector, function (addedNodes) {
1444
+ state.onDispose(watchElements(element, self.selector, function (addedNodes) {
1436
1445
  external_commonjs_jquery_commonjs2_jquery_amd_jquery_root_jQuery_(addedNodes).attr('is-animate-sequence', '');
1437
- }));
1446
+ }).dispose);
1438
1447
  }
1439
1448
  }
1440
1449
  });
@@ -1485,13 +1494,13 @@ definePrototype(FlyoutToggleMixin, ClassNameMixin, {
1485
1494
  close: function close(value) {
1486
1495
  return this.flyoutMixin.close(value);
1487
1496
  },
1488
- toggle: function toggle(source) {
1489
- return this.flyoutMixin.toggleSelf(source);
1497
+ toggle: function toggle(flag, source) {
1498
+ return this.flyoutMixin.toggleSelf(flag, source);
1490
1499
  },
1491
1500
  initElement: function initElement(element, state) {
1492
1501
  var self = this;
1493
1502
  FlyoutToggleMixinSuper.initElement.call(self, element, state);
1494
- self.onDispose(zeta_dom_dom.on(element, {
1503
+ state.onDispose(zeta_dom_dom.on(element, {
1495
1504
  focusin: function focusin() {
1496
1505
  triggerFlyoutAction(self, state, 'focus', self.open, [null, zeta_dom_dom.activeElement]);
1497
1506
  },
@@ -1512,6 +1521,13 @@ definePrototype(FlyoutToggleMixin, ClassNameMixin, {
1512
1521
 
1513
1522
  var FlyoutMixinSuper = ClassNameMixin.prototype;
1514
1523
  var valueMap = new WeakMap();
1524
+ function _toggleSelf(self, flag, value, source) {
1525
+ if (!flag && !isFlyoutOpen(self.element)) {
1526
+ return resolve();
1527
+ }
1528
+ var options = self.getOptions();
1529
+ return flag ? openFlyout(self.element, value, source, options) : toggleFlyout(self.element, source, options);
1530
+ }
1515
1531
  function FlyoutMixin() {
1516
1532
  var self = this;
1517
1533
  ClassNameMixin.call(self, ['open', 'closing', 'visible', 'tweening-in', 'tweening-out']);
@@ -1529,6 +1545,9 @@ function FlyoutMixin() {
1529
1545
  });
1530
1546
  }
1531
1547
  definePrototype(FlyoutMixin, ClassNameMixin, {
1548
+ get element() {
1549
+ return this.elements()[0] || null;
1550
+ },
1532
1551
  getOptions: function getOptions() {
1533
1552
  var self = this;
1534
1553
  var options = pick(self, ['closeOnBlur']);
@@ -1561,19 +1580,22 @@ definePrototype(FlyoutMixin, ClassNameMixin, {
1561
1580
  });
1562
1581
  },
1563
1582
  open: function open(value, source) {
1564
- return openFlyout(this.elements()[0], value, source, this.getOptions());
1583
+ return _toggleSelf(this, true, value, source);
1565
1584
  },
1566
1585
  close: function close(value) {
1567
- return closeFlyout(this.elements()[0], value);
1586
+ return closeFlyout(this.element, value);
1568
1587
  },
1569
- toggleSelf: function toggleSelf(source) {
1570
- return toggleFlyout(this.elements()[0], source, this.getOptions());
1588
+ toggleSelf: function toggleSelf(flag, source) {
1589
+ if (typeof flag !== 'boolean') {
1590
+ source = flag;
1591
+ flag = !isFlyoutOpen(this.element);
1592
+ }
1593
+ return _toggleSelf(this, flag, undefined, source);
1571
1594
  },
1572
1595
  onOpen: function onOpen(callback) {
1573
- var element = this.elements()[0];
1574
1596
  return this.onToggleState(function (opened) {
1575
1597
  if (opened) {
1576
- return callback(valueMap.get(element));
1598
+ callback(valueMap.get(this.element));
1577
1599
  }
1578
1600
  });
1579
1601
  },
@@ -1585,8 +1607,11 @@ definePrototype(FlyoutMixin, ClassNameMixin, {
1585
1607
  },
1586
1608
  initElement: function initElement(element, state) {
1587
1609
  var self = this;
1610
+ if (self.elements()[1]) {
1611
+ _throws('FlyoutMixin only supports single element');
1612
+ }
1588
1613
  FlyoutMixinSuper.initElement.call(self, element, state);
1589
- self.onDispose(app_app.on(element, {
1614
+ state.onDispose(app_app.on(element, {
1590
1615
  flyoutshow: function flyoutshow(e) {
1591
1616
  valueMap.set(element, e.data);
1592
1617
  self.isFlyoutOpened = true;
@@ -1630,7 +1655,7 @@ definePrototype(FocusStateMixin, StatefulMixin, {
1630
1655
  callback(arg || target);
1631
1656
  }
1632
1657
  };
1633
- this.onDispose(zeta_dom_dom.on(element, {
1658
+ state.onDispose(zeta_dom_dom.on(element, {
1634
1659
  focusin: function focusin(e) {
1635
1660
  state.focused = e.source;
1636
1661
  setClass(element, 'focused', e.source);
@@ -1669,7 +1694,7 @@ definePrototype(LoadingStateMixin, ClassNameMixin, {
1669
1694
  var self = this;
1670
1695
  LoadingStateMixinSuper.initElement.call(self, element, state);
1671
1696
  getDirectiveComponent(element).enableLoadingClass = true;
1672
- self.onDispose(subscribeAsync(element, function (loading) {
1697
+ state.onDispose(subscribeAsync(element, function (loading) {
1673
1698
  self.loading = loading || !!any(self.elements(), function (v) {
1674
1699
  return v !== element && getClass(v, 'loading') === true;
1675
1700
  });
@@ -1691,6 +1716,13 @@ function ScrollableMixin() {
1691
1716
  self.scrolling = false;
1692
1717
  }
1693
1718
  definePrototype(ScrollableMixin, ClassNameMixin, {
1719
+ get element() {
1720
+ return this.elements()[0] || null;
1721
+ },
1722
+ get contentElement() {
1723
+ var element = this.element;
1724
+ return element && getDirectiveComponent(element).scrollable.scrollTarget;
1725
+ },
1694
1726
  withOptions: function withOptions(options) {
1695
1727
  this.options = options;
1696
1728
  return this;
@@ -1711,8 +1743,11 @@ definePrototype(ScrollableMixin, ClassNameMixin, {
1711
1743
  },
1712
1744
  initElement: function initElement(element, state) {
1713
1745
  var self = this;
1746
+ if (self.elements()[1]) {
1747
+ _throws('ScrollableMixin only supports single element');
1748
+ }
1714
1749
  ScrollableMixinSuper.initElement.call(self, element, state);
1715
- self.onDispose(app_app.on(element, {
1750
+ state.onDispose(app_app.on(element, {
1716
1751
  scrollIndexChange: function scrollIndexChange(e) {
1717
1752
  self.pageIndex = e.newIndex;
1718
1753
  },
@@ -1727,7 +1762,7 @@ definePrototype(ScrollableMixin, ClassNameMixin, {
1727
1762
  });
1728
1763
  each('destroy enable disable setOptions setStickyPosition refresh scrollPadding stop scrollLeft scrollTop scrollBy scrollTo scrollByPage scrollToPage scrollToElement', function (i, v) {
1729
1764
  defineHiddenProperty(ScrollableMixin.prototype, v, function () {
1730
- var obj = getDirectiveComponent(this.elements()[0]);
1765
+ var obj = getDirectiveComponent(this.element);
1731
1766
  return obj.scrollable[v].apply(null, arguments);
1732
1767
  });
1733
1768
  });