unpoly-rails 3.7.3.2 → 3.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,7 +5,7 @@
5
5
  /***/ (() => {
6
6
 
7
7
  window.up = {
8
- version: '3.7.3'
8
+ version: '3.8.0'
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,
@@ -887,7 +884,9 @@ up.fail = up.error.fail;
887
884
  /* 5 */
888
885
  /***/ (() => {
889
886
 
890
- up.migrate = { config: {} };
887
+ up.migrate = {
888
+ config: {},
889
+ };
891
890
 
892
891
 
893
892
  /***/ }),
@@ -1184,7 +1183,7 @@ up.element = (function () {
1184
1183
  }
1185
1184
  }
1186
1185
  function idSelector(id) {
1187
- if (id.match(/^[a-z0-9\-_]+$/i)) {
1186
+ if (id.match(/^[a-z][a-z0-9\-_]*$/i)) {
1188
1187
  return `#${id}`;
1189
1188
  }
1190
1189
  else {
@@ -1223,16 +1222,9 @@ up.element = (function () {
1223
1222
  paint(element);
1224
1223
  return undo;
1225
1224
  }
1226
- function hasCSSTransition(elementOrStyleHash) {
1227
- let styleHash;
1228
- if (u.isOptions(elementOrStyleHash)) {
1229
- styleHash = elementOrStyleHash;
1230
- }
1231
- else {
1232
- styleHash = computedStyle(elementOrStyleHash);
1233
- }
1234
- const prop = styleHash.transitionProperty;
1235
- const duration = styleHash.transitionDuration;
1225
+ function hasCSSTransition(styleHash) {
1226
+ const prop = styleHash['transition-property'];
1227
+ const duration = styleHash['transition-duration'];
1236
1228
  const noTransition = ((prop === 'none') || ((prop === 'all') && (duration === 0)));
1237
1229
  return !noTransition;
1238
1230
  }
@@ -1241,8 +1233,8 @@ up.element = (function () {
1241
1233
  element.style.position = 'absolute';
1242
1234
  const offsetParentRect = element.offsetParent.getBoundingClientRect();
1243
1235
  setInlineStyle(element, {
1244
- left: elementRectAsFixed.left - computedStyleNumber(element, 'margin-left') - offsetParentRect.left,
1245
- top: elementRectAsFixed.top - computedStyleNumber(element, 'margin-top') - offsetParentRect.top,
1236
+ left: (elementRectAsFixed.left - computedStyleNumber(element, 'margin-left') - offsetParentRect.left) + 'px',
1237
+ top: (elementRectAsFixed.top - computedStyleNumber(element, 'margin-top') - offsetParentRect.top) + 'px',
1246
1238
  right: '',
1247
1239
  bottom: ''
1248
1240
  });
@@ -1274,9 +1266,6 @@ up.element = (function () {
1274
1266
  element.appendChild(wrapper);
1275
1267
  return wrapper;
1276
1268
  }
1277
- function isWrapper(element) {
1278
- return element.matches('up-wrapper');
1279
- }
1280
1269
  function preservingFocus(fn) {
1281
1270
  const oldFocusElement = document.activeElement;
1282
1271
  try {
@@ -1289,7 +1278,8 @@ up.element = (function () {
1289
1278
  }
1290
1279
  }
1291
1280
  function stringAttr(element, attribute) {
1292
- return u.nullToUndefined(element.getAttribute(attribute));
1281
+ let value = element.getAttribute(attribute);
1282
+ return u.replaceValue(value, null, undefined);
1293
1283
  }
1294
1284
  function booleanAttr(element, attribute, pass) {
1295
1285
  if (!element.hasAttribute(attribute))
@@ -1314,14 +1304,15 @@ up.element = (function () {
1314
1304
  }
1315
1305
  }
1316
1306
  }
1317
- function booleanOrStringAttr(element, attribute) {
1318
- return booleanAttr(element, attribute, true);
1307
+ function booleanOrStringAttr(element, attribute, trueValue = true) {
1308
+ let value = booleanAttr(element, attribute, true);
1309
+ return value === true ? trueValue : value;
1319
1310
  }
1320
1311
  function numberAttr(element, attribute) {
1321
1312
  let value = element.getAttribute(attribute);
1322
1313
  if (value) {
1323
1314
  value = value.replace(/_/g, '');
1324
- if (value.match(/^[\d.]+$/)) {
1315
+ if (value.match(/^-?[\d.]+$/)) {
1325
1316
  return parseFloat(value);
1326
1317
  }
1327
1318
  }
@@ -1358,17 +1349,13 @@ up.element = (function () {
1358
1349
  element.classList.add(klass);
1359
1350
  return () => element.classList.remove(klass);
1360
1351
  }
1361
- function setTemporaryAttr(element, attr, value) {
1362
- element.setAttribute(attr, value);
1363
- return () => element.removeAttribute(element, attr);
1364
- }
1365
1352
  function computedStyle(element, props) {
1366
1353
  const style = window.getComputedStyle(element);
1367
1354
  return extractFromStyleObject(style, props);
1368
1355
  }
1369
1356
  function computedStyleNumber(element, prop) {
1370
1357
  const rawValue = computedStyle(element, prop);
1371
- if (u.isGiven(rawValue)) {
1358
+ if (u.isPresent(rawValue)) {
1372
1359
  return parseFloat(rawValue);
1373
1360
  }
1374
1361
  }
@@ -1377,14 +1364,18 @@ up.element = (function () {
1377
1364
  return extractFromStyleObject(style, props);
1378
1365
  }
1379
1366
  function extractFromStyleObject(style, keyOrKeys) {
1367
+ if (up.migrate.loaded)
1368
+ keyOrKeys = up.migrate.fixStyleProps(keyOrKeys);
1380
1369
  if (u.isString(keyOrKeys)) {
1381
- return style[keyOrKeys];
1370
+ return style.getPropertyValue(keyOrKeys);
1382
1371
  }
1383
1372
  else {
1384
- return u.pick(style, keyOrKeys);
1373
+ return u.mapObject(keyOrKeys, (key) => [key, style.getPropertyValue(key)]);
1385
1374
  }
1386
1375
  }
1387
- function setInlineStyle(element, props) {
1376
+ function setInlineStyle(element, props, unit = '') {
1377
+ if (up.migrate.loaded)
1378
+ props = up.migrate.fixStyleProps(props, unit);
1388
1379
  if (u.isString(props)) {
1389
1380
  element.setAttribute('style', props);
1390
1381
  }
@@ -1392,37 +1383,10 @@ up.element = (function () {
1392
1383
  const { style } = element;
1393
1384
  for (let key in props) {
1394
1385
  let value = props[key];
1395
- value = normalizeStyleValueForWrite(key, value);
1396
- style[key] = value;
1386
+ style.setProperty(key, value + unit);
1397
1387
  }
1398
1388
  }
1399
1389
  }
1400
- function normalizeStyleValueForWrite(key, value) {
1401
- if (u.isMissing(value)) {
1402
- value = '';
1403
- }
1404
- else if (CSS_LENGTH_PROPS.has(key.toLowerCase().replace(/-/, ''))) {
1405
- value = cssLength(value);
1406
- }
1407
- return value;
1408
- }
1409
- const CSS_LENGTH_PROPS = new Set([
1410
- 'top', 'right', 'bottom', 'left',
1411
- 'padding', 'paddingtop', 'paddingright', 'paddingbottom', 'paddingleft',
1412
- 'margin', 'margintop', 'marginright', 'marginbottom', 'marginleft',
1413
- 'borderwidth', 'bordertopwidth', 'borderrightwidth', 'borderbottomwidth', 'borderleftwidth',
1414
- 'width', 'height',
1415
- 'maxwidth', 'maxheight',
1416
- 'minwidth', 'minheight',
1417
- ]);
1418
- function cssLength(obj) {
1419
- if (u.isNumber(obj) || (u.isString(obj) && /^\d+$/.test(obj))) {
1420
- return obj.toString() + "px";
1421
- }
1422
- else {
1423
- return obj;
1424
- }
1425
- }
1426
1390
  function isVisible(element) {
1427
1391
  return !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length);
1428
1392
  }
@@ -1447,6 +1411,18 @@ up.element = (function () {
1447
1411
  function crossOriginSelector(attr) {
1448
1412
  return `[${attr}*="//"]:not([${attr}*="//${location.host}/"])`;
1449
1413
  }
1414
+ function isIntersectingWindow(element, { margin = 0 } = {}) {
1415
+ const rect = up.Rect.fromElement(element);
1416
+ rect.grow(margin);
1417
+ return (rect.bottom > 0) && (rect.top < window.innerHeight) &&
1418
+ (rect.right > 0) && (rect.left < window.innerWidth);
1419
+ }
1420
+ function unionSelector(includes, excludes) {
1421
+ let selector = `:is(${includes.join()})`;
1422
+ if (u.isPresent(excludes))
1423
+ selector += `:not(${excludes.join()})`;
1424
+ return selector;
1425
+ }
1450
1426
  return {
1451
1427
  subtree,
1452
1428
  contains,
@@ -1481,7 +1457,6 @@ up.element = (function () {
1481
1457
  setMissingAttr,
1482
1458
  unwrap,
1483
1459
  wrapChildren,
1484
- isWrapper,
1485
1460
  attr: stringAttr,
1486
1461
  booleanAttr,
1487
1462
  numberAttr,
@@ -1498,11 +1473,12 @@ up.element = (function () {
1498
1473
  upClasses,
1499
1474
  toggleAttr,
1500
1475
  addTemporaryClass,
1501
- setTemporaryAttr,
1502
1476
  cleanJQuery,
1503
1477
  parseSelector,
1504
1478
  isEmpty,
1505
1479
  crossOriginSelector,
1480
+ isIntersectingWindow,
1481
+ unionSelector,
1506
1482
  };
1507
1483
  })();
1508
1484
 
@@ -1612,6 +1588,7 @@ up.Record = class Record {
1612
1588
  /***/ (() => {
1613
1589
 
1614
1590
  const u = up.util;
1591
+ const e = up.element;
1615
1592
  up.Config = class Config {
1616
1593
  constructor(blueprintFn = (() => ({}))) {
1617
1594
  this._blueprintFn = blueprintFn;
@@ -1627,10 +1604,7 @@ up.Config = class Config {
1627
1604
  selector(prop) {
1628
1605
  let includes = this[prop];
1629
1606
  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;
1607
+ return e.unionSelector(includes, excludes);
1634
1608
  }
1635
1609
  selectorFn(prop) {
1636
1610
  return () => this.selector(prop);
@@ -1801,6 +1775,12 @@ up.Rect = class Rect extends up.Record {
1801
1775
  get right() {
1802
1776
  return this.left + this.width;
1803
1777
  }
1778
+ grow(padding) {
1779
+ this.left -= padding;
1780
+ this.top -= padding;
1781
+ this.width += padding * 2;
1782
+ this.height += padding * 2;
1783
+ }
1804
1784
  static fromElement(element) {
1805
1785
  return new (this)(element.getBoundingClientRect());
1806
1786
  }
@@ -1812,64 +1792,49 @@ up.Rect = class Rect extends up.Record {
1812
1792
  /***/ (() => {
1813
1793
 
1814
1794
  const e = up.element;
1795
+ const SHIFT_CLASS = 'up-scrollbar-away';
1815
1796
  up.BodyShifter = class BodyShifter {
1816
1797
  constructor() {
1817
- this._unshiftFns = [];
1818
1798
  this._anchoredElements = new Set();
1819
1799
  this._stack = 0;
1800
+ this._cleaners = [];
1820
1801
  }
1821
1802
  lowerStack() {
1822
- this._stack--;
1823
- if (this._stack === 0) {
1803
+ if (--this._stack === 0)
1824
1804
  this._unshiftNow();
1825
- }
1826
1805
  }
1827
1806
  raiseStack() {
1828
- this._stack++;
1829
- if (this._stack === 1) {
1807
+ if (++this._stack === 1)
1830
1808
  this._shiftNow();
1831
- }
1832
1809
  }
1833
1810
  onAnchoredElementInserted(element) {
1834
1811
  this._anchoredElements.add(element);
1835
- if (this._isShifted()) {
1836
- this._shiftAnchoredElement(element);
1837
- }
1812
+ this._shiftElement(element, 'right');
1838
1813
  return () => this._anchoredElements.delete(element);
1839
1814
  }
1840
1815
  _isShifted() {
1841
- return this._scrollbarTookSpace && this._stack > 0;
1816
+ return this._rootScrollbarWidth && this._stack > 0;
1842
1817
  }
1843
1818
  _shiftNow() {
1844
- this._scrollbarWidth = up.viewport.scrollbarWidth();
1845
- this._scrollbarTookSpace = up.viewport.rootHasReducedWidthFromScrollbar();
1846
- if (!this._scrollbarTookSpace)
1847
- return;
1848
- this._shiftBody();
1819
+ this._rootScrollbarWidth = up.viewport.rootScrollbarWidth();
1820
+ this._cleaners.push(e.setTemporaryStyle(e.root, {
1821
+ '--up-scrollbar-width': this._rootScrollbarWidth + 'px'
1822
+ }));
1823
+ this._shiftElement(document.body, 'padding-right');
1849
1824
  for (let element of this._anchoredElements) {
1850
- this._shiftAnchoredElement(element);
1825
+ this._shiftElement(element, 'right');
1851
1826
  }
1852
1827
  }
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));
1828
+ _shiftElement(element, styleProp) {
1829
+ if (!this._isShifted())
1830
+ return;
1831
+ let originalValue = e.style(element, styleProp);
1832
+ this._cleaners.push(e.setTemporaryStyle(e.root, { ['--up-original-' + styleProp]: originalValue }), e.addTemporaryClass(element, SHIFT_CLASS));
1868
1833
  }
1869
1834
  _unshiftNow() {
1870
- let unshiftFn;
1871
- while (unshiftFn = this._unshiftFns.pop()) {
1872
- unshiftFn();
1835
+ let cleaner;
1836
+ while (cleaner = this._cleaners.pop()) {
1837
+ cleaner();
1873
1838
  }
1874
1839
  }
1875
1840
  };
@@ -3078,6 +3043,7 @@ up.Change.FromContent = (_a = class FromContent extends up.Change {
3078
3043
  }
3079
3044
  this.options.title = this.improveHistoryValue(this.options.title, responseDoc.title);
3080
3045
  this.options.metaTags = this.improveHistoryValue(this.options.metaTags, responseDoc.metaTags);
3046
+ this.options.lang = this.improveHistoryValue(this.options.lang, responseDoc.lang);
3081
3047
  }
3082
3048
  _defaultPlacement() {
3083
3049
  if (!this.options.document && !this.options.fragment) {
@@ -3250,20 +3216,17 @@ up.CompilerPass = class CompilerPass {
3250
3216
  const u = up.util;
3251
3217
  const e = up.element;
3252
3218
  up.CSSTransition = class CSSTransition {
3253
- constructor(element, lastFrameKebab, options) {
3219
+ constructor(element, lastFrame, options) {
3254
3220
  this._element = element;
3255
- this._lastFrameKebab = lastFrameKebab;
3256
- this._lastFrameKeysKebab = Object.keys(this._lastFrameKebab);
3257
- if (u.some(this._lastFrameKeysKebab, key => key.match(/A-Z/))) {
3258
- up.fail('Animation keys must be kebab-case');
3259
- }
3221
+ this._lastFrame = lastFrame;
3222
+ this._lastFrameKeys = Object.keys(this._lastFrame);
3260
3223
  this._finishEvent = options.finishEvent;
3261
3224
  this._duration = options.duration;
3262
3225
  this._easing = options.easing;
3263
3226
  this._finished = false;
3264
3227
  }
3265
3228
  start() {
3266
- if (this._lastFrameKeysKebab.length === 0) {
3229
+ if (this._lastFrameKeys.length === 0) {
3267
3230
  this._finished = true;
3268
3231
  return Promise.resolve();
3269
3232
  }
@@ -3287,9 +3250,7 @@ up.CSSTransition = class CSSTransition {
3287
3250
  }
3288
3251
  _startFallbackTimer() {
3289
3252
  const timingTolerance = 100;
3290
- this._fallbackTimer = u.timer((this._duration + timingTolerance), () => {
3291
- this._finish();
3292
- });
3253
+ this._fallbackTimer = u.timer((this._duration + timingTolerance), () => this._finish());
3293
3254
  }
3294
3255
  _stopFallbackTimer() {
3295
3256
  clearTimeout(this._fallbackTimer);
@@ -3305,11 +3266,10 @@ up.CSSTransition = class CSSTransition {
3305
3266
  if (elapsed <= (0.25 * this._duration)) {
3306
3267
  return;
3307
3268
  }
3308
- const completedPropertyKebab = event.propertyName;
3309
- if (!u.contains(this._lastFrameKeysKebab, completedPropertyKebab)) {
3310
- return;
3269
+ const completedProperty = event.propertyName;
3270
+ if (u.contains(this._lastFrameKeys, completedProperty)) {
3271
+ this._finish();
3311
3272
  }
3312
- this._finish();
3313
3273
  }
3314
3274
  _finish() {
3315
3275
  var _a, _b;
@@ -3326,16 +3286,16 @@ up.CSSTransition = class CSSTransition {
3326
3286
  }
3327
3287
  _pauseOldTransition() {
3328
3288
  const oldTransition = e.style(this._element, [
3329
- 'transitionProperty',
3330
- 'transitionDuration',
3331
- 'transitionDelay',
3332
- 'transitionTimingFunction'
3289
+ 'transition-property',
3290
+ 'transition-duration',
3291
+ 'transition-delay',
3292
+ 'transition-timing-function'
3333
3293
  ]);
3334
3294
  if (e.hasCSSTransition(oldTransition)) {
3335
- if (oldTransition.transitionProperty !== 'all') {
3336
- const oldTransitionProperties = oldTransition.transitionProperty.split(/\s*,\s*/);
3337
- const oldTransitionFrameKebab = e.style(this._element, oldTransitionProperties);
3338
- this._setOldTransitionTargetFrame = e.setTemporaryStyle(this._element, oldTransitionFrameKebab);
3295
+ if (oldTransition['transition-property'] !== 'all') {
3296
+ const oldTransitionProperties = oldTransition['transition-property'].split(/\s*,\s*/);
3297
+ const oldTransitionFrame = e.style(this._element, oldTransitionProperties);
3298
+ this._setOldTransitionTargetFrame = e.setTemporaryStyle(this._element, oldTransitionFrame);
3339
3299
  }
3340
3300
  this._setOldTransition = e.concludeCSSTransition(this._element);
3341
3301
  }
@@ -3347,11 +3307,11 @@ up.CSSTransition = class CSSTransition {
3347
3307
  }
3348
3308
  _startMotion() {
3349
3309
  e.setStyle(this._element, {
3350
- transitionProperty: Object.keys(this._lastFrameKebab).join(', '),
3351
- transitionDuration: `${this._duration}ms`,
3352
- transitionTimingFunction: this._easing
3310
+ 'transition-property': this._lastFrameKeys.join(),
3311
+ 'transition-duration': `${this._duration}ms`,
3312
+ 'transition-timing-function': this._easing
3353
3313
  });
3354
- e.setStyle(this._element, this._lastFrameKebab);
3314
+ e.setStyle(this._element, this._lastFrame);
3355
3315
  }
3356
3316
  };
3357
3317
 
@@ -3831,6 +3791,7 @@ var __rest = (this && this.__rest) || function (s, e) {
3831
3791
  return t;
3832
3792
  };
3833
3793
  const u = up.util;
3794
+ const e = up.element;
3834
3795
  up.FormValidator = class FormValidator {
3835
3796
  constructor(form) {
3836
3797
  this._form = form;
@@ -3891,7 +3852,7 @@ up.FormValidator = class FormValidator {
3891
3852
  }
3892
3853
  }
3893
3854
  _getTargetSelectorSolutions({ target, origin }) {
3894
- if (u.isString(target) && target) {
3855
+ if (u.isString(target)) {
3895
3856
  up.puts('up.validate()', 'Validating target "%s"', target);
3896
3857
  let simpleSelectors = up.fragment.splitTarget(target);
3897
3858
  return u.compact(simpleSelectors.map(function (simpleSelector) {
@@ -3920,7 +3881,7 @@ up.FormValidator = class FormValidator {
3920
3881
  _getValidateAttrSolutions(field) {
3921
3882
  let containerWithAttr = field.closest('[up-validate]');
3922
3883
  if (containerWithAttr) {
3923
- let target = containerWithAttr.getAttribute('up-validate');
3884
+ let target = e.booleanOrStringAttr(containerWithAttr, 'up-validate');
3924
3885
  return this._getTargetSelectorSolutions({ target, origin: field });
3925
3886
  }
3926
3887
  }
@@ -3968,7 +3929,8 @@ up.FormValidator = class FormValidator {
3968
3929
  options.guardEvent = up.event.build('up:form:validate', {
3969
3930
  fields: dirtyFields,
3970
3931
  log: 'Validating form',
3971
- params: options.params
3932
+ params: options.params,
3933
+ form: this._form,
3972
3934
  });
3973
3935
  this._rendering = true;
3974
3936
  let renderingPromise = this._nextRenderPromise;
@@ -4617,6 +4579,7 @@ up.Layer = class Layer extends up.Record {
4617
4579
  this.savedTitle = document.title;
4618
4580
  this.savedMetaTags = up.history.findMetaTags();
4619
4581
  this.savedLocation = up.history.location;
4582
+ this.savedLang = up.history.getLang();
4620
4583
  }
4621
4584
  }
4622
4585
  restoreHistory() {
@@ -4632,6 +4595,9 @@ up.Layer = class Layer extends up.Record {
4632
4595
  if (this.savedMetaTags) {
4633
4596
  up.history.updateMetaTags(this.savedMetaTags);
4634
4597
  }
4598
+ if (u.isString(this.savedLang)) {
4599
+ up.history.updateLang(this.savedLang);
4600
+ }
4635
4601
  }
4636
4602
  asCurrent(fn) {
4637
4603
  return this.stack.asCurrent(this, fn);
@@ -4648,6 +4614,9 @@ up.Layer = class Layer extends up.Record {
4648
4614
  if (u.isString(options.title)) {
4649
4615
  this.title = options.title;
4650
4616
  }
4617
+ if (u.isString(options.lang)) {
4618
+ this.lang = options.lang;
4619
+ }
4651
4620
  }
4652
4621
  showsLiveHistory() {
4653
4622
  return this.history && this.isFront();
@@ -4680,6 +4649,20 @@ up.Layer = class Layer extends up.Record {
4680
4649
  up.history.updateMetaTags(metaTags);
4681
4650
  }
4682
4651
  }
4652
+ get lang() {
4653
+ if (this.showsLiveHistory()) {
4654
+ return up.history.getLang();
4655
+ }
4656
+ else {
4657
+ return this.savedLang;
4658
+ }
4659
+ }
4660
+ set lang(lang) {
4661
+ this.savedLang = lang;
4662
+ if (this.showsLiveHistory()) {
4663
+ up.history.updateLang(lang);
4664
+ }
4665
+ }
4683
4666
  get location() {
4684
4667
  if (this.showsLiveHistory()) {
4685
4668
  return up.history.location;
@@ -5408,7 +5391,10 @@ up.LinkFeedbackURLs = class LinkFeedbackURLs {
5408
5391
  }
5409
5392
  isCurrent(normalizedLocation) {
5410
5393
  var _a, _b;
5411
- return this._isSafe && !!(this.href === normalizedLocation ||
5394
+ if (!normalizedLocation) {
5395
+ return false;
5396
+ }
5397
+ return !!(this.href === normalizedLocation ||
5412
5398
  this._upHREF === normalizedLocation ||
5413
5399
  ((_b = (_a = this._aliasPattern) === null || _a === void 0 ? void 0 : _a.test) === null || _b === void 0 ? void 0 : _b.call(_a, normalizedLocation, false)));
5414
5400
  }
@@ -5421,62 +5407,41 @@ up.LinkFeedbackURLs = class LinkFeedbackURLs {
5421
5407
 
5422
5408
  const u = up.util;
5423
5409
  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
- }
5410
+ up.LinkFollowIntent = class LinkFollowIntent {
5411
+ constructor(link, callback) {
5412
+ this._link = link;
5413
+ this._callback = callback;
5414
+ this._on('mouseenter mousedown touchstart', (event) => this._scheduleCallback(event));
5415
+ this._on('mouseleave', () => this._unscheduleCallback());
5416
+ up.fragment.onAborted(this._link, () => this._unscheduleCallback());
5449
5417
  }
5450
- _stopPreload(event) {
5451
- if (event.target === this._currentLink) {
5452
- return this.reset();
5453
- }
5418
+ _on(eventType, callback) {
5419
+ up.on(this._link, eventType, { passive: true }, callback);
5454
5420
  }
5455
- reset() {
5456
- var _a;
5457
- if (!this._currentLink) {
5421
+ _scheduleCallback(event) {
5422
+ if (!up.link.shouldFollowEvent(event, this._link))
5458
5423
  return;
5424
+ this._unscheduleCallback();
5425
+ const applyDelay = (event.type === 'mouseenter');
5426
+ if (applyDelay) {
5427
+ let delay = this._parseDelay();
5428
+ this._timer = u.timer(delay, () => this._runCallback(event));
5459
5429
  }
5460
- clearTimeout(this._timer);
5461
- if ((_a = this._currentRequest) === null || _a === void 0 ? void 0 : _a.background) {
5462
- this._currentRequest.abort();
5430
+ else {
5431
+ this._runCallback(event);
5463
5432
  }
5464
- this._currentLink = undefined;
5465
- this._currentRequest = undefined;
5466
5433
  }
5467
- _preloadAfterDelay(event, link) {
5434
+ _unscheduleCallback() {
5435
+ clearTimeout(this._timer);
5436
+ up.network.abort((request) => (request.origin === this._link) && request.background);
5437
+ }
5438
+ _parseDelay() {
5468
5439
  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));
5440
+ return (_a = e.numberAttr(this._link, 'up-preload-delay')) !== null && _a !== void 0 ? _a : up.link.config.preloadDelay;
5471
5441
  }
5472
- _preloadNow(event, link) {
5473
- if (!link.isConnected) {
5474
- this.reset();
5475
- return;
5476
- }
5477
- const onQueued = request => { return this._currentRequest = request; };
5442
+ _runCallback(event) {
5478
5443
  up.log.putsEvent(event);
5479
- up.error.muteUncriticalRejection(up.link.preload(link, { onQueued }));
5444
+ up.error.muteUncriticalRejection(this._callback());
5480
5445
  }
5481
5446
  };
5482
5447
 
@@ -6236,7 +6201,6 @@ up.Request = (_a = class Request extends up.Record {
6236
6201
  'wrapMethod',
6237
6202
  'contentType',
6238
6203
  'payload',
6239
- 'onQueued',
6240
6204
  'onLoading',
6241
6205
  'fail',
6242
6206
  'abortable',
@@ -6271,7 +6235,7 @@ up.Request = (_a = class Request extends up.Record {
6271
6235
  }
6272
6236
  this.deferred = u.newDeferred();
6273
6237
  (_d = this.badResponseTime) !== null && _d !== void 0 ? _d : (this.badResponseTime = u.evalOption(up.network.config.badResponseTime, this));
6274
- this._addAutoHeaders();
6238
+ this._setAutoHeaders();
6275
6239
  }
6276
6240
  get xhr() {
6277
6241
  var _b;
@@ -6281,7 +6245,7 @@ up.Request = (_a = class Request extends up.Record {
6281
6245
  if (this._fragments) {
6282
6246
  return this._fragments;
6283
6247
  }
6284
- else if (this.target) {
6248
+ else {
6285
6249
  let steps = up.fragment.parseTargetSteps(this.target);
6286
6250
  let selectors = u.map(steps, 'selector');
6287
6251
  let lookupOpts = { origin: this.origin, layer: this.layer };
@@ -6337,9 +6301,7 @@ up.Request = (_a = class Request extends up.Record {
6337
6301
  return u.evalAutoOption(this.cache, up.network.config.autoCache, this);
6338
6302
  }
6339
6303
  runQueuedCallbacks() {
6340
- var _b;
6341
6304
  u.always(this, () => this._evictExpensiveAttrs());
6342
- (_b = this.onQueued) === null || _b === void 0 ? void 0 : _b.call(this, this);
6343
6305
  }
6344
6306
  load() {
6345
6307
  var _b;
@@ -6484,9 +6446,6 @@ up.Request = (_a = class Request extends up.Record {
6484
6446
  return this.method + ' ' + this.url;
6485
6447
  }
6486
6448
  isPartOfSubtree(subtreeElements) {
6487
- if (!this.fragments || !subtreeElements) {
6488
- return false;
6489
- }
6490
6449
  subtreeElements = u.wrapList(subtreeElements);
6491
6450
  return u.some(this.fragments, function (fragment) {
6492
6451
  return u.some(subtreeElements, (subtreeElement) => subtreeElement.contains(fragment));
@@ -6498,17 +6457,20 @@ up.Request = (_a = class Request extends up.Record {
6498
6457
  header(name) {
6499
6458
  return this.headers[name];
6500
6459
  }
6501
- _addAutoHeaders() {
6460
+ _setAutoHeaders() {
6502
6461
  for (let key of ['target', 'failTarget', 'mode', 'failMode', 'context', 'failContext']) {
6503
- this._addAutoHeader(up.protocol.headerize(key), this[key]);
6462
+ this._setPropertyHeader(key);
6504
6463
  }
6505
6464
  let csrfHeader, csrfToken;
6506
6465
  if ((csrfHeader = this.csrfHeader()) && (csrfToken = this.csrfToken())) {
6507
- this._addAutoHeader(csrfHeader, csrfToken);
6466
+ this._setAutoHeader(csrfHeader, csrfToken);
6508
6467
  }
6509
- this._addAutoHeader(up.protocol.headerize('version'), up.version);
6468
+ this._setAutoHeader(up.protocol.headerize('version'), up.version);
6469
+ }
6470
+ _setPropertyHeader(key) {
6471
+ this._setAutoHeader(up.protocol.headerize(key), this[key]);
6510
6472
  }
6511
- _addAutoHeader(name, value) {
6473
+ _setAutoHeader(name, value) {
6512
6474
  if (u.isMissing(value)) {
6513
6475
  return;
6514
6476
  }
@@ -6517,6 +6479,16 @@ up.Request = (_a = class Request extends up.Record {
6517
6479
  }
6518
6480
  this.headers[name] = value;
6519
6481
  }
6482
+ mergeIfUnsent(trackingRequest) {
6483
+ if (this.state !== 'new')
6484
+ return;
6485
+ if (!this.target || !trackingRequest.target)
6486
+ return;
6487
+ let targetAtoms = up.fragment.splitTarget(this.target + ',' + trackingRequest.target);
6488
+ this.target = u.uniq(targetAtoms).join(', ');
6489
+ this._setPropertyHeader('target');
6490
+ this._fragments = u.uniq([...this.fragments, ...trackingRequest.fragments]);
6491
+ }
6520
6492
  static tester(condition, { except } = {}) {
6521
6493
  let testFn;
6522
6494
  if (u.isFunction(condition)) {
@@ -6560,78 +6532,85 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
6560
6532
  });
6561
6533
  };
6562
6534
  const u = up.util;
6535
+ class Route {
6536
+ constructor() {
6537
+ this.varyHeaders = new Set();
6538
+ this.requests = [];
6539
+ }
6540
+ matchBest(newRequest) {
6541
+ let matches = this.requests.filter((cachedRequest) => this.satisfies(cachedRequest, newRequest));
6542
+ return u.last(matches);
6543
+ }
6544
+ delete(request) {
6545
+ u.remove(this.requests, request);
6546
+ }
6547
+ put(request) {
6548
+ this.requests.push(request);
6549
+ }
6550
+ updateVary(response) {
6551
+ for (let headerName of response.varyHeaderNames) {
6552
+ this.varyHeaders.add(headerName);
6553
+ }
6554
+ }
6555
+ satisfies(cachedRequest, newRequest) {
6556
+ if (cachedRequest === newRequest)
6557
+ return true;
6558
+ return u.every(this.varyHeaders, (varyHeader) => {
6559
+ let cachedValue = cachedRequest.header(varyHeader);
6560
+ let newValue = newRequest.header(varyHeader);
6561
+ if (varyHeader === 'X-Up-Target' || varyHeader === 'X-Up-Fail-Target') {
6562
+ if (!cachedValue)
6563
+ return true;
6564
+ if (!newValue)
6565
+ return false;
6566
+ let cachedTokens = u.parseTokens(cachedValue, { separator: 'comma' });
6567
+ let newTokens = u.parseTokens(newValue, { separator: 'comma' });
6568
+ return u.containsAll(cachedTokens, newTokens);
6569
+ }
6570
+ else {
6571
+ return cachedValue === newValue;
6572
+ }
6573
+ });
6574
+ }
6575
+ }
6563
6576
  up.Request.Cache = class Cache {
6564
6577
  constructor() {
6565
6578
  this.reset();
6566
6579
  }
6567
6580
  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()));
6581
+ this._routes = {};
6582
+ this._requests = [];
6579
6583
  }
6580
6584
  get(request) {
6581
6585
  request = this._wrap(request);
6582
- let cacheKey = this._cacheKey(request);
6583
- let cachedRequest = this._map.get(cacheKey);
6586
+ let route = this._getRoute(request);
6587
+ let cachedRequest = route.matchBest(request);
6584
6588
  if (cachedRequest) {
6585
6589
  if (this._isUsable(cachedRequest)) {
6586
6590
  return cachedRequest;
6587
6591
  }
6588
6592
  else {
6589
- this._map.delete(cacheKey);
6593
+ this._delete(request, route);
6590
6594
  }
6591
6595
  }
6592
6596
  }
6593
- get _capacity() {
6594
- return up.network.config.cacheSize;
6595
- }
6596
- _isUsable(request) {
6597
- return request.age < up.network.config.cacheEvictAge;
6598
- }
6599
6597
  put(request) {
6600
6598
  return __awaiter(this, void 0, void 0, function* () {
6601
6599
  request = this._wrap(request);
6602
- this._makeRoom();
6603
- let cacheKey = this._updateCacheKey(request);
6604
- this._map.set(cacheKey, request);
6600
+ let route = this._getRoute(request);
6601
+ let { response } = request;
6602
+ if (response)
6603
+ route.updateVary(response);
6604
+ let superseded = route.requests.filter((oldRequest) => route.satisfies(request, oldRequest));
6605
+ for (let r of superseded) {
6606
+ this._delete(r);
6607
+ }
6608
+ request.cacheRoute = route;
6609
+ route.put(request);
6610
+ this._requests.push(request);
6611
+ this._limitSize();
6605
6612
  });
6606
6613
  }
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
6614
  alias(existingCachedRequest, newRequest) {
6636
6615
  existingCachedRequest = this.get(existingCachedRequest);
6637
6616
  if (!existingCachedRequest)
@@ -6648,7 +6627,7 @@ up.Request.Cache = class Cache {
6648
6627
  newRequest.state = 'tracking';
6649
6628
  let value = yield u.always(existingRequest);
6650
6629
  if (value instanceof up.Response) {
6651
- if (options.force || this._isCacheCompatible(existingRequest, newRequest)) {
6630
+ if (options.force || existingRequest.cacheRoute.satisfies(existingRequest, newRequest)) {
6652
6631
  newRequest.fromCache = true;
6653
6632
  value = u.variant(value, { request: newRequest });
6654
6633
  newRequest.respondWith(value);
@@ -6669,31 +6648,45 @@ up.Request.Cache = class Cache {
6669
6648
  willHaveSameResponse(existingRequest, newRequest) {
6670
6649
  return existingRequest === newRequest || existingRequest === newRequest.trackedRequest;
6671
6650
  }
6672
- _delete(request) {
6673
- request = this._wrap(request);
6674
- let cacheKey = this._cacheKey(request);
6675
- this._map.delete(cacheKey);
6676
- }
6677
6651
  evict(condition = true, testerOptions) {
6678
6652
  this._eachMatch(condition, testerOptions, (request) => this._delete(request));
6679
6653
  }
6680
6654
  expire(condition = true, testerOptions) {
6681
6655
  this._eachMatch(condition, testerOptions, (request) => request.expired = true);
6682
6656
  }
6683
- _makeRoom() {
6684
- while (this._map.size >= this._capacity) {
6685
- let oldestKey = this._map.keys().next().value;
6686
- this._map.delete(oldestKey);
6657
+ reindex(request) {
6658
+ this._delete(request);
6659
+ this.put(request);
6660
+ }
6661
+ _delete(request) {
6662
+ var _a;
6663
+ u.remove(this._requests, request);
6664
+ (_a = request.cacheRoute) === null || _a === void 0 ? void 0 : _a.delete(request);
6665
+ delete request.cacheRoute;
6666
+ }
6667
+ _getRoute(request) {
6668
+ var _a, _b;
6669
+ return request.cacheRoute || ((_a = this._routes)[_b = request.description] || (_a[_b] = new Route()));
6670
+ }
6671
+ _isUsable(request) {
6672
+ return request.age < up.network.config.cacheEvictAge;
6673
+ }
6674
+ get _size() {
6675
+ return this._requests.length;
6676
+ }
6677
+ get _capacity() {
6678
+ return up.network.config.cacheSize;
6679
+ }
6680
+ _limitSize() {
6681
+ for (let i = 0; i < (this._size - this._capacity); i++) {
6682
+ this._delete(this._requests[0]);
6687
6683
  }
6688
6684
  }
6689
6685
  _eachMatch(condition = true, testerOptions, fn) {
6690
6686
  let tester = up.Request.tester(condition, testerOptions);
6691
- let results = u.filter(this._map.values(), tester);
6687
+ let results = u.filter(this._requests, tester);
6692
6688
  u.each(results, fn);
6693
6689
  }
6694
- _isCacheCompatible(request1, request2) {
6695
- return this._cacheKey(request1) === this._cacheKey(request2);
6696
- }
6697
6690
  _wrap(requestOrOptions) {
6698
6691
  return u.wrapValue(up.Request, requestOrOptions);
6699
6692
  }
@@ -6722,7 +6715,7 @@ up.Request.Queue = class Queue {
6722
6715
  u.always(request, responseOrError => this._onRequestSettled(request, responseOrError));
6723
6716
  this._scheduleSlowTimer(request);
6724
6717
  this._queueRequest(request);
6725
- u.microtask(() => this._poke());
6718
+ queueMicrotask(() => this._poke());
6726
6719
  }
6727
6720
  promoteToForeground(request) {
6728
6721
  if (request.background) {
@@ -6763,7 +6756,7 @@ up.Request.Queue = class Queue {
6763
6756
  up.network.registerAliasForRedirect(request, responseOrError);
6764
6757
  }
6765
6758
  this._checkLate();
6766
- u.microtask(() => this._poke());
6759
+ queueMicrotask(() => this._poke());
6767
6760
  }
6768
6761
  _poke() {
6769
6762
  let request;
@@ -6959,16 +6952,13 @@ up.Response = class Response extends up.Record {
6959
6952
  get none() {
6960
6953
  return !this.text;
6961
6954
  }
6962
- isCacheable() {
6963
- return this.ok && !this.none;
6964
- }
6965
6955
  header(name) {
6966
6956
  var _a;
6967
6957
  return this.headers[name] || ((_a = this.xhr) === null || _a === void 0 ? void 0 : _a.getResponseHeader(name));
6968
6958
  }
6969
- get ownInfluncingHeaders() {
6970
- let influencingHeaders = up.protocol.influencingHeadersFromResponse(this);
6971
- return u.filter(influencingHeaders, (headerName) => this.request.header(headerName));
6959
+ get varyHeaderNames() {
6960
+ let varyHeaderValue = this.header('Vary');
6961
+ return u.parseTokens(varyHeaderValue, { separator: 'comma' });
6972
6962
  }
6973
6963
  get contentType() {
6974
6964
  return this.header('Content-Type');
@@ -7009,6 +6999,7 @@ up.Response = class Response extends up.Record {
7009
6999
  var _a;
7010
7000
  const u = up.util;
7011
7001
  const e = up.element;
7002
+ const FULL_DOCUMENT_PATTERN = /^\s*<(html|!DOCTYPE)\b/i;
7012
7003
  up.ResponseDoc = (_a = class ResponseDoc {
7013
7004
  constructor({ document, fragment, content, target, origin, cspNonces, match }) {
7014
7005
  if (document) {
@@ -7029,43 +7020,43 @@ up.ResponseDoc = (_a = class ResponseDoc {
7029
7020
  }
7030
7021
  this._match = match;
7031
7022
  }
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;
7023
+ _parseDocument(value) {
7024
+ if (value instanceof Document) {
7025
+ this._document = value;
7026
+ this._isFullDocument = true;
7027
+ }
7028
+ else if (u.isString(value)) {
7029
+ this._document = e.createBrokenDocumentFromHTML(value);
7030
+ this._isFullDocument = FULL_DOCUMENT_PATTERN.test(value);
7031
+ this._isDocumentBroken = true;
7048
7032
  }
7049
7033
  else {
7050
- matchingElement.appendChild(content);
7034
+ this._document = this._buildFauxDocument(value);
7035
+ this._isFullDocument = value.matches('html');
7051
7036
  }
7052
- this._useParseResult(matchingElement);
7053
7037
  }
7054
- _parse(value, parseFn) {
7055
- if (u.isString(value)) {
7056
- value = parseFn(value);
7057
- }
7058
- return value;
7038
+ _parseFragment(value) {
7039
+ let parsed = u.isString(value) ? e.createFromHTML(value) : value;
7040
+ this._document = this._buildFauxDocument(parsed);
7059
7041
  }
7060
- _useParseResult(node) {
7061
- if (node instanceof Document) {
7062
- this._document = node;
7042
+ _parseContent(value, target) {
7043
+ if (!target)
7044
+ up.fail("must pass a { target } when passing { content }");
7045
+ let simplifiedTarget = u.map(up.fragment.parseTargetSteps(target), 'selector').join();
7046
+ const matchingElement = e.createFromSelector(simplifiedTarget);
7047
+ if (u.isString(value)) {
7048
+ matchingElement.innerHTML = value;
7063
7049
  }
7064
7050
  else {
7065
- this._document = document.createElement('up-document');
7066
- this._document.append(node);
7067
- this._document.documentElement = node;
7051
+ matchingElement.appendChild(value);
7068
7052
  }
7053
+ this._document = this._buildFauxDocument(matchingElement);
7054
+ }
7055
+ _buildFauxDocument(node) {
7056
+ let fauxDocument = document.createElement('up-document');
7057
+ fauxDocument.append(node);
7058
+ fauxDocument.documentElement = node;
7059
+ return fauxDocument;
7069
7060
  }
7070
7061
  rootSelector() {
7071
7062
  return up.fragment.toTarget(this._document.documentElement);
@@ -7074,9 +7065,8 @@ up.ResponseDoc = (_a = class ResponseDoc {
7074
7065
  return this._fromHead(this._getTitleText);
7075
7066
  }
7076
7067
  _getHead() {
7077
- let { head } = this._document;
7078
- if (head && head.childNodes.length > 0) {
7079
- return head;
7068
+ if (this._isFullDocument) {
7069
+ return this._document.head;
7080
7070
  }
7081
7071
  }
7082
7072
  _fromHead(fn) {
@@ -7089,6 +7079,11 @@ up.ResponseDoc = (_a = class ResponseDoc {
7089
7079
  get assets() {
7090
7080
  return this._fromHead(up.script.findAssets);
7091
7081
  }
7082
+ get lang() {
7083
+ if (this._isFullDocument) {
7084
+ return up.history.getLang(this._document);
7085
+ }
7086
+ }
7092
7087
  _getTitleText(head) {
7093
7088
  var _b;
7094
7089
  return (_b = head.querySelector('title')) === null || _b === void 0 ? void 0 : _b.textContent;
@@ -7188,7 +7183,7 @@ up.RevealMotion = class RevealMotion {
7188
7183
  const maxPixels = u.evalOption(this._max, this._element);
7189
7184
  elementRect.height = Math.min(elementRect.height, maxPixels);
7190
7185
  }
7191
- this._addPadding(elementRect);
7186
+ elementRect.grow(this._padding);
7192
7187
  this._substractObstructions(viewportRect);
7193
7188
  if (viewportRect.height < 0) {
7194
7189
  up.fail('Viewport has no visible area');
@@ -7227,10 +7222,6 @@ up.RevealMotion = class RevealMotion {
7227
7222
  return up.Rect.fromElement(this._viewport);
7228
7223
  }
7229
7224
  }
7230
- _addPadding(elementRect) {
7231
- elementRect.top -= this._padding;
7232
- elementRect.height += 2 * this._padding;
7233
- }
7234
7225
  _selectObstructions(selector) {
7235
7226
  let elements = up.fragment.all(selector, { layer: this._obstructionsLayer });
7236
7227
  return u.filter(elements, e.isVisible);
@@ -7368,10 +7359,10 @@ up.Tether = class Tether {
7368
7359
  sync() {
7369
7360
  const elementBox = this._element.getBoundingClientRect();
7370
7361
  const elementMargin = {
7371
- top: e.styleNumber(this._element, 'marginTop'),
7372
- right: e.styleNumber(this._element, 'marginRight'),
7373
- bottom: e.styleNumber(this._element, 'marginBottom'),
7374
- left: e.styleNumber(this._element, 'marginLeft')
7362
+ top: e.styleNumber(this._element, 'margin-top'),
7363
+ right: e.styleNumber(this._element, 'margin-right'),
7364
+ bottom: e.styleNumber(this._element, 'margin-bottom'),
7365
+ left: e.styleNumber(this._element, 'margin-left')
7375
7366
  };
7376
7367
  const anchorBox = this._anchor.getBoundingClientRect();
7377
7368
  let left;
@@ -7439,7 +7430,7 @@ up.Tether = class Tether {
7439
7430
  _setOffset(left, top) {
7440
7431
  this.offsetLeft = left;
7441
7432
  this.offsetTop = top;
7442
- e.setStyle(this._element, { left, top });
7433
+ e.setStyle(this._element, { left, top }, 'px');
7443
7434
  }
7444
7435
  };
7445
7436
 
@@ -7783,10 +7774,6 @@ up.protocol = (function () {
7783
7774
  function locationFromXHR(xhr) {
7784
7775
  return extractHeader(xhr, 'location') || xhr.responseURL;
7785
7776
  }
7786
- function influencingHeadersFromResponse(response) {
7787
- let varyHeaderValue = response.header('Vary');
7788
- return u.parseTokens(varyHeaderValue, { separator: 'comma' });
7789
- }
7790
7777
  const config = new up.Config(() => ({
7791
7778
  methodParam: '_method',
7792
7779
  csrfParam() { return e.metaContent('csrf-param'); },
@@ -7847,7 +7834,6 @@ up.protocol = (function () {
7847
7834
  headerize,
7848
7835
  wrapMethod,
7849
7836
  cspNoncesFromHeader,
7850
- influencingHeadersFromResponse,
7851
7837
  };
7852
7838
  })();
7853
7839
 
@@ -7983,44 +7969,61 @@ up.script = (function () {
7983
7969
  let registeredCompilers = [];
7984
7970
  let registeredMacros = [];
7985
7971
  function registerCompiler(...args) {
7986
- const compiler = buildCompiler(args);
7987
- return insertCompiler(registeredCompilers, compiler);
7972
+ registerProcessor(args);
7988
7973
  }
7989
7974
  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);
7975
+ registerProcessor(args, { macro: true });
7976
+ }
7977
+ function registerAttrCompiler(...args) {
7978
+ let [attr, options, valueCallback] = parseProcessorArgs(args);
7979
+ let selector = `[${attr}]`;
7980
+ let callback = (element) => {
7981
+ let value = e.booleanOrStringAttr(element, attr, options.defaultValue);
7982
+ if (!value)
7983
+ return;
7984
+ return valueCallback(element, value);
7985
+ };
7986
+ registerProcessor([selector, options, callback]);
7996
7987
  }
7997
7988
  function detectSystemMacroPriority(macroSelector) {
7998
7989
  macroSelector = u.evalOption(macroSelector);
7999
7990
  for (let substr in SYSTEM_MACRO_PRIORITIES) {
8000
- const priority = SYSTEM_MACRO_PRIORITIES[substr];
8001
7991
  if (macroSelector.indexOf(substr) >= 0) {
8002
- return priority;
7992
+ return SYSTEM_MACRO_PRIORITIES[substr];
8003
7993
  }
8004
7994
  }
7995
+ up.fail('Unregistered priority for system macro %o', macroSelector);
8005
7996
  }
8006
- const parseCompilerArgs = function (args) {
7997
+ function registerProcessor(args, overrides = {}) {
7998
+ let processor = buildProcessor(args, overrides);
7999
+ if (processor.macro) {
8000
+ if (up.framework.evaling) {
8001
+ processor.priority || (processor.priority = detectSystemMacroPriority(processor.selector));
8002
+ }
8003
+ insertProcessor(registeredMacros, processor);
8004
+ }
8005
+ else {
8006
+ insertProcessor(registeredCompilers, processor);
8007
+ }
8008
+ }
8009
+ const parseProcessorArgs = function (args) {
8007
8010
  const defaults = u.extractOptions(args);
8008
8011
  const selector = args.shift();
8009
8012
  const callback = args.pop();
8010
8013
  const options = Object.assign(Object.assign({}, defaults), u.extractOptions(args));
8011
8014
  return [selector, options, callback];
8012
8015
  };
8013
- function buildCompiler(args) {
8014
- let [selector, options, callback] = parseCompilerArgs(args);
8016
+ function buildProcessor(args, overrides) {
8017
+ let [selector, options, callback] = parseProcessorArgs(args);
8015
8018
  options = u.options(options, {
8016
8019
  selector,
8017
8020
  isDefault: up.framework.evaling,
8018
8021
  priority: 0,
8019
8022
  batch: false,
8020
8023
  });
8021
- return Object.assign(callback, options);
8024
+ return Object.assign(callback, options, overrides);
8022
8025
  }
8023
- function insertCompiler(queue, newCompiler) {
8026
+ function insertProcessor(queue, newCompiler) {
8024
8027
  let existingCompiler;
8025
8028
  let index = 0;
8026
8029
  while ((existingCompiler = queue[index]) && (existingCompiler.priority >= newCompiler.priority)) {
@@ -8114,6 +8117,7 @@ up.script = (function () {
8114
8117
  config,
8115
8118
  compiler: registerCompiler,
8116
8119
  macro: registerMacro,
8120
+ attrCompiler: registerAttrCompiler,
8117
8121
  destructor: registerDestructor,
8118
8122
  hello,
8119
8123
  clean,
@@ -8128,6 +8132,7 @@ up.destructor = up.script.destructor;
8128
8132
  up.macro = up.script.macro;
8129
8133
  up.data = up.script.data;
8130
8134
  up.hello = up.script.hello;
8135
+ up.attribute = up.script.attrCompiler;
8131
8136
 
8132
8137
 
8133
8138
  /***/ }),
@@ -8218,10 +8223,8 @@ up.history = (function () {
8218
8223
  return;
8219
8224
  }
8220
8225
  let location = currentLocation();
8221
- if (up.emit('up:location:restore', { location, log: `Restoring location ${location}` }).defaultPrevented) {
8222
- return;
8223
- }
8224
8226
  up.render({
8227
+ guardEvent: up.event.build('up:location:restore', { location, log: `Restoring location ${location}` }),
8225
8228
  url: location,
8226
8229
  target: config.restoreTargets,
8227
8230
  fail: false,
@@ -8229,7 +8232,8 @@ up.history = (function () {
8229
8232
  location,
8230
8233
  peel: true,
8231
8234
  layer: 'root',
8232
- cache: true,
8235
+ cache: 'auto',
8236
+ revalidate: 'auto',
8233
8237
  saveScroll: false,
8234
8238
  scroll: ['restore', 'auto'],
8235
8239
  saveFocus: false,
@@ -8270,6 +8274,15 @@ up.history = (function () {
8270
8274
  document.head.append(newMetaTag);
8271
8275
  }
8272
8276
  }
8277
+ function getLang(doc = document) {
8278
+ let { documentElement } = doc;
8279
+ if (documentElement.matches('html')) {
8280
+ return doc.documentElement.lang;
8281
+ }
8282
+ }
8283
+ function updateLang(newLang) {
8284
+ e.toggleAttr(e.root, 'lang', newLang, !!newLang);
8285
+ }
8273
8286
  up.macro('a[up-back], [up-href][up-back]', function (link) {
8274
8287
  if (previousLocation) {
8275
8288
  e.setMissingAttrs(link, {
@@ -8291,6 +8304,8 @@ up.history = (function () {
8291
8304
  isLocation,
8292
8305
  findMetaTags,
8293
8306
  updateMetaTags,
8307
+ getLang,
8308
+ updateLang,
8294
8309
  };
8295
8310
  })();
8296
8311
 
@@ -8773,6 +8788,25 @@ up.fragment = (function () {
8773
8788
  up.destructor(fragment, unsubscribe);
8774
8789
  return unsubscribe;
8775
8790
  }
8791
+ function onFirstIntersect(origin, callback, { margin = 0 } = {}) {
8792
+ if (e.isIntersectingWindow(origin, { margin })) {
8793
+ callback();
8794
+ return;
8795
+ }
8796
+ function processIntersectEntries(entries) {
8797
+ for (let entry of entries) {
8798
+ if (entry.isIntersecting) {
8799
+ disconnect();
8800
+ callback();
8801
+ return;
8802
+ }
8803
+ }
8804
+ }
8805
+ let observer = new IntersectionObserver(processIntersectEntries, { rootMargin: `${margin}px` });
8806
+ let disconnect = () => observer.disconnect();
8807
+ observer.observe(origin);
8808
+ onAborted(origin, disconnect);
8809
+ }
8776
8810
  up.on('up:framework:boot', function () {
8777
8811
  const { documentElement } = document;
8778
8812
  documentElement.setAttribute('up-source', u.normalizeURL(location.href, { hash: false }));
@@ -8813,6 +8847,7 @@ up.fragment = (function () {
8813
8847
  shouldRevalidate,
8814
8848
  abort,
8815
8849
  onAborted,
8850
+ onFirstIntersect,
8816
8851
  splitTarget,
8817
8852
  parseTargetSteps,
8818
8853
  isAlive,
@@ -8942,33 +8977,9 @@ up.viewport = (function () {
8942
8977
  function isRoot(element) {
8943
8978
  return element === getRoot();
8944
8979
  }
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
- });
8980
+ function rootScrollbarWidth() {
8981
+ return window.innerWidth - rootWidth();
8982
+ }
8972
8983
  function scrollTopKey(viewport) {
8973
8984
  return up.fragment.tryToTarget(viewport);
8974
8985
  }
@@ -9085,7 +9096,7 @@ up.viewport = (function () {
9085
9096
  const moveBounds = function (diffX, diffY) {
9086
9097
  boundsRect.left += diffX;
9087
9098
  boundsRect.top += diffY;
9088
- return e.setStyle(bounds, boundsRect);
9099
+ return e.setStyle(bounds, boundsRect, 'px');
9089
9100
  };
9090
9101
  moveBounds(0, 0);
9091
9102
  const newElementRect = element.getBoundingClientRect();
@@ -9146,10 +9157,8 @@ up.viewport = (function () {
9146
9157
  get root() { return getRoot(); },
9147
9158
  rootWidth,
9148
9159
  rootHeight,
9149
- rootHasReducedWidthFromScrollbar,
9150
- rootOverflowElement,
9151
9160
  isRoot,
9152
- scrollbarWidth,
9161
+ rootScrollbarWidth,
9153
9162
  saveScroll,
9154
9163
  restoreScroll,
9155
9164
  resetScroll,
@@ -9234,13 +9243,16 @@ up.motion = (function () {
9234
9243
  return Promise.resolve();
9235
9244
  }
9236
9245
  function animateNow(element, lastFrame, options) {
9246
+ if (up.migrate.loaded)
9247
+ lastFrame = up.migrate.fixStyleProps(lastFrame);
9237
9248
  options = Object.assign(Object.assign({}, options), { finishEvent: motionController.finishEvent });
9238
9249
  const cssTransition = new up.CSSTransition(element, lastFrame, options);
9239
9250
  return cssTransition.start();
9240
9251
  }
9241
9252
  function applyConfig(options) {
9242
- options.easing || (options.easing = config.easing);
9243
- options.duration || (options.duration = config.duration);
9253
+ var _a, _b;
9254
+ (_a = options.easing) !== null && _a !== void 0 ? _a : (options.easing = config.easing);
9255
+ (_b = options.duration) !== null && _b !== void 0 ? _b : (options.duration = config.duration);
9244
9256
  }
9245
9257
  function findNamedAnimation(name) {
9246
9258
  return namedAnimations[name] || up.fail("Unknown animation %o", name);
@@ -9390,7 +9402,7 @@ up.motion = (function () {
9390
9402
  return { transform: `translate(${dx}px, ${dy}px)` };
9391
9403
  }
9392
9404
  function noTranslateCSS() {
9393
- return { transform: null };
9405
+ return { transform: '' };
9394
9406
  }
9395
9407
  function untranslatedBox(element) {
9396
9408
  e.setStyle(element, noTranslateCSS());
@@ -9510,6 +9522,7 @@ up.network = (function () {
9510
9522
  if (!newRequest.background) {
9511
9523
  queue.promoteToForeground(cachedRequest);
9512
9524
  }
9525
+ cachedRequest.mergeIfUnsent(newRequest);
9513
9526
  cache.track(cachedRequest, newRequest, { onIncompatible: processRequest });
9514
9527
  return true;
9515
9528
  }
@@ -9522,10 +9535,10 @@ up.network = (function () {
9522
9535
  function handleCaching(request) {
9523
9536
  if (request.willCache()) {
9524
9537
  cache.put(request);
9525
- request.onLoading = () => cache.put(request);
9538
+ request.onLoading = () => cache.reindex(request);
9526
9539
  }
9527
9540
  u.always(request, function (responseOrError) {
9528
- var _a, _b, _c, _d, _e;
9541
+ var _a, _b, _c, _d;
9529
9542
  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
9543
  if (expireCache) {
9531
9544
  cache.expire(expireCache, { except: request });
@@ -9534,12 +9547,21 @@ up.network = (function () {
9534
9547
  if (evictCache) {
9535
9548
  cache.evict(evictCache, { except: request });
9536
9549
  }
9537
- if (cache.get(request)) {
9538
- cache.put(request);
9550
+ let hasCacheEntry = cache.get(request);
9551
+ let isResponse = responseOrError instanceof up.Response;
9552
+ let isNetworkError = !isResponse;
9553
+ let isSuccessResponse = isResponse && responseOrError.ok;
9554
+ let isErrorResponse = isResponse && !responseOrError.ok;
9555
+ let isEmptyResponse = isResponse && responseOrError.none;
9556
+ if (isErrorResponse) {
9557
+ cache.evict(request.url);
9539
9558
  }
9540
- if (!((_e = responseOrError.isCacheable) === null || _e === void 0 ? void 0 : _e.call(responseOrError))) {
9559
+ else if (isNetworkError || isEmptyResponse) {
9541
9560
  cache.evict(request);
9542
9561
  }
9562
+ else if (isSuccessResponse && hasCacheEntry) {
9563
+ cache.put(request);
9564
+ }
9543
9565
  });
9544
9566
  }
9545
9567
  function isBusy() {
@@ -9557,7 +9579,8 @@ up.network = (function () {
9557
9579
  if (request.cache && response.url && request.url !== response.url) {
9558
9580
  const newRequest = u.variant(request, {
9559
9581
  method: response.method,
9560
- url: response.url
9582
+ url: response.url,
9583
+ cacheRoute: null,
9561
9584
  });
9562
9585
  cache.alias(request, newRequest);
9563
9586
  }
@@ -9864,7 +9887,6 @@ __webpack_require__(96);
9864
9887
  up.link = (function () {
9865
9888
  const u = up.util;
9866
9889
  const e = up.element;
9867
- const linkPreloader = new up.LinkPreloader();
9868
9890
  let lastMousedownTarget = null;
9869
9891
  const LINKS_WITH_LOCAL_HTML = ['a[up-content]', 'a[up-fragment]', 'a[up-document]'];
9870
9892
  const LINKS_WITH_REMOTE_HTML = ['a[href]', '[up-href]'];
@@ -9898,10 +9920,9 @@ up.link = (function () {
9898
9920
  }
9899
9921
  function reset() {
9900
9922
  lastMousedownTarget = null;
9901
- linkPreloader.reset();
9902
9923
  }
9903
- const follow = up.mockable(function (link, options) {
9904
- return up.render(followOptions(link, options));
9924
+ const follow = up.mockable(function (link, options, parserOptions) {
9925
+ return up.render(followOptions(link, options, parserOptions));
9905
9926
  });
9906
9927
  function parseRequestOptions(link, options, parserOptions) {
9907
9928
  options = u.options(options);
@@ -9923,6 +9944,7 @@ up.link = (function () {
9923
9944
  return options;
9924
9945
  }
9925
9946
  function followOptions(link, options, parserOptions) {
9947
+ var _a;
9926
9948
  link = up.fragment.get(link);
9927
9949
  options = u.options(options);
9928
9950
  const parser = new up.OptionsParser(link, options, Object.assign({ fail: true }, parserOptions));
@@ -9976,10 +9998,9 @@ up.link = (function () {
9976
9998
  parser.booleanOrString('location');
9977
9999
  parser.booleanOrString('title');
9978
10000
  parser.boolean('metaTags');
10001
+ parser.booleanOrString('lang');
9979
10002
  parser.include(up.motion.motionOptions);
9980
- if (!options.guardEvent) {
9981
- options.guardEvent = up.event.build('up:link:follow', { log: 'Following link' });
9982
- }
10003
+ (_a = options.guardEvent) !== null && _a !== void 0 ? _a : (options.guardEvent = up.event.build('up:link:follow', { log: ['Following link %o', link] }));
9983
10004
  return options;
9984
10005
  }
9985
10006
  function preload(link, options) {
@@ -10018,9 +10039,10 @@ up.link = (function () {
10018
10039
  if (link.matches('a[href], button')) {
10019
10040
  return;
10020
10041
  }
10042
+ let role = link.matches('a') ? 'link' : 'button';
10021
10043
  e.setMissingAttrs(link, {
10022
10044
  tabindex: '0',
10023
- role: 'link',
10045
+ role,
10024
10046
  'up-clickable': ''
10025
10047
  });
10026
10048
  link.addEventListener('keydown', function (event) {
@@ -10080,6 +10102,38 @@ up.link = (function () {
10080
10102
  const method = followMethod(link);
10081
10103
  return up.network.isSafeMethod(method);
10082
10104
  }
10105
+ function onLoadCondition(condition, link, callback) {
10106
+ switch (condition) {
10107
+ case 'insert':
10108
+ callback();
10109
+ break;
10110
+ case 'reveal': {
10111
+ let margin = e.numberAttr(link, 'up-intersect-margin');
10112
+ up.fragment.onFirstIntersect(link, callback, { margin });
10113
+ break;
10114
+ }
10115
+ case 'hover':
10116
+ new up.LinkFollowIntent(link, callback);
10117
+ break;
10118
+ case 'manual':
10119
+ break;
10120
+ }
10121
+ }
10122
+ function loadDeferred(link, options) {
10123
+ let guardEvent = up.event.build('up:deferred:load', { log: ['Loading deferred %o', link] });
10124
+ let forcedOptions = Object.assign({ navigate: false, guardEvent }, options);
10125
+ let defaults = {
10126
+ target: ':origin',
10127
+ cache: 'auto',
10128
+ revalidate: 'auto',
10129
+ feedback: true,
10130
+ };
10131
+ return follow(link, forcedOptions, { defaults });
10132
+ }
10133
+ up.attribute('up-defer', { defaultValue: 'insert' }, function (link, condition) {
10134
+ let doLoad = () => up.error.muteUncriticalRejection(loadDeferred(link));
10135
+ onLoadCondition(condition, link, doLoad);
10136
+ });
10083
10137
  up.on('up:click', config.selectorFn('followSelectors'), function (event, link) {
10084
10138
  if (shouldFollowEvent(event, link)) {
10085
10139
  up.event.halt(event, { log: true });
@@ -10087,21 +10141,20 @@ up.link = (function () {
10087
10141
  up.error.muteUncriticalRejection(follow(link));
10088
10142
  }
10089
10143
  });
10090
- up.macro('[up-expand]', function (area) {
10091
- const selector = area.getAttribute('up-expand') || 'a, [up-href]';
10092
- let childLink = e.get(area, selector);
10144
+ up.attribute('up-expand', { defaultValue: 'a, [up-href]', macro: true }, function (area, childLinkSelector) {
10145
+ let childLink = e.get(area, childLinkSelector);
10093
10146
  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);
10147
+ e.setMissingAttrs(area, Object.assign({ 'up-href': e.attr(childLink, 'href') }, e.upAttrs(childLink)));
10148
+ area.classList.add(...e.upClasses(childLink));
10099
10149
  makeFollowable(area);
10100
10150
  }
10101
10151
  });
10102
10152
  up.compiler(config.selectorFn('preloadSelectors'), function (link) {
10153
+ var _a;
10103
10154
  if (!isPreloadDisabled(link)) {
10104
- linkPreloader.watchLink(link);
10155
+ let doPreload = () => up.error.muteUncriticalRejection(preload(link));
10156
+ let condition = (_a = e.booleanOrStringAttr(link, 'up-preload', null)) !== null && _a !== void 0 ? _a : 'hover';
10157
+ onLoadCondition(condition, link, doPreload);
10105
10158
  }
10106
10159
  });
10107
10160
  up.on('up:framework:reset', reset);
@@ -10110,18 +10163,17 @@ up.link = (function () {
10110
10163
  followOptions,
10111
10164
  preload,
10112
10165
  makeFollowable,
10113
- makeClickable,
10114
10166
  isSafe,
10115
10167
  isFollowable,
10116
10168
  shouldFollowEvent,
10117
- followMethod,
10118
10169
  convertClicks,
10119
10170
  config,
10120
10171
  combineFollowableSelectors,
10121
- preloadIssue,
10172
+ loadDeferred,
10122
10173
  };
10123
10174
  })();
10124
10175
  up.follow = up.link.follow;
10176
+ up.deferred = { load: up.link.loadDeferred };
10125
10177
 
10126
10178
 
10127
10179
  /***/ }),
@@ -10194,7 +10246,8 @@ up.form = (function () {
10194
10246
  options.guardEvent || (options.guardEvent = up.event.build('up:form:submit', {
10195
10247
  submitButton: options.submitButton,
10196
10248
  log: 'Submitting form',
10197
- params: options.params
10249
+ params: options.params,
10250
+ form,
10198
10251
  }));
10199
10252
  options.origin || (options.origin = up.viewport.focusedElementWithin(form) || options.submitButton || form);
10200
10253
  parser.include(up.link.followOptions);
@@ -10469,7 +10522,9 @@ up.form = (function () {
10469
10522
  validator.watchContainer(fieldOrForm);
10470
10523
  });
10471
10524
  function validatingFieldSelector() {
10472
- return config.fieldSelectors.map((selector) => `${selector}[up-validate], [up-validate] ${selector}`).join(', ');
10525
+ let includes = config.fieldSelectors.map((selector) => `${selector}[up-validate], [up-validate] ${selector}`);
10526
+ let excludes = ['[up-validate=false]'];
10527
+ return e.unionSelector(includes, excludes);
10473
10528
  }
10474
10529
  up.compiler('[up-switch]', (switcher) => {
10475
10530
  switchTargets(switcher);
@@ -10480,8 +10535,8 @@ up.form = (function () {
10480
10535
  up.compiler('[up-show-for]:not(.up-switched), [up-hide-for]:not(.up-switched)', (element) => {
10481
10536
  switchTarget(element);
10482
10537
  });
10483
- up.compiler('[up-watch]', (formOrField) => watch(formOrField));
10484
- up.compiler('[up-autosubmit]', (formOrField) => autosubmit(formOrField));
10538
+ up.attribute('up-watch', (formOrField) => watch(formOrField));
10539
+ up.attribute('up-autosubmit', (formOrField) => autosubmit(formOrField));
10485
10540
  return {
10486
10541
  config,
10487
10542
  submit,
@@ -10523,6 +10578,7 @@ up.feedback = (function () {
10523
10578
  const config = new up.Config(() => ({
10524
10579
  currentClasses: ['up-current'],
10525
10580
  navSelectors: ['[up-nav]', 'nav'],
10581
+ noNavSelectors: ['[up-nav=false]'],
10526
10582
  }));
10527
10583
  function reset() {
10528
10584
  up.layer.root.feedbackLocation = null;
@@ -10530,9 +10586,6 @@ up.feedback = (function () {
10530
10586
  const CLASS_ACTIVE = 'up-active';
10531
10587
  const CLASS_LOADING = 'up-loading';
10532
10588
  const SELECTOR_LINK = 'a, [up-href]';
10533
- function navSelector() {
10534
- return config.selector('navSelectors');
10535
- }
10536
10589
  function normalizeURL(url) {
10537
10590
  if (url) {
10538
10591
  return u.normalizeURL(url, { trailingSlash: false, hash: false });
@@ -10541,40 +10594,23 @@ up.feedback = (function () {
10541
10594
  function linkURLs(link) {
10542
10595
  return link.upFeedbackURLs || (link.upFeedbackURLs = new up.LinkFeedbackURLs(link));
10543
10596
  }
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);
10597
+ function updateFragment(fragment, { layer } = {}) {
10598
+ layer || (layer = up.layer.get(fragment));
10599
+ let layerLocation = getNormalizedLayerLocation(layer);
10600
+ const navSelector = config.selector('navSelectors');
10601
+ const navLinkSelector = `${navSelector} :is(${SELECTOR_LINK}), ${navSelector}:is(${SELECTOR_LINK})`;
10602
+ const links = up.fragment.all(navLinkSelector, { layer });
10603
+ for (let link of links) {
10604
+ const isCurrent = linkURLs(link).isCurrent(layerLocation);
10605
+ for (let currentClass of config.currentClasses) {
10606
+ link.classList.toggle(currentClass, isCurrent);
10607
+ }
10608
+ e.toggleAttr(link, 'aria-current', 'page', isCurrent);
10552
10609
  }
10553
10610
  }
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
10611
  function getNormalizedLayerLocation(layer) {
10560
10612
  return layer.feedbackLocation || normalizeURL(layer.location);
10561
10613
  }
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
10614
  function findActivatableArea(element) {
10579
10615
  return e.ancestor(element, SELECTOR_LINK) || element;
10580
10616
  }
@@ -10602,7 +10638,7 @@ up.feedback = (function () {
10602
10638
  const layerLocation = getNormalizedLayerLocation(layer.location);
10603
10639
  if (!processedLocation || (processedLocation !== layerLocation)) {
10604
10640
  layer.feedbackLocation = layerLocation;
10605
- updateLinksWithinNavs(layer.element, { layer });
10641
+ updateFragment(layer.element, { layer });
10606
10642
  }
10607
10643
  }
10608
10644
  function onBrowserLocationChanged() {
@@ -10637,6 +10673,7 @@ up.radio = (function () {
10637
10673
  const e = up.element;
10638
10674
  const config = new up.Config(() => ({
10639
10675
  hungrySelectors: ['[up-hungry]'],
10676
+ noHungrySelectors: ['[up-hungry=false]'],
10640
10677
  pollInterval: 30000,
10641
10678
  }));
10642
10679
  function hungrySteps(renderOptions) {
@@ -10682,7 +10719,7 @@ up.radio = (function () {
10682
10719
  parser.string('ifLayer', { default: 'front' });
10683
10720
  return options;
10684
10721
  }
10685
- up.compiler('[up-poll]:not([up-poll=false])', function (fragment) {
10722
+ up.attribute('up-poll', function (fragment) {
10686
10723
  up.FragmentPolling.forFragment(fragment).onPollAttributeObserved();
10687
10724
  });
10688
10725
  up.macro('[up-flashes]', function (fragment) {