unpoly-rails 3.7.3.1 → 3.8.0.rc1

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.
@@ -5,7 +5,7 @@
5
5
  /***/ (() => {
6
6
 
7
7
  window.up = {
8
- version: '3.7.3'
8
+ version: '3.8.0-rc1'
9
9
  };
10
10
 
11
11
 
@@ -230,11 +230,6 @@ up.util = (function () {
230
230
  function isArguments(value) {
231
231
  return Object.prototype.toString.call(value) === '[object Arguments]';
232
232
  }
233
- function nullToUndefined(value) {
234
- if (!isNull(value)) {
235
- return value;
236
- }
237
- }
238
233
  function wrapList(value) {
239
234
  if (isList(value)) {
240
235
  return value;
@@ -338,9 +333,6 @@ up.util = (function () {
338
333
  function compact(array) {
339
334
  return filterList(array, isGiven);
340
335
  }
341
- function filterMap(list, mapping) {
342
- return filterList(map(list, mapping), isDefined);
343
- }
344
336
  function compactObject(object) {
345
337
  return pickBy(object, isGiven);
346
338
  }
@@ -390,9 +382,6 @@ up.util = (function () {
390
382
  function queueTask(task) {
391
383
  return setTimeout(task);
392
384
  }
393
- function queueMicrotask(task) {
394
- return Promise.resolve().then(task);
395
- }
396
385
  function last(value) {
397
386
  return value[value.length - 1];
398
387
  }
@@ -400,6 +389,9 @@ up.util = (function () {
400
389
  let indexOf = value.indexOf || Array.prototype.indexOf;
401
390
  return indexOf.call(value, subValue) >= 0;
402
391
  }
392
+ function containsAll(values, subValues) {
393
+ return every(subValues, (subValue) => contains(values, subValue));
394
+ }
403
395
  function objectContains(object, subObject) {
404
396
  const reducedValue = pick(object, Object.keys(subObject));
405
397
  return isEqual(subObject, reducedValue);
@@ -583,6 +575,14 @@ up.util = (function () {
583
575
  function reverse(list) {
584
576
  return copy(list).reverse();
585
577
  }
578
+ function replaceValue(value, matchValue, replacementValue) {
579
+ if (value === matchValue) {
580
+ return replacementValue;
581
+ }
582
+ else {
583
+ return value;
584
+ }
585
+ }
586
586
  function renameKeys(object, renameKeyFn) {
587
587
  const renamed = {};
588
588
  for (let key in object) {
@@ -734,7 +734,6 @@ up.util = (function () {
734
734
  normalizeMethod,
735
735
  methodAllowsPayload,
736
736
  copy,
737
- copyArrayLike,
738
737
  merge,
739
738
  mergeDefined,
740
739
  options: newOptions,
@@ -748,7 +747,6 @@ up.util = (function () {
748
747
  every,
749
748
  find: findInList,
750
749
  filter: filterList,
751
- filterMap: filterMap,
752
750
  reject,
753
751
  intersect,
754
752
  compact,
@@ -780,6 +778,7 @@ up.util = (function () {
780
778
  isRegExp,
781
779
  timer: scheduleTimer,
782
780
  contains,
781
+ containsAll,
783
782
  objectContains,
784
783
  toArray,
785
784
  pick,
@@ -806,7 +805,6 @@ up.util = (function () {
806
805
  isBasicObjectProperty,
807
806
  isCrossOrigin,
808
807
  task: queueTask,
809
- microtask: queueMicrotask,
810
808
  isEqual,
811
809
  parseTokens,
812
810
  wrapList,
@@ -817,10 +815,9 @@ up.util = (function () {
817
815
  delegate: defineDelegates,
818
816
  reverse,
819
817
  camelToKebabCase,
820
- nullToUndefined,
818
+ replaceValue,
821
819
  sprintf,
822
820
  renameKeys,
823
- negate,
824
821
  memoizeMethod,
825
822
  safeStringifyJSON,
826
823
  variant,
@@ -1184,7 +1181,7 @@ up.element = (function () {
1184
1181
  }
1185
1182
  }
1186
1183
  function idSelector(id) {
1187
- if (id.match(/^[a-z0-9\-_]+$/i)) {
1184
+ if (id.match(/^[a-z][a-z0-9\-_]*$/i)) {
1188
1185
  return `#${id}`;
1189
1186
  }
1190
1187
  else {
@@ -1274,9 +1271,6 @@ up.element = (function () {
1274
1271
  element.appendChild(wrapper);
1275
1272
  return wrapper;
1276
1273
  }
1277
- function isWrapper(element) {
1278
- return element.matches('up-wrapper');
1279
- }
1280
1274
  function preservingFocus(fn) {
1281
1275
  const oldFocusElement = document.activeElement;
1282
1276
  try {
@@ -1289,7 +1283,8 @@ up.element = (function () {
1289
1283
  }
1290
1284
  }
1291
1285
  function stringAttr(element, attribute) {
1292
- return u.nullToUndefined(element.getAttribute(attribute));
1286
+ let value = element.getAttribute(attribute);
1287
+ return u.replaceValue(value, null, undefined);
1293
1288
  }
1294
1289
  function booleanAttr(element, attribute, pass) {
1295
1290
  if (!element.hasAttribute(attribute))
@@ -1314,14 +1309,15 @@ up.element = (function () {
1314
1309
  }
1315
1310
  }
1316
1311
  }
1317
- function booleanOrStringAttr(element, attribute) {
1318
- return booleanAttr(element, attribute, true);
1312
+ function booleanOrStringAttr(element, attribute, trueValue = true) {
1313
+ let value = booleanAttr(element, attribute, true);
1314
+ return value === true ? trueValue : value;
1319
1315
  }
1320
1316
  function numberAttr(element, attribute) {
1321
1317
  let value = element.getAttribute(attribute);
1322
1318
  if (value) {
1323
1319
  value = value.replace(/_/g, '');
1324
- if (value.match(/^[\d.]+$/)) {
1320
+ if (value.match(/^-?[\d.]+$/)) {
1325
1321
  return parseFloat(value);
1326
1322
  }
1327
1323
  }
@@ -1358,10 +1354,6 @@ up.element = (function () {
1358
1354
  element.classList.add(klass);
1359
1355
  return () => element.classList.remove(klass);
1360
1356
  }
1361
- function setTemporaryAttr(element, attr, value) {
1362
- element.setAttribute(attr, value);
1363
- return () => element.removeAttribute(element, attr);
1364
- }
1365
1357
  function computedStyle(element, props) {
1366
1358
  const style = window.getComputedStyle(element);
1367
1359
  return extractFromStyleObject(style, props);
@@ -1447,6 +1439,18 @@ up.element = (function () {
1447
1439
  function crossOriginSelector(attr) {
1448
1440
  return `[${attr}*="//"]:not([${attr}*="//${location.host}/"])`;
1449
1441
  }
1442
+ function isIntersectingWindow(element, { margin = 0 } = {}) {
1443
+ const rect = up.Rect.fromElement(element);
1444
+ rect.grow(margin);
1445
+ return (rect.bottom > 0) && (rect.top < window.innerHeight) &&
1446
+ (rect.right > 0) && (rect.left < window.innerWidth);
1447
+ }
1448
+ function unionSelector(includes, excludes) {
1449
+ let selector = `:is(${includes.join()})`;
1450
+ if (u.isPresent(excludes))
1451
+ selector += `:not(${excludes.join()})`;
1452
+ return selector;
1453
+ }
1450
1454
  return {
1451
1455
  subtree,
1452
1456
  contains,
@@ -1481,7 +1485,6 @@ up.element = (function () {
1481
1485
  setMissingAttr,
1482
1486
  unwrap,
1483
1487
  wrapChildren,
1484
- isWrapper,
1485
1488
  attr: stringAttr,
1486
1489
  booleanAttr,
1487
1490
  numberAttr,
@@ -1498,11 +1501,12 @@ up.element = (function () {
1498
1501
  upClasses,
1499
1502
  toggleAttr,
1500
1503
  addTemporaryClass,
1501
- setTemporaryAttr,
1502
1504
  cleanJQuery,
1503
1505
  parseSelector,
1504
1506
  isEmpty,
1505
1507
  crossOriginSelector,
1508
+ isIntersectingWindow,
1509
+ unionSelector,
1506
1510
  };
1507
1511
  })();
1508
1512
 
@@ -1612,6 +1616,7 @@ up.Record = class Record {
1612
1616
  /***/ (() => {
1613
1617
 
1614
1618
  const u = up.util;
1619
+ const e = up.element;
1615
1620
  up.Config = class Config {
1616
1621
  constructor(blueprintFn = (() => ({}))) {
1617
1622
  this._blueprintFn = blueprintFn;
@@ -1627,10 +1632,7 @@ up.Config = class Config {
1627
1632
  selector(prop) {
1628
1633
  let includes = this[prop];
1629
1634
  let excludes = this['no' + u.upperCaseFirst(prop)];
1630
- let selector = `:is(${includes.join()})`;
1631
- if (u.isPresent(excludes))
1632
- selector += `:not(${excludes.join()})`;
1633
- return selector;
1635
+ return e.unionSelector(includes, excludes);
1634
1636
  }
1635
1637
  selectorFn(prop) {
1636
1638
  return () => this.selector(prop);
@@ -1801,6 +1803,12 @@ up.Rect = class Rect extends up.Record {
1801
1803
  get right() {
1802
1804
  return this.left + this.width;
1803
1805
  }
1806
+ grow(padding) {
1807
+ this.left -= padding;
1808
+ this.top -= padding;
1809
+ this.width += padding * 2;
1810
+ this.height += padding * 2;
1811
+ }
1804
1812
  static fromElement(element) {
1805
1813
  return new (this)(element.getBoundingClientRect());
1806
1814
  }
@@ -1812,64 +1820,46 @@ up.Rect = class Rect extends up.Record {
1812
1820
  /***/ (() => {
1813
1821
 
1814
1822
  const e = up.element;
1823
+ const SHIFT_CLASS = 'up-scrollbar-away';
1815
1824
  up.BodyShifter = class BodyShifter {
1816
1825
  constructor() {
1817
- this._unshiftFns = [];
1818
1826
  this._anchoredElements = new Set();
1819
1827
  this._stack = 0;
1820
1828
  }
1821
1829
  lowerStack() {
1822
- this._stack--;
1823
- if (this._stack === 0) {
1830
+ if (--this._stack === 0)
1824
1831
  this._unshiftNow();
1825
- }
1826
1832
  }
1827
1833
  raiseStack() {
1828
- this._stack++;
1829
- if (this._stack === 1) {
1834
+ if (++this._stack === 1)
1830
1835
  this._shiftNow();
1831
- }
1832
1836
  }
1833
1837
  onAnchoredElementInserted(element) {
1834
1838
  this._anchoredElements.add(element);
1835
- if (this._isShifted()) {
1836
- this._shiftAnchoredElement(element);
1837
- }
1839
+ this._shiftElement(element, 'right');
1838
1840
  return () => this._anchoredElements.delete(element);
1839
1841
  }
1840
1842
  _isShifted() {
1841
- return this._scrollbarTookSpace && this._stack > 0;
1843
+ return this._rootScrollbarWidth && this._stack > 0;
1842
1844
  }
1843
1845
  _shiftNow() {
1844
- this._scrollbarWidth = up.viewport.scrollbarWidth();
1845
- this._scrollbarTookSpace = up.viewport.rootHasReducedWidthFromScrollbar();
1846
- if (!this._scrollbarTookSpace)
1847
- return;
1848
- this._shiftBody();
1846
+ this._rootScrollbarWidth = up.viewport.rootScrollbarWidth();
1847
+ e.root.style.setProperty('--up-scrollbar-width', this._rootScrollbarWidth + 'px');
1848
+ this._shiftElement(document.body, 'padding-right');
1849
1849
  for (let element of this._anchoredElements) {
1850
- this._shiftAnchoredElement(element);
1850
+ this._shiftElement(element, 'right');
1851
1851
  }
1852
1852
  }
1853
- _shiftBody() {
1854
- const overflowElement = up.viewport.rootOverflowElement();
1855
- this._changeStyle(overflowElement, { overflowY: 'hidden' });
1856
- const { body } = document;
1857
- const bodyRightPadding = e.styleNumber(body, 'paddingRight');
1858
- const bodyRightShift = this._scrollbarWidth + bodyRightPadding;
1859
- this._changeStyle(body, { paddingRight: bodyRightShift });
1860
- }
1861
- _shiftAnchoredElement(element) {
1862
- const elementRight = e.styleNumber(element, 'right');
1863
- const elementRightShift = this._scrollbarWidth + elementRight;
1864
- this._changeStyle(element, { right: elementRightShift });
1865
- }
1866
- _changeStyle(element, styles) {
1867
- this._unshiftFns.push(e.setTemporaryStyle(element, styles));
1853
+ _shiftElement(element, styleProp) {
1854
+ if (!this._isShifted())
1855
+ return;
1856
+ let originalValue = e.style(element, styleProp);
1857
+ element.style.setProperty('--up-original-' + styleProp, originalValue);
1858
+ element.classList.add(SHIFT_CLASS);
1868
1859
  }
1869
1860
  _unshiftNow() {
1870
- let unshiftFn;
1871
- while (unshiftFn = this._unshiftFns.pop()) {
1872
- unshiftFn();
1861
+ for (let element of [document.body, ...this._anchoredElements]) {
1862
+ element.classList.remove(SHIFT_CLASS);
1873
1863
  }
1874
1864
  }
1875
1865
  };
@@ -3078,6 +3068,7 @@ up.Change.FromContent = (_a = class FromContent extends up.Change {
3078
3068
  }
3079
3069
  this.options.title = this.improveHistoryValue(this.options.title, responseDoc.title);
3080
3070
  this.options.metaTags = this.improveHistoryValue(this.options.metaTags, responseDoc.metaTags);
3071
+ this.options.lang = this.improveHistoryValue(this.options.lang, responseDoc.lang);
3081
3072
  }
3082
3073
  _defaultPlacement() {
3083
3074
  if (!this.options.document && !this.options.fragment) {
@@ -3831,6 +3822,7 @@ var __rest = (this && this.__rest) || function (s, e) {
3831
3822
  return t;
3832
3823
  };
3833
3824
  const u = up.util;
3825
+ const e = up.element;
3834
3826
  up.FormValidator = class FormValidator {
3835
3827
  constructor(form) {
3836
3828
  this._form = form;
@@ -3891,7 +3883,7 @@ up.FormValidator = class FormValidator {
3891
3883
  }
3892
3884
  }
3893
3885
  _getTargetSelectorSolutions({ target, origin }) {
3894
- if (u.isString(target) && target) {
3886
+ if (u.isString(target)) {
3895
3887
  up.puts('up.validate()', 'Validating target "%s"', target);
3896
3888
  let simpleSelectors = up.fragment.splitTarget(target);
3897
3889
  return u.compact(simpleSelectors.map(function (simpleSelector) {
@@ -3920,7 +3912,7 @@ up.FormValidator = class FormValidator {
3920
3912
  _getValidateAttrSolutions(field) {
3921
3913
  let containerWithAttr = field.closest('[up-validate]');
3922
3914
  if (containerWithAttr) {
3923
- let target = containerWithAttr.getAttribute('up-validate');
3915
+ let target = e.booleanOrStringAttr(containerWithAttr, 'up-validate');
3924
3916
  return this._getTargetSelectorSolutions({ target, origin: field });
3925
3917
  }
3926
3918
  }
@@ -3968,7 +3960,8 @@ up.FormValidator = class FormValidator {
3968
3960
  options.guardEvent = up.event.build('up:form:validate', {
3969
3961
  fields: dirtyFields,
3970
3962
  log: 'Validating form',
3971
- params: options.params
3963
+ params: options.params,
3964
+ form: this._form,
3972
3965
  });
3973
3966
  this._rendering = true;
3974
3967
  let renderingPromise = this._nextRenderPromise;
@@ -4617,6 +4610,7 @@ up.Layer = class Layer extends up.Record {
4617
4610
  this.savedTitle = document.title;
4618
4611
  this.savedMetaTags = up.history.findMetaTags();
4619
4612
  this.savedLocation = up.history.location;
4613
+ this.savedLang = up.history.getLang();
4620
4614
  }
4621
4615
  }
4622
4616
  restoreHistory() {
@@ -4632,6 +4626,9 @@ up.Layer = class Layer extends up.Record {
4632
4626
  if (this.savedMetaTags) {
4633
4627
  up.history.updateMetaTags(this.savedMetaTags);
4634
4628
  }
4629
+ if (u.isString(this.savedLang)) {
4630
+ up.history.updateLang(this.savedLang);
4631
+ }
4635
4632
  }
4636
4633
  asCurrent(fn) {
4637
4634
  return this.stack.asCurrent(this, fn);
@@ -4648,6 +4645,9 @@ up.Layer = class Layer extends up.Record {
4648
4645
  if (u.isString(options.title)) {
4649
4646
  this.title = options.title;
4650
4647
  }
4648
+ if (u.isString(options.lang)) {
4649
+ this.lang = options.lang;
4650
+ }
4651
4651
  }
4652
4652
  showsLiveHistory() {
4653
4653
  return this.history && this.isFront();
@@ -4680,6 +4680,20 @@ up.Layer = class Layer extends up.Record {
4680
4680
  up.history.updateMetaTags(metaTags);
4681
4681
  }
4682
4682
  }
4683
+ get lang() {
4684
+ if (this.showsLiveHistory()) {
4685
+ return up.history.getLang();
4686
+ }
4687
+ else {
4688
+ return this.savedLang;
4689
+ }
4690
+ }
4691
+ set lang(lang) {
4692
+ this.savedLang = lang;
4693
+ if (this.showsLiveHistory()) {
4694
+ up.history.updateLang(lang);
4695
+ }
4696
+ }
4683
4697
  get location() {
4684
4698
  if (this.showsLiveHistory()) {
4685
4699
  return up.history.location;
@@ -5408,7 +5422,10 @@ up.LinkFeedbackURLs = class LinkFeedbackURLs {
5408
5422
  }
5409
5423
  isCurrent(normalizedLocation) {
5410
5424
  var _a, _b;
5411
- return this._isSafe && !!(this.href === normalizedLocation ||
5425
+ if (!normalizedLocation) {
5426
+ return false;
5427
+ }
5428
+ return !!(this.href === normalizedLocation ||
5412
5429
  this._upHREF === normalizedLocation ||
5413
5430
  ((_b = (_a = this._aliasPattern) === null || _a === void 0 ? void 0 : _a.test) === null || _b === void 0 ? void 0 : _b.call(_a, normalizedLocation, false)));
5414
5431
  }
@@ -5421,62 +5438,41 @@ up.LinkFeedbackURLs = class LinkFeedbackURLs {
5421
5438
 
5422
5439
  const u = up.util;
5423
5440
  const e = up.element;
5424
- up.LinkPreloader = class LinkPreloader {
5425
- watchLink(link) {
5426
- if (!up.link.preloadIssue(link)) {
5427
- this._on(link, 'mouseenter', (event) => this._considerPreload(event, true));
5428
- this._on(link, 'mousedown touchstart', (event) => this._considerPreload(event));
5429
- this._on(link, 'mouseleave', (event) => this._stopPreload(event));
5430
- }
5431
- }
5432
- _on(link, eventTypes, callback) {
5433
- up.on(link, eventTypes, { passive: true }, callback);
5434
- }
5435
- _considerPreload(event, applyDelay) {
5436
- const link = event.target;
5437
- if (link !== this._currentLink) {
5438
- this.reset();
5439
- this._currentLink = link;
5440
- if (up.link.shouldFollowEvent(event, link)) {
5441
- if (applyDelay) {
5442
- this._preloadAfterDelay(event, link);
5443
- }
5444
- else {
5445
- this._preloadNow(event, link);
5446
- }
5447
- }
5448
- }
5441
+ up.LinkFollowIntent = class LinkFollowIntent {
5442
+ constructor(link, callback) {
5443
+ this._link = link;
5444
+ this._callback = callback;
5445
+ this._on('mouseenter mousedown touchstart', (event) => this._scheduleCallback(event));
5446
+ this._on('mouseleave', () => this._unscheduleCallback());
5447
+ up.fragment.onAborted(this._link, () => this._unscheduleCallback());
5449
5448
  }
5450
- _stopPreload(event) {
5451
- if (event.target === this._currentLink) {
5452
- return this.reset();
5453
- }
5449
+ _on(eventType, callback) {
5450
+ up.on(this._link, eventType, { passive: true }, callback);
5454
5451
  }
5455
- reset() {
5456
- var _a;
5457
- if (!this._currentLink) {
5452
+ _scheduleCallback(event) {
5453
+ if (!up.link.shouldFollowEvent(event, this._link))
5458
5454
  return;
5455
+ this._unscheduleCallback();
5456
+ const applyDelay = (event.type === 'mouseenter');
5457
+ if (applyDelay) {
5458
+ let delay = this._parseDelay();
5459
+ this._timer = u.timer(delay, () => this._runCallback(event));
5459
5460
  }
5460
- clearTimeout(this._timer);
5461
- if ((_a = this._currentRequest) === null || _a === void 0 ? void 0 : _a.background) {
5462
- this._currentRequest.abort();
5461
+ else {
5462
+ this._runCallback(event);
5463
5463
  }
5464
- this._currentLink = undefined;
5465
- this._currentRequest = undefined;
5466
5464
  }
5467
- _preloadAfterDelay(event, link) {
5465
+ _unscheduleCallback() {
5466
+ clearTimeout(this._timer);
5467
+ up.network.abort((request) => (request.origin === this._link) && request.background);
5468
+ }
5469
+ _parseDelay() {
5468
5470
  var _a;
5469
- const delay = (_a = e.numberAttr(link, 'up-preload-delay')) !== null && _a !== void 0 ? _a : up.link.config.preloadDelay;
5470
- this._timer = u.timer(delay, () => this._preloadNow(event, link));
5471
+ return (_a = e.numberAttr(this._link, 'up-preload-delay')) !== null && _a !== void 0 ? _a : up.link.config.preloadDelay;
5471
5472
  }
5472
- _preloadNow(event, link) {
5473
- if (!link.isConnected) {
5474
- this.reset();
5475
- return;
5476
- }
5477
- const onQueued = request => { return this._currentRequest = request; };
5473
+ _runCallback(event) {
5478
5474
  up.log.putsEvent(event);
5479
- up.error.muteUncriticalRejection(up.link.preload(link, { onQueued }));
5475
+ up.error.muteUncriticalRejection(this._callback());
5480
5476
  }
5481
5477
  };
5482
5478
 
@@ -6236,7 +6232,6 @@ up.Request = (_a = class Request extends up.Record {
6236
6232
  'wrapMethod',
6237
6233
  'contentType',
6238
6234
  'payload',
6239
- 'onQueued',
6240
6235
  'onLoading',
6241
6236
  'fail',
6242
6237
  'abortable',
@@ -6271,7 +6266,7 @@ up.Request = (_a = class Request extends up.Record {
6271
6266
  }
6272
6267
  this.deferred = u.newDeferred();
6273
6268
  (_d = this.badResponseTime) !== null && _d !== void 0 ? _d : (this.badResponseTime = u.evalOption(up.network.config.badResponseTime, this));
6274
- this._addAutoHeaders();
6269
+ this._setAutoHeaders();
6275
6270
  }
6276
6271
  get xhr() {
6277
6272
  var _b;
@@ -6281,7 +6276,7 @@ up.Request = (_a = class Request extends up.Record {
6281
6276
  if (this._fragments) {
6282
6277
  return this._fragments;
6283
6278
  }
6284
- else if (this.target) {
6279
+ else {
6285
6280
  let steps = up.fragment.parseTargetSteps(this.target);
6286
6281
  let selectors = u.map(steps, 'selector');
6287
6282
  let lookupOpts = { origin: this.origin, layer: this.layer };
@@ -6337,9 +6332,7 @@ up.Request = (_a = class Request extends up.Record {
6337
6332
  return u.evalAutoOption(this.cache, up.network.config.autoCache, this);
6338
6333
  }
6339
6334
  runQueuedCallbacks() {
6340
- var _b;
6341
6335
  u.always(this, () => this._evictExpensiveAttrs());
6342
- (_b = this.onQueued) === null || _b === void 0 ? void 0 : _b.call(this, this);
6343
6336
  }
6344
6337
  load() {
6345
6338
  var _b;
@@ -6484,9 +6477,6 @@ up.Request = (_a = class Request extends up.Record {
6484
6477
  return this.method + ' ' + this.url;
6485
6478
  }
6486
6479
  isPartOfSubtree(subtreeElements) {
6487
- if (!this.fragments || !subtreeElements) {
6488
- return false;
6489
- }
6490
6480
  subtreeElements = u.wrapList(subtreeElements);
6491
6481
  return u.some(this.fragments, function (fragment) {
6492
6482
  return u.some(subtreeElements, (subtreeElement) => subtreeElement.contains(fragment));
@@ -6498,17 +6488,20 @@ up.Request = (_a = class Request extends up.Record {
6498
6488
  header(name) {
6499
6489
  return this.headers[name];
6500
6490
  }
6501
- _addAutoHeaders() {
6491
+ _setAutoHeaders() {
6502
6492
  for (let key of ['target', 'failTarget', 'mode', 'failMode', 'context', 'failContext']) {
6503
- this._addAutoHeader(up.protocol.headerize(key), this[key]);
6493
+ this._setPropertyHeader(key);
6504
6494
  }
6505
6495
  let csrfHeader, csrfToken;
6506
6496
  if ((csrfHeader = this.csrfHeader()) && (csrfToken = this.csrfToken())) {
6507
- this._addAutoHeader(csrfHeader, csrfToken);
6497
+ this._setAutoHeader(csrfHeader, csrfToken);
6508
6498
  }
6509
- this._addAutoHeader(up.protocol.headerize('version'), up.version);
6499
+ this._setAutoHeader(up.protocol.headerize('version'), up.version);
6500
+ }
6501
+ _setPropertyHeader(key) {
6502
+ this._setAutoHeader(up.protocol.headerize(key), this[key]);
6510
6503
  }
6511
- _addAutoHeader(name, value) {
6504
+ _setAutoHeader(name, value) {
6512
6505
  if (u.isMissing(value)) {
6513
6506
  return;
6514
6507
  }
@@ -6517,6 +6510,16 @@ up.Request = (_a = class Request extends up.Record {
6517
6510
  }
6518
6511
  this.headers[name] = value;
6519
6512
  }
6513
+ mergeIfUnsent(trackingRequest) {
6514
+ if (this.state !== 'new')
6515
+ return;
6516
+ if (!this.target || !trackingRequest.target)
6517
+ return;
6518
+ let targetAtoms = up.fragment.splitTarget(this.target + ',' + trackingRequest.target);
6519
+ this.target = u.uniq(targetAtoms).join(', ');
6520
+ this._setPropertyHeader('target');
6521
+ this._fragments = u.uniq([...this.fragments, ...trackingRequest.fragments]);
6522
+ }
6520
6523
  static tester(condition, { except } = {}) {
6521
6524
  let testFn;
6522
6525
  if (u.isFunction(condition)) {
@@ -6560,78 +6563,85 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
6560
6563
  });
6561
6564
  };
6562
6565
  const u = up.util;
6566
+ class Route {
6567
+ constructor() {
6568
+ this.varyHeaders = new Set();
6569
+ this.requests = [];
6570
+ }
6571
+ matchBest(newRequest) {
6572
+ let matches = this.requests.filter((cachedRequest) => this.satisfies(cachedRequest, newRequest));
6573
+ return u.last(matches);
6574
+ }
6575
+ delete(request) {
6576
+ u.remove(this.requests, request);
6577
+ }
6578
+ put(request) {
6579
+ this.requests.push(request);
6580
+ }
6581
+ updateVary(response) {
6582
+ for (let headerName of response.varyHeaderNames) {
6583
+ this.varyHeaders.add(headerName);
6584
+ }
6585
+ }
6586
+ satisfies(cachedRequest, newRequest) {
6587
+ if (cachedRequest === newRequest)
6588
+ return true;
6589
+ return u.every(this.varyHeaders, (varyHeader) => {
6590
+ let cachedValue = cachedRequest.header(varyHeader);
6591
+ let newValue = newRequest.header(varyHeader);
6592
+ if (varyHeader === 'X-Up-Target' || varyHeader === 'X-Up-Fail-Target') {
6593
+ if (!cachedValue)
6594
+ return true;
6595
+ if (!newValue)
6596
+ return false;
6597
+ let cachedTokens = u.parseTokens(cachedValue, { separator: 'comma' });
6598
+ let newTokens = u.parseTokens(newValue, { separator: 'comma' });
6599
+ return u.containsAll(cachedTokens, newTokens);
6600
+ }
6601
+ else {
6602
+ return cachedValue === newValue;
6603
+ }
6604
+ });
6605
+ }
6606
+ }
6563
6607
  up.Request.Cache = class Cache {
6564
6608
  constructor() {
6565
6609
  this.reset();
6566
6610
  }
6567
6611
  reset() {
6568
- this._varyInfo = {};
6569
- this._map = new Map();
6570
- }
6571
- _cacheKey(request) {
6572
- let influencingHeaders = this._getPreviousInfluencingHeaders(request);
6573
- let varyPart = u.flatMap(influencingHeaders, (headerName) => [headerName, request.header(headerName)]);
6574
- return [request.description, ...varyPart].join(':');
6575
- }
6576
- _getPreviousInfluencingHeaders(request) {
6577
- var _a, _b;
6578
- return ((_a = this._varyInfo)[_b = request.description] || (_a[_b] = new Set()));
6612
+ this._routes = {};
6613
+ this._requests = [];
6579
6614
  }
6580
6615
  get(request) {
6581
6616
  request = this._wrap(request);
6582
- let cacheKey = this._cacheKey(request);
6583
- let cachedRequest = this._map.get(cacheKey);
6617
+ let route = this._getRoute(request);
6618
+ let cachedRequest = route.matchBest(request);
6584
6619
  if (cachedRequest) {
6585
6620
  if (this._isUsable(cachedRequest)) {
6586
6621
  return cachedRequest;
6587
6622
  }
6588
6623
  else {
6589
- this._map.delete(cacheKey);
6624
+ this._delete(request, route);
6590
6625
  }
6591
6626
  }
6592
6627
  }
6593
- get _capacity() {
6594
- return up.network.config.cacheSize;
6595
- }
6596
- _isUsable(request) {
6597
- return request.age < up.network.config.cacheEvictAge;
6598
- }
6599
6628
  put(request) {
6600
6629
  return __awaiter(this, void 0, void 0, function* () {
6601
6630
  request = this._wrap(request);
6602
- this._makeRoom();
6603
- let cacheKey = this._updateCacheKey(request);
6604
- this._map.set(cacheKey, request);
6631
+ let route = this._getRoute(request);
6632
+ let { response } = request;
6633
+ if (response)
6634
+ route.updateVary(response);
6635
+ let superseded = route.requests.filter((oldRequest) => route.satisfies(request, oldRequest));
6636
+ for (let r of superseded) {
6637
+ this._delete(r);
6638
+ }
6639
+ request.cacheRoute = route;
6640
+ route.put(request);
6641
+ this._requests.push(request);
6642
+ this._limitSize();
6605
6643
  });
6606
6644
  }
6607
- _updateCacheKey(request) {
6608
- let oldCacheKey = this._cacheKey(request);
6609
- let { response } = request;
6610
- if (response) {
6611
- this._mergePreviousHeaderNames(request, response);
6612
- let newCacheKey = this._cacheKey(request);
6613
- this._renameMapKey(oldCacheKey, newCacheKey);
6614
- return newCacheKey;
6615
- }
6616
- else {
6617
- return oldCacheKey;
6618
- }
6619
- }
6620
- _renameMapKey(oldKey, newKey) {
6621
- if (oldKey !== newKey && this._map.has(oldKey)) {
6622
- this._map.set(newKey, this._map.get(oldKey));
6623
- this._map.delete(oldKey);
6624
- }
6625
- }
6626
- _mergePreviousHeaderNames(request, response) {
6627
- let headersInfluencingResponse = response.ownInfluncingHeaders;
6628
- if (headersInfluencingResponse.length) {
6629
- let previousInfluencingHeaders = this._getPreviousInfluencingHeaders(request);
6630
- for (let headerName of headersInfluencingResponse) {
6631
- previousInfluencingHeaders.add(headerName);
6632
- }
6633
- }
6634
- }
6635
6645
  alias(existingCachedRequest, newRequest) {
6636
6646
  existingCachedRequest = this.get(existingCachedRequest);
6637
6647
  if (!existingCachedRequest)
@@ -6648,7 +6658,7 @@ up.Request.Cache = class Cache {
6648
6658
  newRequest.state = 'tracking';
6649
6659
  let value = yield u.always(existingRequest);
6650
6660
  if (value instanceof up.Response) {
6651
- if (options.force || this._isCacheCompatible(existingRequest, newRequest)) {
6661
+ if (options.force || existingRequest.cacheRoute.satisfies(existingRequest, newRequest)) {
6652
6662
  newRequest.fromCache = true;
6653
6663
  value = u.variant(value, { request: newRequest });
6654
6664
  newRequest.respondWith(value);
@@ -6669,31 +6679,45 @@ up.Request.Cache = class Cache {
6669
6679
  willHaveSameResponse(existingRequest, newRequest) {
6670
6680
  return existingRequest === newRequest || existingRequest === newRequest.trackedRequest;
6671
6681
  }
6672
- _delete(request) {
6673
- request = this._wrap(request);
6674
- let cacheKey = this._cacheKey(request);
6675
- this._map.delete(cacheKey);
6676
- }
6677
6682
  evict(condition = true, testerOptions) {
6678
6683
  this._eachMatch(condition, testerOptions, (request) => this._delete(request));
6679
6684
  }
6680
6685
  expire(condition = true, testerOptions) {
6681
6686
  this._eachMatch(condition, testerOptions, (request) => request.expired = true);
6682
6687
  }
6683
- _makeRoom() {
6684
- while (this._map.size >= this._capacity) {
6685
- let oldestKey = this._map.keys().next().value;
6686
- this._map.delete(oldestKey);
6688
+ reindex(request) {
6689
+ this._delete(request);
6690
+ this.put(request);
6691
+ }
6692
+ _delete(request) {
6693
+ var _a;
6694
+ u.remove(this._requests, request);
6695
+ (_a = request.cacheRoute) === null || _a === void 0 ? void 0 : _a.delete(request);
6696
+ delete request.cacheRoute;
6697
+ }
6698
+ _getRoute(request) {
6699
+ var _a, _b;
6700
+ return request.cacheRoute || ((_a = this._routes)[_b = request.description] || (_a[_b] = new Route()));
6701
+ }
6702
+ _isUsable(request) {
6703
+ return request.age < up.network.config.cacheEvictAge;
6704
+ }
6705
+ get _size() {
6706
+ return this._requests.length;
6707
+ }
6708
+ get _capacity() {
6709
+ return up.network.config.cacheSize;
6710
+ }
6711
+ _limitSize() {
6712
+ for (let i = 0; i < (this._size - this._capacity); i++) {
6713
+ this._delete(this._requests[0]);
6687
6714
  }
6688
6715
  }
6689
6716
  _eachMatch(condition = true, testerOptions, fn) {
6690
6717
  let tester = up.Request.tester(condition, testerOptions);
6691
- let results = u.filter(this._map.values(), tester);
6718
+ let results = u.filter(this._requests, tester);
6692
6719
  u.each(results, fn);
6693
6720
  }
6694
- _isCacheCompatible(request1, request2) {
6695
- return this._cacheKey(request1) === this._cacheKey(request2);
6696
- }
6697
6721
  _wrap(requestOrOptions) {
6698
6722
  return u.wrapValue(up.Request, requestOrOptions);
6699
6723
  }
@@ -6722,7 +6746,7 @@ up.Request.Queue = class Queue {
6722
6746
  u.always(request, responseOrError => this._onRequestSettled(request, responseOrError));
6723
6747
  this._scheduleSlowTimer(request);
6724
6748
  this._queueRequest(request);
6725
- u.microtask(() => this._poke());
6749
+ queueMicrotask(() => this._poke());
6726
6750
  }
6727
6751
  promoteToForeground(request) {
6728
6752
  if (request.background) {
@@ -6763,7 +6787,7 @@ up.Request.Queue = class Queue {
6763
6787
  up.network.registerAliasForRedirect(request, responseOrError);
6764
6788
  }
6765
6789
  this._checkLate();
6766
- u.microtask(() => this._poke());
6790
+ queueMicrotask(() => this._poke());
6767
6791
  }
6768
6792
  _poke() {
6769
6793
  let request;
@@ -6959,16 +6983,13 @@ up.Response = class Response extends up.Record {
6959
6983
  get none() {
6960
6984
  return !this.text;
6961
6985
  }
6962
- isCacheable() {
6963
- return this.ok && !this.none;
6964
- }
6965
6986
  header(name) {
6966
6987
  var _a;
6967
6988
  return this.headers[name] || ((_a = this.xhr) === null || _a === void 0 ? void 0 : _a.getResponseHeader(name));
6968
6989
  }
6969
- get ownInfluncingHeaders() {
6970
- let influencingHeaders = up.protocol.influencingHeadersFromResponse(this);
6971
- return u.filter(influencingHeaders, (headerName) => this.request.header(headerName));
6990
+ get varyHeaderNames() {
6991
+ let varyHeaderValue = this.header('Vary');
6992
+ return u.parseTokens(varyHeaderValue, { separator: 'comma' });
6972
6993
  }
6973
6994
  get contentType() {
6974
6995
  return this.header('Content-Type');
@@ -7009,6 +7030,7 @@ up.Response = class Response extends up.Record {
7009
7030
  var _a;
7010
7031
  const u = up.util;
7011
7032
  const e = up.element;
7033
+ const FULL_DOCUMENT_PATTERN = /^\s*<(html|!DOCTYPE)\b/i;
7012
7034
  up.ResponseDoc = (_a = class ResponseDoc {
7013
7035
  constructor({ document, fragment, content, target, origin, cspNonces, match }) {
7014
7036
  if (document) {
@@ -7029,43 +7051,43 @@ up.ResponseDoc = (_a = class ResponseDoc {
7029
7051
  }
7030
7052
  this._match = match;
7031
7053
  }
7032
- _parseDocument(document) {
7033
- document = this._parse(document, e.createBrokenDocumentFromHTML);
7034
- this._isDocumentBroken = true;
7035
- this._useParseResult(document);
7036
- }
7037
- _parseFragment(fragment) {
7038
- fragment = this._parse(fragment, e.createFromHTML);
7039
- this._useParseResult(fragment);
7040
- }
7041
- _parseContent(content, target) {
7042
- if (!target)
7043
- up.fail("must pass a { target } when passing { content }");
7044
- target = u.map(up.fragment.parseTargetSteps(target), 'selector').join();
7045
- const matchingElement = e.createFromSelector(target);
7046
- if (u.isString(content)) {
7047
- matchingElement.innerHTML = content;
7054
+ _parseDocument(value) {
7055
+ if (value instanceof Document) {
7056
+ this._document = value;
7057
+ this._isFullDocument = true;
7058
+ }
7059
+ else if (u.isString(value)) {
7060
+ this._document = e.createBrokenDocumentFromHTML(value);
7061
+ this._isFullDocument = FULL_DOCUMENT_PATTERN.test(value);
7062
+ this._isDocumentBroken = true;
7048
7063
  }
7049
7064
  else {
7050
- matchingElement.appendChild(content);
7065
+ this._document = this._buildFauxDocument(value);
7066
+ this._isFullDocument = value.matches('html');
7051
7067
  }
7052
- this._useParseResult(matchingElement);
7053
7068
  }
7054
- _parse(value, parseFn) {
7055
- if (u.isString(value)) {
7056
- value = parseFn(value);
7057
- }
7058
- return value;
7069
+ _parseFragment(value) {
7070
+ let parsed = u.isString(value) ? e.createFromHTML(value) : value;
7071
+ this._document = this._buildFauxDocument(parsed);
7059
7072
  }
7060
- _useParseResult(node) {
7061
- if (node instanceof Document) {
7062
- this._document = node;
7073
+ _parseContent(value, target) {
7074
+ if (!target)
7075
+ up.fail("must pass a { target } when passing { content }");
7076
+ let simplifiedTarget = u.map(up.fragment.parseTargetSteps(target), 'selector').join();
7077
+ const matchingElement = e.createFromSelector(simplifiedTarget);
7078
+ if (u.isString(value)) {
7079
+ matchingElement.innerHTML = value;
7063
7080
  }
7064
7081
  else {
7065
- this._document = document.createElement('up-document');
7066
- this._document.append(node);
7067
- this._document.documentElement = node;
7082
+ matchingElement.appendChild(value);
7068
7083
  }
7084
+ this._document = this._buildFauxDocument(matchingElement);
7085
+ }
7086
+ _buildFauxDocument(node) {
7087
+ let fauxDocument = document.createElement('up-document');
7088
+ fauxDocument.append(node);
7089
+ fauxDocument.documentElement = node;
7090
+ return fauxDocument;
7069
7091
  }
7070
7092
  rootSelector() {
7071
7093
  return up.fragment.toTarget(this._document.documentElement);
@@ -7074,9 +7096,8 @@ up.ResponseDoc = (_a = class ResponseDoc {
7074
7096
  return this._fromHead(this._getTitleText);
7075
7097
  }
7076
7098
  _getHead() {
7077
- let { head } = this._document;
7078
- if (head && head.childNodes.length > 0) {
7079
- return head;
7099
+ if (this._isFullDocument) {
7100
+ return this._document.head;
7080
7101
  }
7081
7102
  }
7082
7103
  _fromHead(fn) {
@@ -7089,6 +7110,11 @@ up.ResponseDoc = (_a = class ResponseDoc {
7089
7110
  get assets() {
7090
7111
  return this._fromHead(up.script.findAssets);
7091
7112
  }
7113
+ get lang() {
7114
+ if (this._isFullDocument) {
7115
+ return up.history.getLang(this._document);
7116
+ }
7117
+ }
7092
7118
  _getTitleText(head) {
7093
7119
  var _b;
7094
7120
  return (_b = head.querySelector('title')) === null || _b === void 0 ? void 0 : _b.textContent;
@@ -7188,7 +7214,7 @@ up.RevealMotion = class RevealMotion {
7188
7214
  const maxPixels = u.evalOption(this._max, this._element);
7189
7215
  elementRect.height = Math.min(elementRect.height, maxPixels);
7190
7216
  }
7191
- this._addPadding(elementRect);
7217
+ elementRect.grow(this._padding);
7192
7218
  this._substractObstructions(viewportRect);
7193
7219
  if (viewportRect.height < 0) {
7194
7220
  up.fail('Viewport has no visible area');
@@ -7227,10 +7253,6 @@ up.RevealMotion = class RevealMotion {
7227
7253
  return up.Rect.fromElement(this._viewport);
7228
7254
  }
7229
7255
  }
7230
- _addPadding(elementRect) {
7231
- elementRect.top -= this._padding;
7232
- elementRect.height += 2 * this._padding;
7233
- }
7234
7256
  _selectObstructions(selector) {
7235
7257
  let elements = up.fragment.all(selector, { layer: this._obstructionsLayer });
7236
7258
  return u.filter(elements, e.isVisible);
@@ -7783,10 +7805,6 @@ up.protocol = (function () {
7783
7805
  function locationFromXHR(xhr) {
7784
7806
  return extractHeader(xhr, 'location') || xhr.responseURL;
7785
7807
  }
7786
- function influencingHeadersFromResponse(response) {
7787
- let varyHeaderValue = response.header('Vary');
7788
- return u.parseTokens(varyHeaderValue, { separator: 'comma' });
7789
- }
7790
7808
  const config = new up.Config(() => ({
7791
7809
  methodParam: '_method',
7792
7810
  csrfParam() { return e.metaContent('csrf-param'); },
@@ -7847,7 +7865,6 @@ up.protocol = (function () {
7847
7865
  headerize,
7848
7866
  wrapMethod,
7849
7867
  cspNoncesFromHeader,
7850
- influencingHeadersFromResponse,
7851
7868
  };
7852
7869
  })();
7853
7870
 
@@ -7983,44 +8000,61 @@ up.script = (function () {
7983
8000
  let registeredCompilers = [];
7984
8001
  let registeredMacros = [];
7985
8002
  function registerCompiler(...args) {
7986
- const compiler = buildCompiler(args);
7987
- return insertCompiler(registeredCompilers, compiler);
8003
+ registerProcessor(args);
7988
8004
  }
7989
8005
  function registerMacro(...args) {
7990
- const macro = buildCompiler(args);
7991
- if (up.framework.evaling) {
7992
- macro.priority || (macro.priority = detectSystemMacroPriority(macro.selector) ||
7993
- up.fail('Unregistered priority for system macro %o', macro.selector));
7994
- }
7995
- return insertCompiler(registeredMacros, macro);
8006
+ registerProcessor(args, { macro: true });
8007
+ }
8008
+ function registerAttrCompiler(...args) {
8009
+ let [attr, options, valueCallback] = parseProcessorArgs(args);
8010
+ let selector = `[${attr}]`;
8011
+ let callback = (element) => {
8012
+ let value = e.booleanOrStringAttr(element, attr, options.defaultValue);
8013
+ if (!value)
8014
+ return;
8015
+ return valueCallback(element, value);
8016
+ };
8017
+ registerProcessor([selector, options, callback]);
7996
8018
  }
7997
8019
  function detectSystemMacroPriority(macroSelector) {
7998
8020
  macroSelector = u.evalOption(macroSelector);
7999
8021
  for (let substr in SYSTEM_MACRO_PRIORITIES) {
8000
- const priority = SYSTEM_MACRO_PRIORITIES[substr];
8001
8022
  if (macroSelector.indexOf(substr) >= 0) {
8002
- return priority;
8023
+ return SYSTEM_MACRO_PRIORITIES[substr];
8024
+ }
8025
+ }
8026
+ up.fail('Unregistered priority for system macro %o', macroSelector);
8027
+ }
8028
+ function registerProcessor(args, overrides = {}) {
8029
+ let processor = buildProcessor(args, overrides);
8030
+ if (processor.macro) {
8031
+ if (up.framework.evaling) {
8032
+ processor.priority || (processor.priority = detectSystemMacroPriority(processor.selector));
8003
8033
  }
8034
+ insertProcessor(registeredMacros, processor);
8035
+ }
8036
+ else {
8037
+ insertProcessor(registeredCompilers, processor);
8004
8038
  }
8005
8039
  }
8006
- const parseCompilerArgs = function (args) {
8040
+ const parseProcessorArgs = function (args) {
8007
8041
  const defaults = u.extractOptions(args);
8008
8042
  const selector = args.shift();
8009
8043
  const callback = args.pop();
8010
8044
  const options = Object.assign(Object.assign({}, defaults), u.extractOptions(args));
8011
8045
  return [selector, options, callback];
8012
8046
  };
8013
- function buildCompiler(args) {
8014
- let [selector, options, callback] = parseCompilerArgs(args);
8047
+ function buildProcessor(args, overrides) {
8048
+ let [selector, options, callback] = parseProcessorArgs(args);
8015
8049
  options = u.options(options, {
8016
8050
  selector,
8017
8051
  isDefault: up.framework.evaling,
8018
8052
  priority: 0,
8019
8053
  batch: false,
8020
8054
  });
8021
- return Object.assign(callback, options);
8055
+ return Object.assign(callback, options, overrides);
8022
8056
  }
8023
- function insertCompiler(queue, newCompiler) {
8057
+ function insertProcessor(queue, newCompiler) {
8024
8058
  let existingCompiler;
8025
8059
  let index = 0;
8026
8060
  while ((existingCompiler = queue[index]) && (existingCompiler.priority >= newCompiler.priority)) {
@@ -8114,6 +8148,7 @@ up.script = (function () {
8114
8148
  config,
8115
8149
  compiler: registerCompiler,
8116
8150
  macro: registerMacro,
8151
+ attrCompiler: registerAttrCompiler,
8117
8152
  destructor: registerDestructor,
8118
8153
  hello,
8119
8154
  clean,
@@ -8128,6 +8163,7 @@ up.destructor = up.script.destructor;
8128
8163
  up.macro = up.script.macro;
8129
8164
  up.data = up.script.data;
8130
8165
  up.hello = up.script.hello;
8166
+ up.attribute = up.script.attrCompiler;
8131
8167
 
8132
8168
 
8133
8169
  /***/ }),
@@ -8270,6 +8306,15 @@ up.history = (function () {
8270
8306
  document.head.append(newMetaTag);
8271
8307
  }
8272
8308
  }
8309
+ function getLang(doc = document) {
8310
+ let { documentElement } = doc;
8311
+ if (documentElement.matches('html')) {
8312
+ return doc.documentElement.lang;
8313
+ }
8314
+ }
8315
+ function updateLang(newLang) {
8316
+ e.toggleAttr(e.root, 'lang', newLang, !!newLang);
8317
+ }
8273
8318
  up.macro('a[up-back], [up-href][up-back]', function (link) {
8274
8319
  if (previousLocation) {
8275
8320
  e.setMissingAttrs(link, {
@@ -8291,6 +8336,8 @@ up.history = (function () {
8291
8336
  isLocation,
8292
8337
  findMetaTags,
8293
8338
  updateMetaTags,
8339
+ getLang,
8340
+ updateLang,
8294
8341
  };
8295
8342
  })();
8296
8343
 
@@ -8773,6 +8820,25 @@ up.fragment = (function () {
8773
8820
  up.destructor(fragment, unsubscribe);
8774
8821
  return unsubscribe;
8775
8822
  }
8823
+ function onFirstIntersect(origin, callback, { margin = 0 } = {}) {
8824
+ if (e.isIntersectingWindow(origin, { margin })) {
8825
+ callback();
8826
+ return;
8827
+ }
8828
+ function processIntersectEntries(entries) {
8829
+ for (let entry of entries) {
8830
+ if (entry.isIntersecting) {
8831
+ disconnect();
8832
+ callback();
8833
+ return;
8834
+ }
8835
+ }
8836
+ }
8837
+ let observer = new IntersectionObserver(processIntersectEntries, { rootMargin: `${margin}px` });
8838
+ let disconnect = () => observer.disconnect();
8839
+ observer.observe(origin);
8840
+ onAborted(origin, disconnect);
8841
+ }
8776
8842
  up.on('up:framework:boot', function () {
8777
8843
  const { documentElement } = document;
8778
8844
  documentElement.setAttribute('up-source', u.normalizeURL(location.href, { hash: false }));
@@ -8813,6 +8879,7 @@ up.fragment = (function () {
8813
8879
  shouldRevalidate,
8814
8880
  abort,
8815
8881
  onAborted,
8882
+ onFirstIntersect,
8816
8883
  splitTarget,
8817
8884
  parseTargetSteps,
8818
8885
  isAlive,
@@ -8942,33 +9009,9 @@ up.viewport = (function () {
8942
9009
  function isRoot(element) {
8943
9010
  return element === getRoot();
8944
9011
  }
8945
- function rootHasReducedWidthFromScrollbar() {
8946
- return window.innerWidth > document.documentElement.offsetWidth;
8947
- }
8948
- function rootOverflowElement() {
8949
- const { body } = document;
8950
- const html = document.documentElement;
8951
- const element = u.find([html, body], wasChosenAsOverflowingElement);
8952
- return element || getRoot();
8953
- }
8954
- function wasChosenAsOverflowingElement(element) {
8955
- const overflowY = e.style(element, 'overflow-y');
8956
- return overflowY === 'auto' || overflowY === 'scroll';
8957
- }
8958
- const scrollbarWidth = u.memoize(function () {
8959
- const outerStyle = {
8960
- position: 'absolute',
8961
- top: '0',
8962
- left: '0',
8963
- width: '100px',
8964
- height: '100px',
8965
- overflowY: 'scroll'
8966
- };
8967
- const outer = up.element.affix(document.body, '[up-viewport]', { style: outerStyle });
8968
- const width = outer.offsetWidth - outer.clientWidth;
8969
- outer.remove();
8970
- return width;
8971
- });
9012
+ function rootScrollbarWidth() {
9013
+ return window.innerWidth - rootWidth();
9014
+ }
8972
9015
  function scrollTopKey(viewport) {
8973
9016
  return up.fragment.tryToTarget(viewport);
8974
9017
  }
@@ -9146,10 +9189,8 @@ up.viewport = (function () {
9146
9189
  get root() { return getRoot(); },
9147
9190
  rootWidth,
9148
9191
  rootHeight,
9149
- rootHasReducedWidthFromScrollbar,
9150
- rootOverflowElement,
9151
9192
  isRoot,
9152
- scrollbarWidth,
9193
+ rootScrollbarWidth,
9153
9194
  saveScroll,
9154
9195
  restoreScroll,
9155
9196
  resetScroll,
@@ -9239,8 +9280,9 @@ up.motion = (function () {
9239
9280
  return cssTransition.start();
9240
9281
  }
9241
9282
  function applyConfig(options) {
9242
- options.easing || (options.easing = config.easing);
9243
- options.duration || (options.duration = config.duration);
9283
+ var _a, _b;
9284
+ (_a = options.easing) !== null && _a !== void 0 ? _a : (options.easing = config.easing);
9285
+ (_b = options.duration) !== null && _b !== void 0 ? _b : (options.duration = config.duration);
9244
9286
  }
9245
9287
  function findNamedAnimation(name) {
9246
9288
  return namedAnimations[name] || up.fail("Unknown animation %o", name);
@@ -9510,6 +9552,7 @@ up.network = (function () {
9510
9552
  if (!newRequest.background) {
9511
9553
  queue.promoteToForeground(cachedRequest);
9512
9554
  }
9555
+ cachedRequest.mergeIfUnsent(newRequest);
9513
9556
  cache.track(cachedRequest, newRequest, { onIncompatible: processRequest });
9514
9557
  return true;
9515
9558
  }
@@ -9522,10 +9565,10 @@ up.network = (function () {
9522
9565
  function handleCaching(request) {
9523
9566
  if (request.willCache()) {
9524
9567
  cache.put(request);
9525
- request.onLoading = () => cache.put(request);
9568
+ request.onLoading = () => cache.reindex(request);
9526
9569
  }
9527
9570
  u.always(request, function (responseOrError) {
9528
- var _a, _b, _c, _d, _e;
9571
+ var _a, _b, _c, _d;
9529
9572
  let expireCache = (_b = (_a = responseOrError.expireCache) !== null && _a !== void 0 ? _a : request.expireCache) !== null && _b !== void 0 ? _b : u.evalOption(config.expireCache, request, responseOrError);
9530
9573
  if (expireCache) {
9531
9574
  cache.expire(expireCache, { except: request });
@@ -9534,12 +9577,21 @@ up.network = (function () {
9534
9577
  if (evictCache) {
9535
9578
  cache.evict(evictCache, { except: request });
9536
9579
  }
9537
- if (cache.get(request)) {
9538
- cache.put(request);
9580
+ let hasCacheEntry = cache.get(request);
9581
+ let isResponse = responseOrError instanceof up.Response;
9582
+ let isNetworkError = !isResponse;
9583
+ let isSuccessResponse = isResponse && responseOrError.ok;
9584
+ let isErrorResponse = isResponse && !responseOrError.ok;
9585
+ let isEmptyResponse = isResponse && responseOrError.none;
9586
+ if (isErrorResponse) {
9587
+ cache.evict(request.url);
9539
9588
  }
9540
- if (!((_e = responseOrError.isCacheable) === null || _e === void 0 ? void 0 : _e.call(responseOrError))) {
9589
+ else if (isNetworkError || isEmptyResponse) {
9541
9590
  cache.evict(request);
9542
9591
  }
9592
+ else if (isSuccessResponse && hasCacheEntry) {
9593
+ cache.put(request);
9594
+ }
9543
9595
  });
9544
9596
  }
9545
9597
  function isBusy() {
@@ -9557,7 +9609,8 @@ up.network = (function () {
9557
9609
  if (request.cache && response.url && request.url !== response.url) {
9558
9610
  const newRequest = u.variant(request, {
9559
9611
  method: response.method,
9560
- url: response.url
9612
+ url: response.url,
9613
+ cacheRoute: null,
9561
9614
  });
9562
9615
  cache.alias(request, newRequest);
9563
9616
  }
@@ -9864,7 +9917,6 @@ __webpack_require__(96);
9864
9917
  up.link = (function () {
9865
9918
  const u = up.util;
9866
9919
  const e = up.element;
9867
- const linkPreloader = new up.LinkPreloader();
9868
9920
  let lastMousedownTarget = null;
9869
9921
  const LINKS_WITH_LOCAL_HTML = ['a[up-content]', 'a[up-fragment]', 'a[up-document]'];
9870
9922
  const LINKS_WITH_REMOTE_HTML = ['a[href]', '[up-href]'];
@@ -9898,10 +9950,9 @@ up.link = (function () {
9898
9950
  }
9899
9951
  function reset() {
9900
9952
  lastMousedownTarget = null;
9901
- linkPreloader.reset();
9902
9953
  }
9903
- const follow = up.mockable(function (link, options) {
9904
- return up.render(followOptions(link, options));
9954
+ const follow = up.mockable(function (link, options, parserOptions) {
9955
+ return up.render(followOptions(link, options, parserOptions));
9905
9956
  });
9906
9957
  function parseRequestOptions(link, options, parserOptions) {
9907
9958
  options = u.options(options);
@@ -9923,6 +9974,7 @@ up.link = (function () {
9923
9974
  return options;
9924
9975
  }
9925
9976
  function followOptions(link, options, parserOptions) {
9977
+ var _a;
9926
9978
  link = up.fragment.get(link);
9927
9979
  options = u.options(options);
9928
9980
  const parser = new up.OptionsParser(link, options, Object.assign({ fail: true }, parserOptions));
@@ -9976,10 +10028,9 @@ up.link = (function () {
9976
10028
  parser.booleanOrString('location');
9977
10029
  parser.booleanOrString('title');
9978
10030
  parser.boolean('metaTags');
10031
+ parser.booleanOrString('lang');
9979
10032
  parser.include(up.motion.motionOptions);
9980
- if (!options.guardEvent) {
9981
- options.guardEvent = up.event.build('up:link:follow', { log: 'Following link' });
9982
- }
10033
+ (_a = options.guardEvent) !== null && _a !== void 0 ? _a : (options.guardEvent = up.event.build('up:link:follow', { log: ['Following link %o', link] }));
9983
10034
  return options;
9984
10035
  }
9985
10036
  function preload(link, options) {
@@ -10018,9 +10069,10 @@ up.link = (function () {
10018
10069
  if (link.matches('a[href], button')) {
10019
10070
  return;
10020
10071
  }
10072
+ let role = link.matches('a') ? 'link' : 'button';
10021
10073
  e.setMissingAttrs(link, {
10022
10074
  tabindex: '0',
10023
- role: 'link',
10075
+ role,
10024
10076
  'up-clickable': ''
10025
10077
  });
10026
10078
  link.addEventListener('keydown', function (event) {
@@ -10080,6 +10132,38 @@ up.link = (function () {
10080
10132
  const method = followMethod(link);
10081
10133
  return up.network.isSafeMethod(method);
10082
10134
  }
10135
+ function onLoadCondition(condition, link, callback) {
10136
+ switch (condition) {
10137
+ case 'insert':
10138
+ callback();
10139
+ break;
10140
+ case 'reveal': {
10141
+ let margin = e.numberAttr(link, 'up-intersect-margin');
10142
+ up.fragment.onFirstIntersect(link, callback, { margin });
10143
+ break;
10144
+ }
10145
+ case 'hover':
10146
+ new up.LinkFollowIntent(link, callback);
10147
+ break;
10148
+ case 'manual':
10149
+ break;
10150
+ }
10151
+ }
10152
+ function loadDeferred(link, options) {
10153
+ let guardEvent = up.event.build('up:deferred:load', { log: ['Loading deferred %o', link] });
10154
+ let forcedOptions = Object.assign({ navigate: false, guardEvent }, options);
10155
+ let defaults = {
10156
+ target: ':origin',
10157
+ cache: 'auto',
10158
+ revalidate: 'auto',
10159
+ feedback: true,
10160
+ };
10161
+ return follow(link, forcedOptions, { defaults });
10162
+ }
10163
+ up.attribute('up-defer', { defaultValue: 'insert' }, function (link, condition) {
10164
+ let doLoad = () => up.error.muteUncriticalRejection(loadDeferred(link));
10165
+ onLoadCondition(condition, link, doLoad);
10166
+ });
10083
10167
  up.on('up:click', config.selectorFn('followSelectors'), function (event, link) {
10084
10168
  if (shouldFollowEvent(event, link)) {
10085
10169
  up.event.halt(event, { log: true });
@@ -10087,21 +10171,20 @@ up.link = (function () {
10087
10171
  up.error.muteUncriticalRejection(follow(link));
10088
10172
  }
10089
10173
  });
10090
- up.macro('[up-expand]', function (area) {
10091
- const selector = area.getAttribute('up-expand') || 'a, [up-href]';
10092
- let childLink = e.get(area, selector);
10174
+ up.attribute('up-expand', { defaultValue: 'a, [up-href]', macro: true }, function (area, childLinkSelector) {
10175
+ let childLink = e.get(area, childLinkSelector);
10093
10176
  if (childLink) {
10094
- const areaAttrs = e.upAttrs(childLink);
10095
- areaAttrs['up-href'] || (areaAttrs['up-href'] = childLink.getAttribute('href'));
10096
- e.setMissingAttrs(area, areaAttrs);
10097
- const areaClasses = e.upClasses(childLink);
10098
- area.classList.add(...areaClasses);
10177
+ e.setMissingAttrs(area, Object.assign({ 'up-href': e.attr(childLink, 'href') }, e.upAttrs(childLink)));
10178
+ area.classList.add(...e.upClasses(childLink));
10099
10179
  makeFollowable(area);
10100
10180
  }
10101
10181
  });
10102
10182
  up.compiler(config.selectorFn('preloadSelectors'), function (link) {
10183
+ var _a;
10103
10184
  if (!isPreloadDisabled(link)) {
10104
- linkPreloader.watchLink(link);
10185
+ let doPreload = () => up.error.muteUncriticalRejection(preload(link));
10186
+ let condition = (_a = e.booleanOrStringAttr(link, 'up-preload', null)) !== null && _a !== void 0 ? _a : 'hover';
10187
+ onLoadCondition(condition, link, doPreload);
10105
10188
  }
10106
10189
  });
10107
10190
  up.on('up:framework:reset', reset);
@@ -10110,18 +10193,17 @@ up.link = (function () {
10110
10193
  followOptions,
10111
10194
  preload,
10112
10195
  makeFollowable,
10113
- makeClickable,
10114
10196
  isSafe,
10115
10197
  isFollowable,
10116
10198
  shouldFollowEvent,
10117
- followMethod,
10118
10199
  convertClicks,
10119
10200
  config,
10120
10201
  combineFollowableSelectors,
10121
- preloadIssue,
10202
+ loadDeferred,
10122
10203
  };
10123
10204
  })();
10124
10205
  up.follow = up.link.follow;
10206
+ up.deferred = { load: up.link.loadDeferred };
10125
10207
 
10126
10208
 
10127
10209
  /***/ }),
@@ -10194,7 +10276,8 @@ up.form = (function () {
10194
10276
  options.guardEvent || (options.guardEvent = up.event.build('up:form:submit', {
10195
10277
  submitButton: options.submitButton,
10196
10278
  log: 'Submitting form',
10197
- params: options.params
10279
+ params: options.params,
10280
+ form,
10198
10281
  }));
10199
10282
  options.origin || (options.origin = up.viewport.focusedElementWithin(form) || options.submitButton || form);
10200
10283
  parser.include(up.link.followOptions);
@@ -10469,7 +10552,9 @@ up.form = (function () {
10469
10552
  validator.watchContainer(fieldOrForm);
10470
10553
  });
10471
10554
  function validatingFieldSelector() {
10472
- return config.fieldSelectors.map((selector) => `${selector}[up-validate], [up-validate] ${selector}`).join(', ');
10555
+ let includes = config.fieldSelectors.map((selector) => `${selector}[up-validate], [up-validate] ${selector}`);
10556
+ let excludes = ['[up-validate=false]'];
10557
+ return e.unionSelector(includes, excludes);
10473
10558
  }
10474
10559
  up.compiler('[up-switch]', (switcher) => {
10475
10560
  switchTargets(switcher);
@@ -10480,8 +10565,8 @@ up.form = (function () {
10480
10565
  up.compiler('[up-show-for]:not(.up-switched), [up-hide-for]:not(.up-switched)', (element) => {
10481
10566
  switchTarget(element);
10482
10567
  });
10483
- up.compiler('[up-watch]', (formOrField) => watch(formOrField));
10484
- up.compiler('[up-autosubmit]', (formOrField) => autosubmit(formOrField));
10568
+ up.attribute('up-watch', (formOrField) => watch(formOrField));
10569
+ up.attribute('up-autosubmit', (formOrField) => autosubmit(formOrField));
10485
10570
  return {
10486
10571
  config,
10487
10572
  submit,
@@ -10523,6 +10608,7 @@ up.feedback = (function () {
10523
10608
  const config = new up.Config(() => ({
10524
10609
  currentClasses: ['up-current'],
10525
10610
  navSelectors: ['[up-nav]', 'nav'],
10611
+ noNavSelectors: ['[up-nav=false]'],
10526
10612
  }));
10527
10613
  function reset() {
10528
10614
  up.layer.root.feedbackLocation = null;
@@ -10530,9 +10616,6 @@ up.feedback = (function () {
10530
10616
  const CLASS_ACTIVE = 'up-active';
10531
10617
  const CLASS_LOADING = 'up-loading';
10532
10618
  const SELECTOR_LINK = 'a, [up-href]';
10533
- function navSelector() {
10534
- return config.selector('navSelectors');
10535
- }
10536
10619
  function normalizeURL(url) {
10537
10620
  if (url) {
10538
10621
  return u.normalizeURL(url, { trailingSlash: false, hash: false });
@@ -10541,40 +10624,23 @@ up.feedback = (function () {
10541
10624
  function linkURLs(link) {
10542
10625
  return link.upFeedbackURLs || (link.upFeedbackURLs = new up.LinkFeedbackURLs(link));
10543
10626
  }
10544
- function updateFragment(fragment) {
10545
- const layerOption = { layer: up.layer.get(fragment) };
10546
- if (up.fragment.closest(fragment, navSelector(), layerOption)) {
10547
- const links = up.fragment.subtree(fragment, SELECTOR_LINK, layerOption);
10548
- updateLinks(links, layerOption);
10549
- }
10550
- else {
10551
- updateLinksWithinNavs(fragment, layerOption);
10627
+ function updateFragment(fragment, { layer } = {}) {
10628
+ layer || (layer = up.layer.get(fragment));
10629
+ let layerLocation = getNormalizedLayerLocation(layer);
10630
+ const navSelector = config.selector('navSelectors');
10631
+ const navLinkSelector = `${navSelector} :is(${SELECTOR_LINK}), ${navSelector}:is(${SELECTOR_LINK})`;
10632
+ const links = up.fragment.all(navLinkSelector, { layer });
10633
+ for (let link of links) {
10634
+ const isCurrent = linkURLs(link).isCurrent(layerLocation);
10635
+ for (let currentClass of config.currentClasses) {
10636
+ link.classList.toggle(currentClass, isCurrent);
10637
+ }
10638
+ e.toggleAttr(link, 'aria-current', 'page', isCurrent);
10552
10639
  }
10553
10640
  }
10554
- function updateLinksWithinNavs(fragment, options) {
10555
- const navs = up.fragment.subtree(fragment, navSelector(), options);
10556
- const links = u.flatMap(navs, nav => e.subtree(nav, SELECTOR_LINK));
10557
- updateLinks(links, options);
10558
- }
10559
10641
  function getNormalizedLayerLocation(layer) {
10560
10642
  return layer.feedbackLocation || normalizeURL(layer.location);
10561
10643
  }
10562
- function updateLinks(links, options = {}) {
10563
- if (!links.length) {
10564
- return;
10565
- }
10566
- const layer = options.layer || up.layer.get(links[0]);
10567
- let layerLocation = getNormalizedLayerLocation(layer);
10568
- if (layerLocation) {
10569
- for (let link of links) {
10570
- const isCurrent = linkURLs(link).isCurrent(layerLocation);
10571
- for (let currentClass of config.currentClasses) {
10572
- link.classList.toggle(currentClass, isCurrent);
10573
- }
10574
- e.toggleAttr(link, 'aria-current', 'page', isCurrent);
10575
- }
10576
- }
10577
- }
10578
10644
  function findActivatableArea(element) {
10579
10645
  return e.ancestor(element, SELECTOR_LINK) || element;
10580
10646
  }
@@ -10602,7 +10668,7 @@ up.feedback = (function () {
10602
10668
  const layerLocation = getNormalizedLayerLocation(layer.location);
10603
10669
  if (!processedLocation || (processedLocation !== layerLocation)) {
10604
10670
  layer.feedbackLocation = layerLocation;
10605
- updateLinksWithinNavs(layer.element, { layer });
10671
+ updateFragment(layer.element, { layer });
10606
10672
  }
10607
10673
  }
10608
10674
  function onBrowserLocationChanged() {
@@ -10637,6 +10703,7 @@ up.radio = (function () {
10637
10703
  const e = up.element;
10638
10704
  const config = new up.Config(() => ({
10639
10705
  hungrySelectors: ['[up-hungry]'],
10706
+ noHungrySelectors: ['[up-hungry=false]'],
10640
10707
  pollInterval: 30000,
10641
10708
  }));
10642
10709
  function hungrySteps(renderOptions) {
@@ -10682,7 +10749,7 @@ up.radio = (function () {
10682
10749
  parser.string('ifLayer', { default: 'front' });
10683
10750
  return options;
10684
10751
  }
10685
- up.compiler('[up-poll]:not([up-poll=false])', function (fragment) {
10752
+ up.attribute('up-poll', function (fragment) {
10686
10753
  up.FragmentPolling.forFragment(fragment).onPollAttributeObserved();
10687
10754
  });
10688
10755
  up.macro('[up-flashes]', function (fragment) {