unpoly-rails 3.10.2 → 3.11.0.rc12

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.10.2'
8
+ version: '3.11.0-rc12'
9
9
  };
10
10
 
11
11
 
@@ -116,7 +116,7 @@ up.util = (function () {
116
116
  }
117
117
  function iteratee(block) {
118
118
  if (isString(block)) {
119
- return item => item[block];
119
+ return (item) => item[block];
120
120
  }
121
121
  else {
122
122
  return block;
@@ -135,11 +135,7 @@ up.util = (function () {
135
135
  return mapped;
136
136
  }
137
137
  function mapObject(array, pairer) {
138
- const merger = function (object, pair) {
139
- object[pair[0]] = pair[1];
140
- return object;
141
- };
142
- return map(array, pairer).reduce(merger, {});
138
+ return Object.fromEntries(array.map(pairer));
143
139
  }
144
140
  function each(array, block) {
145
141
  let i = 0;
@@ -147,15 +143,18 @@ up.util = (function () {
147
143
  block(item, i++);
148
144
  }
149
145
  }
150
- function isNull(object) {
151
- return object === null;
146
+ function isNull(value) {
147
+ return value === null;
148
+ }
149
+ function isTruthy(value) {
150
+ return !!value;
152
151
  }
153
- function isUndefined(object) {
154
- return object === undefined;
152
+ function isUndefined(value) {
153
+ return value === undefined;
155
154
  }
156
155
  const isDefined = negate(isUndefined);
157
- function isMissing(object) {
158
- return isUndefined(object) || isNull(object);
156
+ function isMissing(value) {
157
+ return isUndefined(value) || isNull(value);
159
158
  }
160
159
  const isGiven = negate(isMissing);
161
160
  function isBlank(value) {
@@ -180,49 +179,49 @@ up.util = (function () {
180
179
  }
181
180
  }
182
181
  const isPresent = negate(isBlank);
183
- function isFunction(object) {
184
- return typeof (object) === 'function';
182
+ function isFunction(value) {
183
+ return typeof (value) === 'function';
185
184
  }
186
- function isString(object) {
187
- return (typeof (object) === 'string') || object instanceof String;
185
+ function isString(value) {
186
+ return (typeof (value) === 'string') || value instanceof String;
188
187
  }
189
- function isBoolean(object) {
190
- return (typeof (object) === 'boolean') || object instanceof Boolean;
188
+ function isBoolean(value) {
189
+ return (typeof (value) === 'boolean') || value instanceof Boolean;
191
190
  }
192
- function isNumber(object) {
193
- return (typeof (object) === 'number') || object instanceof Number;
191
+ function isNumber(value) {
192
+ return (typeof (value) === 'number') || value instanceof Number;
194
193
  }
195
- function isOptions(object) {
196
- return (typeof (object) === 'object') && !isNull(object) && (isUndefined(object.constructor) || (object.constructor === Object));
194
+ function isOptions(value) {
195
+ return (typeof (value) === 'object') && !isNull(value) && (isUndefined(value.constructor) || (value.constructor === Object));
197
196
  }
198
- function isObject(object) {
199
- const typeOfResult = typeof (object);
200
- return ((typeOfResult === 'object') && !isNull(object)) || (typeOfResult === 'function');
197
+ function isObject(value) {
198
+ const typeOfResult = typeof (value);
199
+ return ((typeOfResult === 'object') && !isNull(value)) || (typeOfResult === 'function');
201
200
  }
202
- function isElement(object) {
203
- return object instanceof Element;
201
+ function isElement(value) {
202
+ return value instanceof Element;
204
203
  }
205
- function isTextNode(object) {
206
- return object instanceof Text;
204
+ function isTextNode(value) {
205
+ return value instanceof Text;
207
206
  }
208
- function isRegExp(object) {
209
- return object instanceof RegExp;
207
+ function isRegExp(value) {
208
+ return value instanceof RegExp;
210
209
  }
211
- function isError(object) {
212
- return object instanceof Error;
210
+ function isError(value) {
211
+ return value instanceof Error;
213
212
  }
214
- function isJQuery(object) {
215
- return up.browser.canJQuery() && object instanceof jQuery;
213
+ function isJQuery(value) {
214
+ return up.browser.canJQuery() && value instanceof jQuery;
216
215
  }
217
- function isElementLike(object) {
218
- return !!(object && (object.addEventListener || (isJQuery(object) && object[0]?.addEventListener)));
216
+ function isElementLike(value) {
217
+ return !!(value && (value.addEventListener || (isJQuery(value) && value[0]?.addEventListener)));
219
218
  }
220
- function isPromise(object) {
221
- return isObject(object) && isFunction(object.then);
219
+ function isPromise(value) {
220
+ return isObject(value) && isFunction(value.then);
222
221
  }
223
222
  const { isArray } = Array;
224
- function isFormData(object) {
225
- return object instanceof FormData;
223
+ function isFormData(value) {
224
+ return value instanceof FormData;
226
225
  }
227
226
  function toArray(value) {
228
227
  return isArray(value) ? value : copyArrayLike(value);
@@ -389,13 +388,15 @@ up.util = (function () {
389
388
  return filterList(list, tester);
390
389
  }
391
390
  function intersect(array1, array2) {
392
- return filterList(array1, element => contains(array2, element));
391
+ return filterList(array1, (element) => contains(array2, element));
393
392
  }
394
393
  function scheduleTimer(millis, callback) {
395
394
  return setTimeout(callback, millis);
396
395
  }
397
396
  function queueTask(task) {
398
- return setTimeout(task);
397
+ const channel = new MessageChannel();
398
+ channel.port1.onmessage = () => task();
399
+ channel.port2.postMessage(0);
399
400
  }
400
401
  function last(value) {
401
402
  return value[value.length - 1];
@@ -425,7 +426,7 @@ up.util = (function () {
425
426
  const filtered = {};
426
427
  for (let key in object) {
427
428
  const value = object[key];
428
- if (tester(value, key, object)) {
429
+ if (tester(value, key)) {
429
430
  filtered[key] = object[key];
430
431
  }
431
432
  }
@@ -462,7 +463,7 @@ up.util = (function () {
462
463
  "'": '''
463
464
  };
464
465
  function escapeHTML(string) {
465
- return string.replace(/[&<>"']/g, char => ESCAPE_HTML_ENTITY_MAP[char]);
466
+ return string.replace(/[&<>"']/g, (char) => ESCAPE_HTML_ENTITY_MAP[char]);
466
467
  }
467
468
  function escapeRegExp(string) {
468
469
  return string.replace(/[\\^$*+?.()|[\]{}]/g, '\\$&');
@@ -491,9 +492,9 @@ up.util = (function () {
491
492
  function identity(arg) {
492
493
  return arg;
493
494
  }
494
- function sequence(functions) {
495
- functions = compact(functions);
496
- return (...args) => map(functions, fn => fn(...args));
495
+ function sequence(...args) {
496
+ let functions = scanFunctions(...args);
497
+ return (...args) => map(functions, (fn) => fn(...args));
497
498
  }
498
499
  function flatten(array) {
499
500
  const flattened = [];
@@ -528,34 +529,36 @@ up.util = (function () {
528
529
  return Object.prototype.hasOwnProperty(k);
529
530
  }
530
531
  function isEqual(a, b) {
532
+ if (a === b) {
533
+ return true;
534
+ }
531
535
  if (a?.valueOf) {
532
536
  a = a.valueOf();
533
537
  }
534
538
  if (b?.valueOf) {
535
539
  b = b.valueOf();
536
540
  }
541
+ if (a === b) {
542
+ return true;
543
+ }
537
544
  if (typeof (a) !== typeof (b)) {
538
545
  return false;
539
546
  }
540
- else if (isList(a) && isList(b)) {
547
+ if (isList(a) && isList(b)) {
541
548
  return isEqualList(a, b);
542
549
  }
543
- else if (isObject(a) && a[isEqual.key]) {
550
+ if (isObject(a) && a[isEqual.key]) {
544
551
  return a[isEqual.key](b);
545
552
  }
546
- else if (isOptions(a) && isOptions(b)) {
547
- const aKeys = Object.keys(a);
548
- const bKeys = Object.keys(b);
549
- if (isEqualList(aKeys, bKeys)) {
550
- return every(aKeys, aKey => isEqual(a[aKey], b[aKey]));
551
- }
552
- else {
553
- return false;
554
- }
555
- }
556
- else {
557
- return a === b;
553
+ if (isOptions(a) && isOptions(b)) {
554
+ return isEqualOptions(a, b);
558
555
  }
556
+ return false;
557
+ }
558
+ function isEqualOptions(a, b) {
559
+ const aKeys = Object.keys(a);
560
+ const bKeys = Object.keys(b);
561
+ return isEqualList(aKeys, bKeys) && every(aKeys, (key) => isEqual(a[key], b[key]));
559
562
  }
560
563
  isEqual.key = 'up.util.isEqual';
561
564
  function isEqualList(a, b) {
@@ -611,7 +614,7 @@ up.util = (function () {
611
614
  return renamed;
612
615
  }
613
616
  function camelToKebabCase(str) {
614
- return str.replace(/[A-Z]/g, char => '-' + char.toLowerCase());
617
+ return str.replace(/[A-Z]/g, (char) => '-' + char.toLowerCase());
615
618
  }
616
619
  function lowerCaseFirst(str) {
617
620
  return str[0].toLowerCase() + str.slice(1);
@@ -794,36 +797,39 @@ up.util = (function () {
794
797
  }
795
798
  function maskPattern(str, patterns, { keepDelimiters = false } = {}) {
796
799
  let maskCount = 0;
797
- let maskPattern = /§(\d+)/g;
798
- let matches = [];
799
- let replaceLayers = 0;
800
- let replace = (replacePattern) => {
800
+ let maskPattern = /§\d+/g;
801
+ let maskings = {};
802
+ let replaceLayers = [];
803
+ let replace = (replacePattern, allowRestoreTransform) => {
801
804
  let didReplace = false;
802
805
  str = str.replaceAll(replacePattern, function (match) {
803
806
  didReplace = true;
804
- let glyph = '§' + (maskCount++);
805
- let mask;
807
+ let mask = '§' + (maskCount++);
808
+ let remain;
806
809
  let masked;
807
810
  if (keepDelimiters) {
808
811
  let startDelimiter = match[0];
809
812
  let endDelimiter = match.slice(-1);
810
813
  masked = match.slice(1, -1);
811
- mask = startDelimiter + glyph + endDelimiter;
814
+ remain = startDelimiter + mask + endDelimiter;
812
815
  }
813
816
  else {
814
817
  masked = match;
815
- mask = glyph;
818
+ remain = mask;
816
819
  }
817
- matches.push(masked);
818
- return mask;
820
+ maskings[mask] = masked;
821
+ return remain;
819
822
  });
820
823
  if (didReplace)
821
- replaceLayers++;
824
+ replaceLayers.unshift({ allowRestoreTransform });
822
825
  };
823
- [maskPattern, ...patterns].forEach(replace);
826
+ replace(maskPattern, false);
827
+ for (let pattern of patterns)
828
+ replace(pattern, true);
824
829
  let restore = (s, transform = identity) => {
825
- for (let i = 0; i < replaceLayers; i++) {
826
- s = s.replace(maskPattern, (match, placeholderIndex) => transform(matches[placeholderIndex]));
830
+ for (let { allowRestoreTransform } of replaceLayers) {
831
+ let iterationTransform = allowRestoreTransform ? transform : identity;
832
+ s = s.replace(maskPattern, (match) => iterationTransform(assert(maskings[match], isString)));
827
833
  }
828
834
  return s;
829
835
  };
@@ -837,6 +843,7 @@ up.util = (function () {
837
843
  function ensureDoubleQuotes(str) {
838
844
  if (str[0] === '"')
839
845
  return str;
846
+ assert(str[0] === "'");
840
847
  str = str.slice(1, -1);
841
848
  let transformed = str.replace(/(\\\\)|(\\')|(\\")|(")/g, function (_match, escapedBackslash, escapedSingleQuote, _doubleQuote) {
842
849
  return escapedBackslash
@@ -865,6 +872,17 @@ up.util = (function () {
865
872
  ];
866
873
  });
867
874
  }
875
+ function spanObject(keys, value) {
876
+ return mapObject(keys, (key) => [key, value]);
877
+ }
878
+ function assert(value, testFn = isTruthy) {
879
+ if (testFn(value)) {
880
+ return value;
881
+ }
882
+ else {
883
+ throw "assert failed";
884
+ }
885
+ }
868
886
  return {
869
887
  parseURL,
870
888
  normalizeURL,
@@ -882,6 +900,7 @@ up.util = (function () {
882
900
  map,
883
901
  flatMap,
884
902
  mapObject,
903
+ spanObject,
885
904
  findResult,
886
905
  some,
887
906
  every,
@@ -972,6 +991,7 @@ up.util = (function () {
972
991
  maskPattern,
973
992
  expressionOutline,
974
993
  parseString,
994
+ assert,
975
995
  };
976
996
  })();
977
997
 
@@ -1085,12 +1105,13 @@ up.element = (function () {
1085
1105
  return root.querySelector(selector);
1086
1106
  }
1087
1107
  function subtree(root, selector) {
1088
- const results = [];
1108
+ const descendantMatches = root.querySelectorAll(selector);
1089
1109
  if (elementLikeMatches(root, selector)) {
1090
- results.push(root);
1110
+ return [root, ...descendantMatches];
1111
+ }
1112
+ else {
1113
+ return descendantMatches;
1091
1114
  }
1092
- results.push(...root.querySelectorAll(selector));
1093
- return results;
1094
1115
  }
1095
1116
  function subtreeFirst(root, selector) {
1096
1117
  return elementLikeMatches(root, selector) ? root : root.querySelector(selector);
@@ -1196,7 +1217,7 @@ up.element = (function () {
1196
1217
  }
1197
1218
  function metaContent(name) {
1198
1219
  const selector = "meta" + attrSelector('name', name);
1199
- return first(selector)?.getAttribute('content');
1220
+ return document.head.querySelector(selector)?.getAttribute('content');
1200
1221
  }
1201
1222
  function insertBefore(existingNode, newNode) {
1202
1223
  existingNode.parentNode.insertBefore(newNode, existingNode);
@@ -1306,7 +1327,7 @@ up.element = (function () {
1306
1327
  return element;
1307
1328
  }
1308
1329
  const SINGLETON_TAG_NAMES = ['HTML', 'BODY', 'HEAD', 'TITLE'];
1309
- const isSingleton = up.mockable(element => element.matches(SINGLETON_TAG_NAMES.join()));
1330
+ const isSingleton = up.mockable((element) => element.matches(SINGLETON_TAG_NAMES.join()));
1310
1331
  function elementTagName(element) {
1311
1332
  return element.tagName.toLowerCase();
1312
1333
  }
@@ -1334,9 +1355,11 @@ up.element = (function () {
1334
1355
  function createBrokenDocumentFromHTML(html) {
1335
1356
  return new DOMParser().parseFromString(html, 'text/html');
1336
1357
  }
1337
- function fixParserDamage(scriptish) {
1338
- let clone = createFromHTML(scriptish.outerHTML);
1339
- scriptish.replaceWith(clone);
1358
+ function revivedClone(element) {
1359
+ let clone = createFromHTML(element.outerHTML);
1360
+ if ('nonce' in element)
1361
+ clone.nonce = element.nonce;
1362
+ return clone;
1340
1363
  }
1341
1364
  function createFromHTML(html) {
1342
1365
  return extractSingular(createNodesFromHTML(html));
@@ -1532,7 +1555,7 @@ up.element = (function () {
1532
1555
  }
1533
1556
  function extractFromStyleObject(style, keyOrKeys) {
1534
1557
  if (up.migrate.loaded)
1535
- keyOrKeys = up.migrate.fixStyleProps(keyOrKeys);
1558
+ keyOrKeys = up.migrate.fixGetStyleProps(keyOrKeys);
1536
1559
  if (u.isString(keyOrKeys)) {
1537
1560
  return style.getPropertyValue(keyOrKeys);
1538
1561
  }
@@ -1542,7 +1565,7 @@ up.element = (function () {
1542
1565
  }
1543
1566
  function setInlineStyle(element, props, unit = '') {
1544
1567
  if (up.migrate.loaded)
1545
- props = up.migrate.fixStyleProps(props, unit);
1568
+ props = up.migrate.fixSetStyleProps(props, unit);
1546
1569
  if (u.isString(props)) {
1547
1570
  element.setAttribute('style', props);
1548
1571
  }
@@ -1644,7 +1667,7 @@ up.element = (function () {
1644
1667
  attrSelector,
1645
1668
  tagName: elementTagName,
1646
1669
  createBrokenDocumentFromHTML,
1647
- fixParserDamage,
1670
+ revivedClone,
1648
1671
  createNodesFromHTML,
1649
1672
  createFromHTML,
1650
1673
  extractSingular,
@@ -1779,7 +1802,7 @@ up.Record = class Record {
1779
1802
  return {};
1780
1803
  }
1781
1804
  constructor(options) {
1782
- Object.assign(this, this.defaults(options), this.attributes(options));
1805
+ Object.assign(this, u.mergeDefined(this.defaults(options), this.attributes(options)));
1783
1806
  }
1784
1807
  attributes(source = this) {
1785
1808
  return u.pick(source, this.keys());
@@ -1858,13 +1881,39 @@ up.LogConfig = class LogConfig extends up.Config {
1858
1881
  /* 19 */
1859
1882
  /***/ (() => {
1860
1883
 
1884
+ const u = up.util;
1885
+ up.Registry = class Registry {
1886
+ constructor(valueDescription, normalize = u.identity) {
1887
+ this._data = {};
1888
+ this._normalize = normalize;
1889
+ this._valueDescription = valueDescription;
1890
+ this.put = this.put.bind(this);
1891
+ document.addEventListener('up:framework:reset', () => this.reset());
1892
+ }
1893
+ put(key, object) {
1894
+ object = this._normalize(object);
1895
+ object.isDefault = up.framework.evaling;
1896
+ this._data[key] = object;
1897
+ }
1898
+ get(name) {
1899
+ return this._data[name] || up.fail("Unknown %s %o", this._valueDescription, name);
1900
+ }
1901
+ reset() {
1902
+ this._data = u.pickBy(this._data, 'isDefault');
1903
+ }
1904
+ };
1905
+
1906
+
1907
+ /***/ }),
1908
+ /* 20 */
1909
+ /***/ (() => {
1910
+
1861
1911
  const u = up.util;
1862
1912
  const e = up.element;
1863
1913
  up.OptionsParser = class OptionsParser {
1864
1914
  constructor(element, options, parserOptions = {}) {
1865
1915
  this._options = options;
1866
1916
  this._element = element;
1867
- this._parserOptions = parserOptions;
1868
1917
  this._fail = parserOptions.fail;
1869
1918
  this._closest = parserOptions.closest;
1870
1919
  this._attrPrefix = parserOptions.attrPrefix || 'up-';
@@ -1899,11 +1948,11 @@ up.OptionsParser = class OptionsParser {
1899
1948
  value ??= this._parseFromAttr(attrValueFn, this._element, attrName);
1900
1949
  }
1901
1950
  value ??= keyOptions.default ?? this._defaults[key];
1902
- let normalizeFn = keyOptions.normalize;
1903
- if (normalizeFn) {
1904
- value = normalizeFn(value);
1905
- }
1906
1951
  if (u.isDefined(value)) {
1952
+ let normalizeFn = keyOptions.normalize;
1953
+ if (normalizeFn) {
1954
+ value = normalizeFn(value);
1955
+ }
1907
1956
  this._options[key] = value;
1908
1957
  }
1909
1958
  let failKey;
@@ -1912,8 +1961,8 @@ up.OptionsParser = class OptionsParser {
1912
1961
  this.parse(attrValueFn, failKey, { ...keyOptions, attr: failAttrNames });
1913
1962
  }
1914
1963
  }
1915
- include(optionsFn) {
1916
- let fnResult = optionsFn(this._element, this._options, this._parserOptions);
1964
+ include(optionsFn, parserOptions) {
1965
+ let fnResult = optionsFn(this._element, this._options, { defaults: this._defaults, ...parserOptions });
1917
1966
  Object.assign(this._options, fnResult);
1918
1967
  }
1919
1968
  _parseFromAttr(attrValueFn, element, attrName) {
@@ -1940,7 +1989,7 @@ up.OptionsParser = class OptionsParser {
1940
1989
 
1941
1990
 
1942
1991
  /***/ }),
1943
- /* 20 */
1992
+ /* 21 */
1944
1993
  /***/ (() => {
1945
1994
 
1946
1995
  const u = up.util;
@@ -1969,7 +2018,7 @@ up.FIFOCache = class FIFOCache {
1969
2018
 
1970
2019
 
1971
2020
  /***/ }),
1972
- /* 21 */
2021
+ /* 22 */
1973
2022
  /***/ (() => {
1974
2023
 
1975
2024
  up.Rect = class Rect extends up.Record {
@@ -2000,7 +2049,7 @@ up.Rect = class Rect extends up.Record {
2000
2049
 
2001
2050
 
2002
2051
  /***/ }),
2003
- /* 22 */
2052
+ /* 23 */
2004
2053
  /***/ (() => {
2005
2054
 
2006
2055
  const e = up.element;
@@ -2048,7 +2097,7 @@ up.BodyShifter = class BodyShifter {
2048
2097
 
2049
2098
 
2050
2099
  /***/ }),
2051
- /* 23 */
2100
+ /* 24 */
2052
2101
  /***/ (() => {
2053
2102
 
2054
2103
  const u = up.util;
@@ -2074,7 +2123,7 @@ up.Change = class Change {
2074
2123
 
2075
2124
 
2076
2125
  /***/ }),
2077
- /* 24 */
2126
+ /* 25 */
2078
2127
  /***/ (() => {
2079
2128
 
2080
2129
  const u = up.util;
@@ -2142,21 +2191,21 @@ up.Change.Addition = class Addition extends up.Change {
2142
2191
  _responseOptions() {
2143
2192
  return { response: this._response };
2144
2193
  }
2145
- executeSteps(steps, responseDoc, noneOptions) {
2146
- return new up.Change.UpdateSteps({ steps, noneOptions }).execute(responseDoc);
2194
+ executeSteps({ steps, responseDoc, noneOptions, passRenderOptions = this.options }) {
2195
+ return new up.Change.UpdateSteps({ steps, noneOptions, passRenderOptions }).execute(responseDoc);
2147
2196
  }
2148
2197
  };
2149
2198
 
2150
2199
 
2151
2200
  /***/ }),
2152
- /* 25 */
2201
+ /* 26 */
2153
2202
  /***/ (() => {
2154
2203
 
2155
2204
  var _a;
2156
2205
  const u = up.util;
2157
2206
  up.RenderJob = (_a = class RenderJob {
2158
- constructor(options) {
2159
- this.options = options;
2207
+ constructor(renderOptions) {
2208
+ this.renderOptions = renderOptions;
2160
2209
  }
2161
2210
  execute() {
2162
2211
  this._rendered = this._executePromise();
@@ -2165,9 +2214,9 @@ up.RenderJob = (_a = class RenderJob {
2165
2214
  async _executePromise() {
2166
2215
  try {
2167
2216
  this._emitGuardEvent();
2168
- this.options = up.RenderOptions.preprocess(this.options);
2169
- up.browser.assertConfirmed(this.options);
2170
- up.RenderOptions.assertContentGiven(this.options);
2217
+ this.renderOptions = up.RenderOptions.preprocess(this.renderOptions);
2218
+ up.browser.assertConfirmed(this.renderOptions);
2219
+ up.RenderOptions.assertContentGiven(this.renderOptions);
2171
2220
  let result = await this._getChange().execute();
2172
2221
  this._handleResult(result);
2173
2222
  return result;
@@ -2179,7 +2228,7 @@ up.RenderJob = (_a = class RenderJob {
2179
2228
  }
2180
2229
  _handleResult(result) {
2181
2230
  if (result instanceof up.RenderResult) {
2182
- let { onRendered, onFinished } = result.options;
2231
+ let { onRendered, onFinished } = result.renderOptions;
2183
2232
  if (!result.none)
2184
2233
  up.error.guard(() => onRendered?.(result));
2185
2234
  let guardedOnFinished = function (result) {
@@ -2192,7 +2241,7 @@ up.RenderJob = (_a = class RenderJob {
2192
2241
  _handleError(error) {
2193
2242
  let prefix = error instanceof up.Aborted ? 'Rendering was aborted' : 'Error while rendering';
2194
2243
  up.puts('up.render()', `${prefix}: ${error.name}: ${error.message}`);
2195
- up.error.guard(() => this.options.onError?.(error));
2244
+ up.error.guard(() => this.renderOptions.onError?.(error));
2196
2245
  }
2197
2246
  get finished() {
2198
2247
  return this._awaitFinished();
@@ -2213,7 +2262,7 @@ up.RenderJob = (_a = class RenderJob {
2213
2262
  }
2214
2263
  _getChange() {
2215
2264
  let handleAbort = u.memoize((request) => this._handleAbortOption(request));
2216
- let renderOptions = { ...this.options, handleAbort };
2265
+ let renderOptions = { ...this.renderOptions, handleAbort };
2217
2266
  if (renderOptions.url) {
2218
2267
  return new up.Change.FromURL(renderOptions);
2219
2268
  }
@@ -2225,16 +2274,16 @@ up.RenderJob = (_a = class RenderJob {
2225
2274
  }
2226
2275
  }
2227
2276
  _emitGuardEvent() {
2228
- let guardEvent = u.pluckKey(this.options, 'guardEvent');
2277
+ let guardEvent = u.pluckKey(this.renderOptions, 'guardEvent');
2229
2278
  if (guardEvent) {
2230
- guardEvent.renderOptions = this.options;
2231
- if (up.emit(guardEvent, { target: this.options.origin }).defaultPrevented) {
2279
+ guardEvent.renderOptions = this.renderOptions;
2280
+ if (up.emit(guardEvent, { target: this.renderOptions.origin }).defaultPrevented) {
2232
2281
  throw new up.Aborted(`Rendering was prevented by ${guardEvent.type} listener`);
2233
2282
  }
2234
2283
  }
2235
2284
  }
2236
2285
  _handleAbortOption(request) {
2237
- let { abort } = this.options;
2286
+ let { abort } = this.renderOptions;
2238
2287
  if (!abort || !up.network.isBusy())
2239
2288
  return;
2240
2289
  let { bindFragments, bindLayer, origin, layer } = this._getChange().getPreflightProps();
@@ -2272,7 +2321,7 @@ up.RenderJob = (_a = class RenderJob {
2272
2321
 
2273
2322
 
2274
2323
  /***/ }),
2275
- /* 26 */
2324
+ /* 27 */
2276
2325
  /***/ (() => {
2277
2326
 
2278
2327
  up.Change.DestroyFragment = class DestroyFragment extends up.Change {
@@ -2297,18 +2346,18 @@ up.Change.DestroyFragment = class DestroyFragment extends up.Change {
2297
2346
  async _destroyAfterAnimation() {
2298
2347
  this._emitDestroyed();
2299
2348
  await this._animate();
2300
- this._wipe();
2349
+ this._erase();
2301
2350
  this._onFinished?.();
2302
2351
  }
2303
2352
  _destroyNow() {
2304
- this._wipe();
2353
+ this._erase();
2305
2354
  this._emitDestroyed();
2306
2355
  this._onFinished?.();
2307
2356
  }
2308
2357
  _animate() {
2309
2358
  return up.motion.animate(this._element, this._animation, this.options);
2310
2359
  }
2311
- _wipe() {
2360
+ _erase() {
2312
2361
  this._layer.asCurrent(() => {
2313
2362
  up.fragment.abort(this._element);
2314
2363
  up.script.clean(this._element, { layer: this._layer });
@@ -2323,7 +2372,7 @@ up.Change.DestroyFragment = class DestroyFragment extends up.Change {
2323
2372
 
2324
2373
 
2325
2374
  /***/ }),
2326
- /* 27 */
2375
+ /* 28 */
2327
2376
  /***/ (() => {
2328
2377
 
2329
2378
  let u = up.util;
@@ -2377,6 +2426,7 @@ up.Change.OpenLayer = class OpenLayer extends up.Change.Addition {
2377
2426
  this._assertOpenEventEmitted();
2378
2427
  this.layer = this._buildLayer();
2379
2428
  this._baseLayer.peel({ history: !this.layer.history });
2429
+ this._baseLayer.saveHistory();
2380
2430
  up.layer.stack.push(this.layer);
2381
2431
  this.layer.createElements();
2382
2432
  this.layer.setupHandlers();
@@ -2386,14 +2436,15 @@ up.Change.OpenLayer = class OpenLayer extends up.Change.Addition {
2386
2436
  this.handleLayerChangeRequests();
2387
2437
  this.responseDoc.commitElement(this._content);
2388
2438
  this.layer.setContent(this._content);
2389
- this.setReloadAttrs({ newElement: this._content, source: this.options.source });
2390
2439
  this.responseDoc.finalizeElement(this._content);
2440
+ this.setReloadAttrs({ newElement: this._content, source: this.options.source });
2441
+ up.hello(this.layer.element, { ...this.options, layer: this.layer, dataRoot: this._content });
2391
2442
  this._newOverlayResult = new up.RenderResult({
2392
2443
  layer: this.layer,
2393
2444
  fragments: [this._content],
2394
2445
  target: this.target,
2446
+ renderOptions: this.options,
2395
2447
  });
2396
- up.hello(this.layer.element, { ...this.options, layer: this.layer, dataRoot: this._content });
2397
2448
  this._handleScroll();
2398
2449
  this._newOverlayResult.finished = this._finish();
2399
2450
  this.layer.opening = false;
@@ -2404,7 +2455,10 @@ up.Change.OpenLayer = class OpenLayer extends up.Change.Addition {
2404
2455
  if (this._otherLayersResult)
2405
2456
  return;
2406
2457
  let otherLayerSteps = this._getHungrySteps().other;
2407
- this._otherLayersResult = this.executeSteps(otherLayerSteps, this.responseDoc);
2458
+ this._otherLayersResult = this.executeSteps({
2459
+ steps: otherLayerSteps,
2460
+ responseDoc: this.responseDoc,
2461
+ });
2408
2462
  }
2409
2463
  async _finish() {
2410
2464
  await this.layer.startOpenAnimation();
@@ -2414,7 +2468,7 @@ up.Change.OpenLayer = class OpenLayer extends up.Change.Addition {
2414
2468
  }
2415
2469
  _buildLayer() {
2416
2470
  const buildOptions = { ...this.options, opening: true };
2417
- const beforeNew = optionsWithLayerDefaults => {
2471
+ const beforeNew = (optionsWithLayerDefaults) => {
2418
2472
  return this.options = up.RenderOptions.finalize(optionsWithLayerDefaults);
2419
2473
  };
2420
2474
  return up.layer.build(buildOptions, beforeNew);
@@ -2423,9 +2477,7 @@ up.Change.OpenLayer = class OpenLayer extends up.Change.Addition {
2423
2477
  if (this.layer.history === 'auto') {
2424
2478
  this.layer.history = up.fragment.hasAutoHistory([this._content], this.layer);
2425
2479
  }
2426
- let { parent } = this.layer;
2427
- this.layer.history &&= parent.history;
2428
- parent.saveHistory();
2480
+ this.layer.history &&= this._baseLayer.history;
2429
2481
  this.layer.updateHistory(this.options);
2430
2482
  }
2431
2483
  _handleFocus() {
@@ -2478,7 +2530,7 @@ up.Change.OpenLayer = class OpenLayer extends up.Change.Addition {
2478
2530
 
2479
2531
 
2480
2532
  /***/ }),
2481
- /* 28 */
2533
+ /* 29 */
2482
2534
  /***/ (() => {
2483
2535
 
2484
2536
  var _a;
@@ -2550,13 +2602,20 @@ up.Change.UpdateLayer = (_a = class UpdateLayer extends up.Change.Addition {
2550
2602
  this.layer.updateHistory(this.options);
2551
2603
  }
2552
2604
  this.handleLayerChangeRequests();
2553
- this._currentLayerResult = this.executeSteps(this._steps, this.responseDoc, this.options);
2605
+ this._currentLayerResult = this.executeSteps({
2606
+ steps: this._steps,
2607
+ responseDoc: this.responseDoc,
2608
+ noneOptions: this.options,
2609
+ });
2554
2610
  }
2555
2611
  _renderOtherLayers() {
2556
2612
  if (this._otherLayersResult)
2557
2613
  return;
2558
2614
  let otherLayerSteps = this._getHungrySteps().other;
2559
- this._otherLayersResult = this.executeSteps(otherLayerSteps, this.responseDoc);
2615
+ this._otherLayersResult = this.executeSteps({
2616
+ steps: otherLayerSteps,
2617
+ responseDoc: this.responseDoc,
2618
+ });
2560
2619
  }
2561
2620
  _matchPreflight() {
2562
2621
  this._matchOldElements();
@@ -2629,7 +2688,7 @@ up.Change.UpdateLayer = (_a = class UpdateLayer extends up.Change.Addition {
2629
2688
 
2630
2689
 
2631
2690
  /***/ }),
2632
- /* 29 */
2691
+ /* 30 */
2633
2692
  /***/ (() => {
2634
2693
 
2635
2694
  const u = up.util;
@@ -2637,30 +2696,30 @@ const e = up.element;
2637
2696
  up.Change.UpdateSteps = class UpdateSteps extends up.Change.Addition {
2638
2697
  constructor(options) {
2639
2698
  super(options);
2699
+ this._steps = u.copy(u.assert(options.steps));
2700
+ this._passRenderOptions = u.assert(options.passRenderOptions);
2640
2701
  this._noneOptions = options.noneOptions || {};
2641
- this._steps = u.copy(options.steps);
2642
2702
  }
2643
2703
  execute(responseDoc) {
2644
2704
  this.responseDoc = responseDoc;
2645
2705
  this._steps = responseDoc.selectSteps(this._steps);
2646
2706
  this._steps = responseDoc.commitSteps(this._steps);
2647
- if (!this._steps.length) {
2648
- return this._executeNone();
2649
- }
2650
2707
  this.renderResult = new up.RenderResult({
2651
- layer: this._steps[0]?.layer,
2708
+ layer: this._passRenderOptions.layer,
2652
2709
  target: up.fragment.targetForSteps(this._steps),
2710
+ renderOptions: this._passRenderOptions,
2653
2711
  });
2654
- this._steps.reverse();
2655
- const motionEndPromises = this._steps.map(step => this._executeStep(step));
2656
- this.renderResult.finished = this._finish(motionEndPromises);
2712
+ if (!this._steps.length) {
2713
+ this._handleFocus(null, this._noneOptions);
2714
+ this._handleScroll(null, this._noneOptions);
2715
+ }
2716
+ else {
2717
+ this._steps.reverse();
2718
+ const motionEndPromises = this._steps.map((step) => this._executeStep(step));
2719
+ this.renderResult.finished = this._finish(motionEndPromises);
2720
+ }
2657
2721
  return this.renderResult;
2658
2722
  }
2659
- _executeNone() {
2660
- this._handleFocus(null, this._noneOptions);
2661
- this._handleScroll(null, this._noneOptions);
2662
- return up.RenderResult.buildNone();
2663
- }
2664
2723
  async _finish(motionEndPromises) {
2665
2724
  await Promise.all(motionEndPromises);
2666
2725
  for (let step of this._steps) {
@@ -2673,17 +2732,16 @@ up.Change.UpdateSteps = class UpdateSteps extends up.Change.Addition {
2673
2732
  this.renderResult.fragments.unshift(...newFragments);
2674
2733
  }
2675
2734
  _executeStep(step) {
2676
- this.setReloadAttrs(step);
2677
2735
  switch (step.placement) {
2678
2736
  case 'swap': {
2679
- let keepPlan = this._findKeepPlan(step);
2737
+ let keepPlan = up.fragment.keepPlan(step);
2680
2738
  if (keepPlan) {
2681
2739
  this._handleFocus(step.oldElement, step);
2682
2740
  this._handleScroll(step.oldElement, step);
2683
2741
  return Promise.resolve();
2684
2742
  }
2685
2743
  else {
2686
- this._preserveKeepables(step);
2744
+ this._preserveDescendantKeepables(step);
2687
2745
  const parent = step.oldElement.parentNode;
2688
2746
  const morphOptions = {
2689
2747
  ...step,
@@ -2691,11 +2749,9 @@ up.Change.UpdateSteps = class UpdateSteps extends up.Change.Addition {
2691
2749
  up.fragment.markAsDestroying(step.oldElement);
2692
2750
  },
2693
2751
  afterInsert: () => {
2694
- this._restoreKeepables(step);
2695
- this.responseDoc.finalizeElement(step.newElement);
2696
- this._unmarkKeepables(step);
2697
- up.hello(step.newElement, step);
2698
- this._addToResult(step.newElement);
2752
+ this._restoreDescendantKeepables(step);
2753
+ this._welcomeElement(step.newElement, step);
2754
+ this._finalizeDescendantKeepables(step);
2699
2755
  },
2700
2756
  beforeDetach: () => {
2701
2757
  up.script.clean(step.oldElement, { layer: step.layer });
@@ -2732,90 +2788,64 @@ up.Change.UpdateSteps = class UpdateSteps extends up.Change.Addition {
2732
2788
  let wrapper = e.wrapChildren(step.newElement);
2733
2789
  let position = step.placement === 'before' ? 'afterbegin' : 'beforeend';
2734
2790
  step.oldElement.insertAdjacentElement(position, wrapper);
2735
- this.responseDoc.finalizeElement(wrapper);
2736
- up.hello(wrapper, step);
2737
- this._addToResult(wrapper);
2791
+ this._welcomeElement(wrapper, step);
2738
2792
  this._handleFocus(wrapper, step);
2739
2793
  this._handleScroll(wrapper, step);
2740
- return up.animate(wrapper, step.transition, step).then(() => e.unwrap(wrapper));
2794
+ return up.animate(wrapper, step.animation, step).then(() => e.unwrap(wrapper));
2741
2795
  }
2742
2796
  default: {
2743
2797
  up.fail('Unknown placement: %o', step.placement);
2744
2798
  }
2745
2799
  }
2746
2800
  }
2747
- _findKeepPlan(options) {
2748
- if (!options.keep) {
2749
- return;
2750
- }
2751
- const { oldElement, newElement } = options;
2752
- let doKeep = e.booleanAttr(oldElement, 'up-keep');
2753
- if (!doKeep) {
2754
- return;
2755
- }
2756
- let partner;
2757
- let partnerSelector = up.fragment.toTarget(oldElement);
2758
- const lookupOpts = { layer: options.layer };
2759
- if (options.descendantsOnly) {
2760
- partner = up.fragment.get(newElement, partnerSelector, lookupOpts);
2761
- }
2762
- else {
2763
- partner = e.subtreeFirst(newElement, partnerSelector, lookupOpts);
2764
- }
2765
- if (partner && e.booleanAttr(partner, 'up-keep') !== false) {
2766
- const plan = {
2767
- oldElement,
2768
- newElement: partner,
2769
- newData: up.script.data(partner),
2770
- renderOptions: options,
2771
- };
2772
- if (!up.fragment.emitKeep(plan).defaultPrevented) {
2773
- return plan;
2774
- }
2775
- }
2801
+ _welcomeElement(element, step) {
2802
+ this.responseDoc.finalizeElement(element);
2803
+ this.setReloadAttrs(step);
2804
+ up.hello(element, step);
2805
+ this._addToResult(element);
2776
2806
  }
2777
- _preserveKeepables(step) {
2778
- const keepPlans = [];
2807
+ _preserveDescendantKeepables(step) {
2808
+ const descendantKeepPlans = [];
2779
2809
  if (step.keep) {
2780
2810
  for (let keepable of step.oldElement.querySelectorAll('[up-keep]')) {
2781
- let keepPlan = this._findKeepPlan({ ...step, oldElement: keepable, descendantsOnly: true });
2811
+ let keepPlan = up.fragment.keepPlan({ ...step, oldElement: keepable, descendantsOnly: true });
2782
2812
  if (keepPlan) {
2783
2813
  const keepableClone = keepable.cloneNode(true);
2784
2814
  keepable.insertAdjacentElement('beforebegin', keepableClone);
2785
2815
  keepable.classList.add('up-keeping');
2786
2816
  up.script.disableSubtree(keepPlan.newElement);
2787
2817
  let viewports = up.viewport.subtree(keepPlan.oldElement);
2788
- keepPlan.revivers = viewports.map(function (viewport) {
2818
+ keepPlan.revivers = u.map(viewports, function (viewport) {
2789
2819
  let cursorProps = up.viewport.copyCursorProps(viewport);
2790
2820
  return () => up.viewport.copyCursorProps(cursorProps, viewport);
2791
2821
  });
2792
- if (this._willChangeElement(document.body)) {
2822
+ if (this._willChangeBody()) {
2793
2823
  keepPlan.newElement.replaceWith(keepable);
2794
2824
  }
2795
2825
  else {
2796
2826
  document.body.append(keepable);
2797
2827
  }
2798
- keepPlans.push(keepPlan);
2828
+ descendantKeepPlans.push(keepPlan);
2799
2829
  }
2800
2830
  }
2801
2831
  }
2802
- step.keepPlans = keepPlans;
2832
+ step.descendantKeepPlans = descendantKeepPlans;
2803
2833
  }
2804
- _restoreKeepables(step) {
2805
- for (let keepPlan of step.keepPlans) {
2834
+ _restoreDescendantKeepables(step) {
2835
+ for (let keepPlan of step.descendantKeepPlans) {
2806
2836
  keepPlan.newElement.replaceWith(keepPlan.oldElement);
2807
2837
  for (let reviver of keepPlan.revivers) {
2808
2838
  reviver();
2809
2839
  }
2810
2840
  }
2811
2841
  }
2812
- _unmarkKeepables(step) {
2813
- for (let keepPlan of step.keepPlans) {
2842
+ _finalizeDescendantKeepables(step) {
2843
+ for (let keepPlan of step.descendantKeepPlans) {
2814
2844
  keepPlan.oldElement.classList.remove('up-keeping');
2815
2845
  }
2816
2846
  }
2817
- _willChangeElement(element) {
2818
- return u.some(this._steps, (step) => step.oldElement.contains(element));
2847
+ _willChangeBody() {
2848
+ return u.some(this._steps, (step) => step.oldElement.matches('body'));
2819
2849
  }
2820
2850
  _handleFocus(fragment, options) {
2821
2851
  const fragmentFocus = new up.FragmentFocus({
@@ -2837,7 +2867,7 @@ up.Change.UpdateSteps = class UpdateSteps extends up.Change.Addition {
2837
2867
 
2838
2868
 
2839
2869
  /***/ }),
2840
- /* 30 */
2870
+ /* 31 */
2841
2871
  /***/ (() => {
2842
2872
 
2843
2873
  const u = up.util;
@@ -2915,7 +2945,7 @@ up.Change.CloseLayer = class CloseLayer extends up.Change {
2915
2945
 
2916
2946
 
2917
2947
  /***/ }),
2918
- /* 31 */
2948
+ /* 32 */
2919
2949
  /***/ (() => {
2920
2950
 
2921
2951
  var _a;
@@ -2934,7 +2964,7 @@ up.Change.FromURL = (_a = class FromURL extends up.Change {
2934
2964
  return request;
2935
2965
  this.options.handleAbort?.(request);
2936
2966
  request.runPreviews(this.options);
2937
- return await u.always(request, responseOrError => this._onRequestSettled(responseOrError));
2967
+ return await u.always(request, (responseOrError) => this._onRequestSettled(responseOrError));
2938
2968
  }
2939
2969
  _newPageReason() {
2940
2970
  if (u.isCrossOrigin(this.options.url)) {
@@ -2992,7 +3022,7 @@ up.Change.FromURL = (_a = class FromURL extends up.Change {
2992
3022
 
2993
3023
 
2994
3024
  /***/ }),
2995
- /* 32 */
3025
+ /* 33 */
2996
3026
  /***/ (() => {
2997
3027
 
2998
3028
  var _a;
@@ -3027,7 +3057,7 @@ up.Change.FromResponse = (_a = class FromResponse extends up.Change {
3027
3057
  this.options.failTarget = ':none';
3028
3058
  }
3029
3059
  _updateContentFromResponse(finalRenderOptions) {
3030
- if (finalRenderOptions.failPrefixForced) {
3060
+ if (finalRenderOptions.didForceFailOptions) {
3031
3061
  up.puts('up.render()', 'Rendering failed response using fail-prefixed options (https://unpoly.com/failed-responses)');
3032
3062
  }
3033
3063
  this._augmentOptionsFromResponse(finalRenderOptions);
@@ -3110,6 +3140,17 @@ up.Change.FromResponse = (_a = class FromResponse extends up.Change {
3110
3140
  renderOptions.source = this.improveHistoryValue(renderOptions.source, 'keep');
3111
3141
  renderOptions.history = !!renderOptions.location;
3112
3142
  }
3143
+ let openLayerOptions = this._response.openLayer;
3144
+ if (openLayerOptions) {
3145
+ Object.assign(renderOptions, {
3146
+ ...up.Layer.Overlay.UNSET_VISUALS,
3147
+ target: undefined,
3148
+ ...up.fragment.config.navigateOptions,
3149
+ ...openLayerOptions,
3150
+ layer: 'new',
3151
+ });
3152
+ Object.assign(renderOptions, openLayerOptions);
3153
+ }
3113
3154
  renderOptions.location = this.improveHistoryValue(renderOptions.location, serverLocation);
3114
3155
  renderOptions.title = this.improveHistoryValue(renderOptions.title, this._response.title);
3115
3156
  renderOptions.eventPlans = this._response.eventPlans;
@@ -3124,7 +3165,7 @@ up.Change.FromResponse = (_a = class FromResponse extends up.Change {
3124
3165
  renderOptions.target = ':none';
3125
3166
  }
3126
3167
  renderOptions.context = u.merge(renderOptions.context, this._response.context);
3127
- renderOptions.cspNonces = this._response.cspNonces;
3168
+ renderOptions.cspInfo = this._response.cspInfo;
3128
3169
  renderOptions.time ??= this._response.lastModified;
3129
3170
  renderOptions.etag ??= this._response.etag;
3130
3171
  }
@@ -3138,7 +3179,7 @@ up.Change.FromResponse = (_a = class FromResponse extends up.Change {
3138
3179
 
3139
3180
 
3140
3181
  /***/ }),
3141
- /* 33 */
3182
+ /* 34 */
3142
3183
  /***/ (() => {
3143
3184
 
3144
3185
  var _a;
@@ -3183,9 +3224,7 @@ up.Change.FromContent = (_a = class FromContent extends up.Change {
3183
3224
  return this._seekPlan(this._executePlan.bind(this)) || this._cannotMatchPostflightTarget();
3184
3225
  }
3185
3226
  _executePlan(matchedPlan) {
3186
- let result = matchedPlan.execute(this._getResponseDoc(), this._onPlanApplicable.bind(this, matchedPlan));
3187
- result.options = this.options;
3188
- return result;
3227
+ return matchedPlan.execute(this._getResponseDoc(), this._onPlanApplicable.bind(this, matchedPlan));
3189
3228
  }
3190
3229
  _isApplicablePlanError(error) {
3191
3230
  return !(error instanceof up.CannotMatch);
@@ -3210,7 +3249,7 @@ up.Change.FromContent = (_a = class FromContent extends up.Change {
3210
3249
  'fragment',
3211
3250
  'document',
3212
3251
  'html',
3213
- 'cspNonces',
3252
+ 'cspInfo',
3214
3253
  'origin',
3215
3254
  'data',
3216
3255
  ]);
@@ -3241,7 +3280,7 @@ up.Change.FromContent = (_a = class FromContent extends up.Change {
3241
3280
  return this._expandTargets(target || ':main', layer)[0];
3242
3281
  }
3243
3282
  getPreflightProps(opts = {}) {
3244
- const getPlanProps = plan => plan.getPreflightProps();
3283
+ const getPlanProps = (plan) => plan.getPreflightProps();
3245
3284
  return this._seekPlan(getPlanProps) || opts.optional || this._cannotMatchPreflightTarget();
3246
3285
  }
3247
3286
  _cannotMatchPreflightTarget() {
@@ -3259,7 +3298,7 @@ up.Change.FromContent = (_a = class FromContent extends up.Change {
3259
3298
  else if (this._layers.length === 0) {
3260
3299
  this._cannotMatchLayer();
3261
3300
  }
3262
- else if (this.options.failPrefixForced) {
3301
+ else if (this.options.didForceFailOptions) {
3263
3302
  throw new up.CannotMatch('No target selector given for failed responses (https://unpoly.com/failed-responses)');
3264
3303
  }
3265
3304
  else {
@@ -3293,7 +3332,7 @@ up.Change.FromContent = (_a = class FromContent extends up.Change {
3293
3332
 
3294
3333
 
3295
3334
  /***/ }),
3296
- /* 34 */
3335
+ /* 35 */
3297
3336
  /***/ (() => {
3298
3337
 
3299
3338
  const u = up.util;
@@ -3388,7 +3427,7 @@ up.CompilerPass = class CompilerPass {
3388
3427
 
3389
3428
 
3390
3429
  /***/ }),
3391
- /* 35 */
3430
+ /* 36 */
3392
3431
  /***/ (() => {
3393
3432
 
3394
3433
  const u = up.util;
@@ -3493,7 +3532,7 @@ up.CSSTransition = class CSSTransition {
3493
3532
 
3494
3533
 
3495
3534
  /***/ }),
3496
- /* 36 */
3535
+ /* 37 */
3497
3536
  /***/ (() => {
3498
3537
 
3499
3538
  const u = up.util;
@@ -3516,7 +3555,7 @@ up.DestructorPass = class DestructorPass {
3516
3555
 
3517
3556
 
3518
3557
  /***/ }),
3519
- /* 37 */
3558
+ /* 38 */
3520
3559
  /***/ (() => {
3521
3560
 
3522
3561
  const u = up.util;
@@ -3615,7 +3654,7 @@ up.EventEmitter = class EventEmitter extends up.Record {
3615
3654
 
3616
3655
 
3617
3656
  /***/ }),
3618
- /* 38 */
3657
+ /* 39 */
3619
3658
  /***/ (() => {
3620
3659
 
3621
3660
  const u = up.util;
@@ -3666,7 +3705,8 @@ up.EventListener = class EventListener extends up.Record {
3666
3705
  }
3667
3706
  let element = event.target;
3668
3707
  if (this.selector) {
3669
- element = element.closest(u.evalOption(this.selector));
3708
+ let selector = u.evalOption(this.selector);
3709
+ element = element.closest(selector);
3670
3710
  }
3671
3711
  if (this.guard && !this.guard(event)) {
3672
3712
  return;
@@ -3719,7 +3759,7 @@ up.EventListener = class EventListener extends up.Record {
3719
3759
 
3720
3760
 
3721
3761
  /***/ }),
3722
- /* 39 */
3762
+ /* 40 */
3723
3763
  /***/ (() => {
3724
3764
 
3725
3765
  const u = up.util;
@@ -3765,7 +3805,7 @@ up.EventListenerGroup = class EventListenerGroup extends up.Record {
3765
3805
  }
3766
3806
  });
3767
3807
  }
3768
- static fromBindArgs(args, defaults) {
3808
+ static fromBindArgs(args, overrides) {
3769
3809
  args = u.copy(args);
3770
3810
  const callback = args.pop();
3771
3811
  let elements;
@@ -3785,14 +3825,63 @@ up.EventListenerGroup = class EventListenerGroup extends up.Record {
3785
3825
  }
3786
3826
  const options = u.extractOptions(args);
3787
3827
  const selector = args[0];
3788
- const attributes = { elements, eventTypes, selector, callback, ...options, ...defaults };
3828
+ const attributes = { elements, eventTypes, selector, callback, ...options, ...overrides };
3789
3829
  return new (this)(attributes);
3790
3830
  }
3791
3831
  };
3792
3832
 
3793
3833
 
3794
3834
  /***/ }),
3795
- /* 40 */
3835
+ /* 41 */
3836
+ /***/ (() => {
3837
+
3838
+ const u = up.util;
3839
+ up.SelectorTracker = class SelectorTracker {
3840
+ constructor(selector, options, addCallback) {
3841
+ this._selector = selector;
3842
+ this._addCallback = addCallback;
3843
+ this._layer = options.layer || 'any';
3844
+ this._filter = options.filter || u.identity;
3845
+ this._live = options.live ?? true;
3846
+ this._knownMatches = new Map();
3847
+ }
3848
+ start() {
3849
+ this._sync();
3850
+ return u.sequence(this._trackFragments(), () => this._removeAllMatches());
3851
+ }
3852
+ _trackFragments() {
3853
+ if (this._live) {
3854
+ return up.on('up:fragment:inserted up:fragment:destroyed', () => this._sync());
3855
+ }
3856
+ }
3857
+ _sync() {
3858
+ let removeMap = new Map(this._knownMatches);
3859
+ this._knownMatches.clear();
3860
+ for (let newMatch of this._currentMatches) {
3861
+ let knownRemoveCallback = removeMap.get(newMatch);
3862
+ removeMap.delete(newMatch);
3863
+ let removeCallback = knownRemoveCallback || this._addCallback(newMatch) || u.noop;
3864
+ this._knownMatches.set(newMatch, removeCallback);
3865
+ }
3866
+ this._runRemoveCallbacks(removeMap);
3867
+ }
3868
+ get _currentMatches() {
3869
+ let allMatches = up.fragment.all(this._selector, { layer: this._layer });
3870
+ return this._filter(allMatches);
3871
+ }
3872
+ _removeAllMatches() {
3873
+ this._runRemoveCallbacks(this._knownMatches);
3874
+ }
3875
+ _runRemoveCallbacks(map) {
3876
+ for (let [element, removeCallback] of map) {
3877
+ removeCallback(element);
3878
+ }
3879
+ }
3880
+ };
3881
+
3882
+
3883
+ /***/ }),
3884
+ /* 42 */
3796
3885
  /***/ (() => {
3797
3886
 
3798
3887
  const u = up.util;
@@ -3800,40 +3889,49 @@ up.FieldWatcher = class FieldWatcher {
3800
3889
  constructor(root, options, callback) {
3801
3890
  this._options = options;
3802
3891
  this._root = root;
3803
- this._scope = up.form.getScope(root);
3804
3892
  this._callback = callback;
3805
3893
  this._batch = options.batch;
3894
+ this._logPrefix = options.logPrefix ?? 'up.watch()';
3895
+ this._ensureWatchable();
3806
3896
  }
3807
3897
  start() {
3808
3898
  this._scheduledValues = null;
3809
3899
  this._processedValues = this._readFieldValues();
3810
3900
  this._currentTimer = null;
3811
3901
  this._callbackRunning = false;
3812
- this._cleaner = u.cleaner();
3813
- this._watchFieldsWithin(this._root);
3814
- this._root.addEventListener('up:fragment:inserted', ({ target }) => {
3815
- if (target !== this._root)
3816
- this._watchFieldsWithin(target);
3817
- });
3818
- this._cleaner(up.fragment.onAborted(this._scope, () => this._abort()));
3819
- this._cleaner(up.on(this._scope, 'reset', () => this._onFormReset()));
3902
+ return u.sequence(up.form.trackFields(this._root, (field) => this._watchField(field)), this._trackAbort(), this._trackReset(), () => this._abort());
3820
3903
  }
3821
- stop() {
3822
- this._abort();
3823
- this._cleaner.clean();
3904
+ _ensureWatchable() {
3905
+ const fail = (message) => up.fail(message, this._logPrefix, this._root);
3906
+ if (!this._callback) {
3907
+ fail('No callback provided for %s (%o)');
3908
+ }
3909
+ if (this._root.matches('input[type=radio]')) {
3910
+ fail('Use %s with the container of a radio group, not with an individual radio button (%o)');
3911
+ }
3912
+ if (up.form.isField(this._root) && !this._root.name) {
3913
+ fail('%s can only watch fields with a name (%o)');
3914
+ }
3915
+ }
3916
+ _trackAbort() {
3917
+ let guard = ({ target }) => target.contains(this._region);
3918
+ return up.on('up:fragment:aborted', { guard }, () => this._abort());
3919
+ }
3920
+ _trackReset() {
3921
+ let guard = ({ target }) => target === this._region;
3922
+ return up.on('reset', { guard }, (event) => this._onFormReset(event));
3923
+ }
3924
+ get _region() {
3925
+ return up.form.getRegion(this._root);
3824
3926
  }
3825
3927
  _fieldOptions(field) {
3826
3928
  let rootOptions = u.copy(this._options);
3827
3929
  return up.form.watchOptions(field, rootOptions, { defaults: { event: 'input' } });
3828
3930
  }
3829
- _watchFieldsWithin(container) {
3830
- for (let field of up.form.fields(container)) {
3831
- this._watchField(field);
3832
- }
3833
- }
3834
3931
  _watchField(field) {
3835
3932
  let fieldOptions = this._fieldOptions(field);
3836
- this._cleaner(up.on(field, fieldOptions.event, () => this._check(fieldOptions)));
3933
+ let eventType = fieldOptions.event;
3934
+ return up.on(field, eventType, (event) => this._check(event, fieldOptions));
3837
3935
  }
3838
3936
  _abort() {
3839
3937
  this._scheduledValues = null;
@@ -3858,7 +3956,7 @@ up.FieldWatcher = class FieldWatcher {
3858
3956
  return;
3859
3957
  if (this._currentTimer)
3860
3958
  return;
3861
- if (!this._scope.isConnected)
3959
+ if (!up.fragment.isAlive(this._region))
3862
3960
  return;
3863
3961
  let callbackOptions = u.omit(this._scheduledFieldOptions, ['event', 'delay']);
3864
3962
  const diff = this._changedValues(this._processedValues, this._scheduledValues);
@@ -3903,20 +4001,114 @@ up.FieldWatcher = class FieldWatcher {
3903
4001
  _readFieldValues() {
3904
4002
  return up.Params.fromContainer(this._root).toObject();
3905
4003
  }
3906
- _check(fieldOptions = {}) {
4004
+ _check(event, fieldOptions = {}) {
3907
4005
  const values = this._readFieldValues();
3908
4006
  if (this._isNewValues(values)) {
4007
+ up.log.putsEvent(event);
3909
4008
  this._scheduleValues(values, fieldOptions);
3910
4009
  }
3911
4010
  }
3912
- _onFormReset() {
3913
- u.task(() => this._check());
4011
+ _onFormReset(event) {
4012
+ u.task(() => this._check(event));
3914
4013
  }
3915
4014
  };
3916
4015
 
3917
4016
 
3918
4017
  /***/ }),
3919
- /* 41 */
4018
+ /* 43 */
4019
+ /***/ (() => {
4020
+
4021
+ const u = up.util;
4022
+ const e = up.element;
4023
+ const BUILTIN_SWITCH_EFFECTS = [
4024
+ { attr: 'up-hide-for', toggle(target, active) { e.toggle(target, !active); } },
4025
+ { attr: 'up-show-for', toggle(target, active) { e.toggle(target, active); } },
4026
+ { attr: 'up-disable-for', toggle(target, active) { up.form.setDisabled(target, active); } },
4027
+ { attr: 'up-enable-for', toggle(target, active) { up.form.setDisabled(target, !active); } },
4028
+ ];
4029
+ up.Switcher = class Switcher {
4030
+ constructor(root) {
4031
+ this._root = root;
4032
+ this._switcheeSelector = root.getAttribute('up-switch') || up.fail("No switch target given for %o", root);
4033
+ this._regionSelector = root.getAttribute('up-switch-region');
4034
+ }
4035
+ start() {
4036
+ this._switchRegion();
4037
+ return u.sequence(this._trackFieldChanges(), this._trackNewSwitchees());
4038
+ }
4039
+ _trackFieldChanges() {
4040
+ let callback = () => this._onFieldChanged();
4041
+ return up.migrate.watchForSwitch?.(this._root, callback)
4042
+ || up.watch(this._root, { logPrefix: '[up-switch]' }, callback);
4043
+ }
4044
+ _trackNewSwitchees() {
4045
+ let filter = (matches) => {
4046
+ let scope = this._scope;
4047
+ return u.filter(matches, (match) => scope?.contains(match));
4048
+ };
4049
+ let onSwitcheeAdded = (switchee) => this._switchSwitchee(switchee);
4050
+ return up.fragment.trackSelector(this._switcheeSelector, { filter }, onSwitcheeAdded);
4051
+ }
4052
+ _onFieldChanged() {
4053
+ this._switchRegion();
4054
+ }
4055
+ _switchRegion() {
4056
+ const fieldTokens = this._buildFieldTokens();
4057
+ for (let switchee of this._findSwitchees()) {
4058
+ this._switchSwitchee(switchee, fieldTokens);
4059
+ }
4060
+ }
4061
+ _switchSwitchee(switchee, fieldTokens = this._buildFieldTokens()) {
4062
+ let previousValues = switchee.upSwitchValues;
4063
+ if (!u.isEqual(previousValues, fieldTokens)) {
4064
+ switchee.upSwitchValues = fieldTokens;
4065
+ this._switchSwitcheeNow(switchee, fieldTokens);
4066
+ }
4067
+ }
4068
+ _switchSwitcheeNow(switchee, fieldTokens) {
4069
+ for (let { attr, toggle } of BUILTIN_SWITCH_EFFECTS) {
4070
+ let attrValue = switchee.getAttribute(attr);
4071
+ if (attrValue) {
4072
+ let activeTokens = this._parseSwitcheeTokens(attrValue);
4073
+ let isActive = u.intersect(fieldTokens, activeTokens).length > 0;
4074
+ toggle(switchee, isActive);
4075
+ }
4076
+ }
4077
+ let log = ['Switching %o', switchee];
4078
+ up.emit(switchee, 'up:form:switch', { field: this._root, fieldTokens, log });
4079
+ }
4080
+ _findSwitchees() {
4081
+ let scope = this._scope;
4082
+ return scope ? up.fragment.subtree(scope, this._switcheeSelector) : [];
4083
+ }
4084
+ get _scope() {
4085
+ if (this._regionSelector) {
4086
+ return up.fragment.get(this._regionSelector, { origin: this._root });
4087
+ }
4088
+ else {
4089
+ return up.form.getRegion(this._root);
4090
+ }
4091
+ }
4092
+ _parseSwitcheeTokens(str) {
4093
+ return u.getSimpleTokens(str, { json: true });
4094
+ }
4095
+ _buildFieldTokens() {
4096
+ let values = up.Params.fromContainer(this._root).values();
4097
+ let tokens = [...values];
4098
+ let anyPresent = u.some(values, u.isPresent);
4099
+ tokens.push(anyPresent ? ':present' : ':blank');
4100
+ let fields = up.form.fields(this._root);
4101
+ if (fields[0]?.matches('[type=radio], [type=checkbox]')) {
4102
+ let anyChecked = u.some(fields, 'checked');
4103
+ tokens.push(anyChecked ? ':checked' : ':unchecked');
4104
+ }
4105
+ return tokens;
4106
+ }
4107
+ };
4108
+
4109
+
4110
+ /***/ }),
4111
+ /* 44 */
3920
4112
  /***/ (() => {
3921
4113
 
3922
4114
  const u = up.util;
@@ -3927,41 +4119,51 @@ up.FormValidator = class FormValidator {
3927
4119
  this._dirtySolutions = [];
3928
4120
  this._nextRenderTimer = null;
3929
4121
  this._rendering = false;
3930
- this._resetNextRenderPromise();
3931
4122
  this._honorAbort();
3932
4123
  }
4124
+ start() {
4125
+ let guard = (field) => this._isValidatingField(field);
4126
+ let callback = (field) => this._onFieldAdded(field);
4127
+ return up.form.trackFields(this._form, { guard }, callback);
4128
+ }
4129
+ _isValidatingField(field) {
4130
+ return field.closest('[up-validate]:not([up-validate=false])');
4131
+ }
4132
+ _onFieldAdded(field) {
4133
+ let eventType = up.form.validateOptions(field).event;
4134
+ return up.on(field, eventType, (event) => {
4135
+ up.log.putsEvent(event);
4136
+ up.error.muteUncriticalRejection(this.validate({ origin: field }));
4137
+ });
4138
+ }
3933
4139
  _honorAbort() {
3934
4140
  up.fragment.onAborted(this._form, (event) => this._onAborted(event));
3935
4141
  }
3936
4142
  _onAborted(event) {
3937
- if (this._dirtySolutions.length) {
3938
- this._dirtySolutions = [];
3939
- this._nextRenderPromise.reject(new up.Aborted(event.reason));
3940
- this._resetNextRenderPromise();
4143
+ let abortedError = new up.Aborted(event.reason);
4144
+ let solution;
4145
+ while (solution = this._dirtySolutions.shift()) {
4146
+ solution.deferred.reject(abortedError);
3941
4147
  }
3942
4148
  }
3943
- _resetNextRenderPromise() {
3944
- this._nextRenderPromise = u.newDeferred();
3945
- }
3946
- watchContainer(fieldOrForm) {
3947
- let { event } = this._originOptions(fieldOrForm);
3948
- let guard = () => up.fragment.isAlive(fieldOrForm);
3949
- let callback = () => up.error.muteUncriticalRejection(this.validate({ origin: fieldOrForm }));
3950
- up.on(fieldOrForm, event, { guard }, callback);
3951
- }
3952
4149
  validate(options = {}) {
3953
- let solutions = this._getSolutions(options);
3954
- this._dirtySolutions.push(...solutions);
4150
+ let newSolutions = this._getSolutions(options);
4151
+ this._dirtySolutions.push(...newSolutions);
3955
4152
  this._scheduleNextRender();
3956
- return this._nextRenderPromise;
4153
+ return newSolutions[0]?.deferred;
3957
4154
  }
3958
4155
  _getSolutions(options) {
3959
4156
  let solutions = this._getTargetSelectorSolutions(options)
3960
4157
  || this._getFieldSolutions(options)
3961
4158
  || this._getElementSolutions(options.origin);
4159
+ let deferred = u.newDeferred();
3962
4160
  for (let solution of solutions) {
3963
- solution.renderOptions = this._originOptions(solution.origin, options);
4161
+ let renderOptions = up.form.validateOptions(solution.origin, options);
4162
+ solution.batch = u.pluckKey(renderOptions, 'batch');
4163
+ solution.renderOptions = renderOptions;
4164
+ solution.destination = `${renderOptions.method} ${renderOptions.url}`;
3964
4165
  solution.target = up.fragment.resolveOrigin(solution.target, solution);
4166
+ solution.deferred = deferred;
3965
4167
  }
3966
4168
  return solutions;
3967
4169
  }
@@ -4013,9 +4215,6 @@ up.FormValidator = class FormValidator {
4013
4215
  return this._getTargetSelectorSolutions({ target, origin: field });
4014
4216
  }
4015
4217
  }
4016
- _originOptions(element, overrideOptions) {
4017
- return up.form.watchOptions(element, overrideOptions, { defaults: { event: 'change' } });
4018
- }
4019
4218
  _scheduleNextRender() {
4020
4219
  let solutionDelays = this._dirtySolutions.map((solution) => solution.renderOptions.delay);
4021
4220
  let shortestDelay = Math.min(...solutionDelays) || 0;
@@ -4035,33 +4234,53 @@ up.FormValidator = class FormValidator {
4035
4234
  return;
4036
4235
  if (this._nextRenderTimer)
4037
4236
  return;
4038
- let options = this._mergeRenderOptions(this._dirtySolutions);
4039
- this._dirtySolutions = [];
4237
+ let solutionsBatch = this._selectDirtySolutionsBatch();
4238
+ let renderOptions = this._mergeRenderOptions(solutionsBatch);
4040
4239
  this._rendering = true;
4041
- let renderingPromise = this._nextRenderPromise;
4042
- this._resetNextRenderPromise();
4043
4240
  try {
4044
- renderingPromise.resolve(up.render(options));
4045
- await renderingPromise;
4241
+ let renderPromise = up.render(renderOptions);
4242
+ for (let solution of solutionsBatch) {
4243
+ solution.deferred.resolve(renderPromise);
4244
+ }
4245
+ await renderPromise;
4046
4246
  }
4047
4247
  finally {
4048
4248
  this._rendering = false;
4049
4249
  this._renderDirtySolutions();
4050
4250
  }
4051
4251
  }
4252
+ _selectDirtySolutionsBatch() {
4253
+ let batch = [];
4254
+ let i = 0;
4255
+ while (i < this._dirtySolutions.length) {
4256
+ let solution = this._dirtySolutions[i];
4257
+ if (batch.length === 0 || this._canBatchSolutions(batch[0], solution)) {
4258
+ batch.push(solution);
4259
+ this._dirtySolutions.splice(i, 1);
4260
+ }
4261
+ else {
4262
+ i++;
4263
+ }
4264
+ }
4265
+ return batch;
4266
+ }
4267
+ _canBatchSolutions(s1, s2) {
4268
+ return s1.destination === s2.destination && s1.batch && s2.batch;
4269
+ }
4052
4270
  _mergeRenderOptions(dirtySolutions) {
4053
4271
  let dirtyOrigins = u.map(dirtySolutions, 'origin');
4054
4272
  let dirtyFields = u.flatMap(dirtyOrigins, up.form.fields);
4055
4273
  let dirtyNames = u.uniq(u.map(dirtyFields, 'name'));
4056
4274
  let dirtyRenderOptionsList = u.map(dirtySolutions, 'renderOptions');
4057
- let options = u.mergeDefined(...dirtyRenderOptionsList, up.form.destinationOptions(this._form));
4275
+ let formDestinationOptions = up.form.destinationOptions(this._form);
4276
+ let options = u.mergeDefined(formDestinationOptions, ...dirtyRenderOptionsList);
4058
4277
  options.target = u.map(dirtySolutions, 'target').join(', ');
4059
4278
  options.origin = this._form;
4060
4279
  options.focus ??= 'keep';
4061
4280
  options.failOptions = false;
4062
4281
  options.defaultMaybe = true;
4063
- options.params = up.Params.merge(options.params, ...u.map(dirtyRenderOptionsList, 'params'));
4064
- options.headers = u.merge(options.headers, ...u.map(dirtyRenderOptionsList, 'headers'));
4282
+ options.params = up.Params.merge(formDestinationOptions.params, ...u.map(dirtyRenderOptionsList, 'params'));
4283
+ options.headers = u.merge(formDestinationOptions.headers, ...u.map(dirtyRenderOptionsList, 'headers'));
4065
4284
  this._addValidateHeader(options.headers, dirtyNames);
4066
4285
  options.feedback = u.some(dirtyRenderOptionsList, 'feedback');
4067
4286
  options.data = undefined;
@@ -4089,15 +4308,11 @@ up.FormValidator = class FormValidator {
4089
4308
  value = ':unknown';
4090
4309
  headers[key] = value;
4091
4310
  }
4092
- static forElement(element) {
4093
- let form = up.form.get(element);
4094
- return form.upFormValidator ||= new this(form);
4095
- }
4096
4311
  };
4097
4312
 
4098
4313
 
4099
4314
  /***/ }),
4100
- /* 42 */
4315
+ /* 45 */
4101
4316
  /***/ (() => {
4102
4317
 
4103
4318
  up.FocusCapsule = class FocusCapsule {
@@ -4136,7 +4351,7 @@ up.FocusCapsule = class FocusCapsule {
4136
4351
 
4137
4352
 
4138
4353
  /***/ }),
4139
- /* 43 */
4354
+ /* 46 */
4140
4355
  /***/ (() => {
4141
4356
 
4142
4357
  const u = up.util;
@@ -4179,7 +4394,7 @@ up.FragmentProcessor = class FragmentProcessor extends up.Record {
4179
4394
  return this.processPrimitive(opt);
4180
4395
  }
4181
4396
  processArray(array) {
4182
- return u.find(array, opt => this.tryProcess(opt));
4397
+ return u.find(array, (opt) => this.tryProcess(opt));
4183
4398
  }
4184
4399
  resolveCondition(condition) {
4185
4400
  if (condition === 'main') {
@@ -4201,7 +4416,7 @@ up.FragmentProcessor = class FragmentProcessor extends up.Record {
4201
4416
 
4202
4417
 
4203
4418
  /***/ }),
4204
- /* 44 */
4419
+ /* 47 */
4205
4420
  /***/ (() => {
4206
4421
 
4207
4422
  const u = up.util;
@@ -4250,7 +4465,7 @@ up.FragmentFinder = class FragmentFinder {
4250
4465
 
4251
4466
 
4252
4467
  /***/ }),
4253
- /* 45 */
4468
+ /* 48 */
4254
4469
  /***/ (() => {
4255
4470
 
4256
4471
  const u = up.util;
@@ -4260,6 +4475,7 @@ up.FragmentFocus = class FragmentFocus extends up.FragmentProcessor {
4260
4475
  keys() {
4261
4476
  return super.keys().concat([
4262
4477
  'hash',
4478
+ 'focusVisible',
4263
4479
  'focusCapsule',
4264
4480
  'inputDevice',
4265
4481
  ]);
@@ -4316,7 +4532,12 @@ up.FragmentFocus = class FragmentFocus extends up.FragmentProcessor {
4316
4532
  }
4317
4533
  _focusElement(element) {
4318
4534
  if (element) {
4319
- up.focus(element, { force: true, ...PREVENT_SCROLL_OPTIONS, inputDevice: this.inputDevice });
4535
+ up.focus(element, {
4536
+ force: true,
4537
+ ...PREVENT_SCROLL_OPTIONS,
4538
+ inputDevice: this.inputDevice,
4539
+ focusVisible: this.focusVisible,
4540
+ });
4320
4541
  return true;
4321
4542
  }
4322
4543
  }
@@ -4333,7 +4554,7 @@ up.FragmentFocus = class FragmentFocus extends up.FragmentProcessor {
4333
4554
 
4334
4555
 
4335
4556
  /***/ }),
4336
- /* 46 */
4557
+ /* 49 */
4337
4558
  /***/ (() => {
4338
4559
 
4339
4560
  const e = up.element;
@@ -4373,7 +4594,7 @@ up.FragmentPolling = class FragmentPolling {
4373
4594
  if (this._state === 'started') {
4374
4595
  this._clearReloadTimer();
4375
4596
  this._state = 'stopped';
4376
- this.unbindEvents?.();
4597
+ this._unbindEvents?.();
4377
4598
  }
4378
4599
  }
4379
4600
  forceStart(options) {
@@ -4386,8 +4607,8 @@ up.FragmentPolling = class FragmentPolling {
4386
4607
  this.forceStarted = false;
4387
4608
  }
4388
4609
  _ensureEventsBound() {
4389
- if (!this.unbindEvents) {
4390
- this.unbindEvents = up.on('visibilitychange up:layer:opened up:layer:dismissed up:layer:accepted', this._onVisibilityChange.bind(this));
4610
+ if (!this._unbindEvents) {
4611
+ this._unbindEvents = up.on('visibilitychange up:layer:opened up:layer:dismissed up:layer:accepted', this._onVisibilityChange.bind(this));
4391
4612
  }
4392
4613
  }
4393
4614
  _onVisibilityChange() {
@@ -4419,6 +4640,11 @@ up.FragmentPolling = class FragmentPolling {
4419
4640
  if (this._state !== 'started') {
4420
4641
  return;
4421
4642
  }
4643
+ if (!up.fragment.isAlive(this._fragment)) {
4644
+ this._stop();
4645
+ up.puts('[up-poll]', 'Stopped polling a detached fragment');
4646
+ return;
4647
+ }
4422
4648
  if (!this._isFragmentVisible()) {
4423
4649
  up.puts('[up-poll]', 'Will not poll hidden fragment');
4424
4650
  return;
@@ -4488,7 +4714,7 @@ up.FragmentPolling = class FragmentPolling {
4488
4714
 
4489
4715
 
4490
4716
  /***/ }),
4491
- /* 47 */
4717
+ /* 50 */
4492
4718
  /***/ (() => {
4493
4719
 
4494
4720
  const u = up.util;
@@ -4505,8 +4731,10 @@ up.FragmentScrolling = class FragmentScrolling extends up.FragmentProcessor {
4505
4731
  }
4506
4732
  processPrimitive(opt) {
4507
4733
  switch (opt) {
4508
- case 'reset':
4509
- return this._reset();
4734
+ case 'top':
4735
+ return this._scrollTo(0);
4736
+ case 'bottom':
4737
+ return this._scrollTo(99999999);
4510
4738
  case 'layer':
4511
4739
  return this._revealLayer();
4512
4740
  case 'main':
@@ -4541,9 +4769,8 @@ up.FragmentScrolling = class FragmentScrolling extends up.FragmentProcessor {
4541
4769
  _revealLayer() {
4542
4770
  return this._revealElement(this.layer.getBoxElement());
4543
4771
  }
4544
- _reset() {
4545
- up.viewport.resetScroll({ ...this.attributes(), around: this.fragment });
4546
- return true;
4772
+ _scrollTo(position) {
4773
+ return up.viewport.scrollTo(position, { ...this.attributes(), around: this.fragment });
4547
4774
  }
4548
4775
  _restore() {
4549
4776
  return up.viewport.restoreScroll({ ...this.attributes(), around: this.fragment });
@@ -4552,7 +4779,7 @@ up.FragmentScrolling = class FragmentScrolling extends up.FragmentProcessor {
4552
4779
 
4553
4780
 
4554
4781
  /***/ }),
4555
- /* 48 */
4782
+ /* 51 */
4556
4783
  /***/ (() => {
4557
4784
 
4558
4785
  const e = up.element;
@@ -4578,14 +4805,15 @@ up.Layer = class Layer extends up.Record {
4578
4805
  }
4579
4806
  constructor(options = {}) {
4580
4807
  super(options);
4581
- if (!this.mode) {
4582
- throw "missing { mode } option";
4583
- }
4808
+ u.assert(this.mode);
4584
4809
  }
4585
4810
  setupHandlers() {
4586
4811
  up.link.convertClicks(this);
4812
+ this._unbindLocationChanged = up.on('up:location:changed', (event) => this._onBrowserLocationChanged(event));
4813
+ }
4814
+ teardownHandlers() {
4815
+ this._unbindLocationChanged?.();
4587
4816
  }
4588
- teardownHandlers() { }
4589
4817
  mainTargets() {
4590
4818
  return up.layer.mainTargets(this.mode);
4591
4819
  }
@@ -4684,28 +4912,28 @@ up.Layer = class Layer extends up.Record {
4684
4912
  return !this.element.isConnected;
4685
4913
  }
4686
4914
  saveHistory() {
4687
- if (this.history) {
4688
- this.savedTitle = document.title;
4689
- this.savedMetaTags = up.history.findMetaTags();
4690
- this.savedLocation = up.history.location;
4691
- this.savedLang = up.history.getLang();
4692
- }
4915
+ u.assert(this.isFront());
4916
+ if (!this.showsLiveHistory())
4917
+ return;
4918
+ this._savedTitle = this.title;
4919
+ this._savedMetaTags = this.metaTags;
4920
+ this._savedLocation = this.location;
4921
+ this._savedLang = this.lang;
4693
4922
  }
4694
4923
  restoreHistory() {
4695
- if (!this.showsLiveHistory()) {
4924
+ if (!this.showsLiveHistory())
4696
4925
  return;
4926
+ if (this._savedLocation) {
4927
+ up.history.push(this._savedLocation);
4697
4928
  }
4698
- if (this.savedLocation) {
4699
- up.history.push(this.savedLocation);
4700
- }
4701
- if (this.savedTitle) {
4702
- document.title = this.savedTitle;
4929
+ if (this._savedTitle) {
4930
+ document.title = this._savedTitle;
4703
4931
  }
4704
- if (this.savedMetaTags) {
4705
- up.history.updateMetaTags(this.savedMetaTags);
4932
+ if (this._savedMetaTags) {
4933
+ up.history.updateMetaTags(this._savedMetaTags);
4706
4934
  }
4707
- if (u.isString(this.savedLang)) {
4708
- up.history.updateLang(this.savedLang);
4935
+ if (u.isString(this._savedLang)) {
4936
+ up.history.updateLang(this._savedLang);
4709
4937
  }
4710
4938
  }
4711
4939
  asCurrent(fn) {
@@ -4713,32 +4941,37 @@ up.Layer = class Layer extends up.Record {
4713
4941
  }
4714
4942
  updateHistory(options) {
4715
4943
  if (u.isString(options.location)) {
4716
- this.location = options.location;
4944
+ this._updateLocation(options.location, { push: true });
4717
4945
  }
4718
4946
  if (up.history.config.updateMetaTags && u.isList(options.metaTags)) {
4719
4947
  up.migrate?.warnOfHungryMetaTags?.(options.metaTags);
4720
- this.metaTags = options.metaTags;
4948
+ this._updateMetaTags(options.metaTags);
4721
4949
  }
4722
4950
  if (u.isString(options.title)) {
4723
- this.title = options.title;
4951
+ this._updateTitle(options.title);
4724
4952
  }
4725
4953
  if (u.isString(options.lang)) {
4726
- this.lang = options.lang;
4954
+ this._updateLang(options.lang);
4727
4955
  }
4728
4956
  }
4729
4957
  showsLiveHistory() {
4730
4958
  return this.history && this.isFront();
4731
4959
  }
4960
+ _onBrowserLocationChanged({ location }) {
4961
+ if (this.showsLiveHistory()) {
4962
+ this._updateLocation(location, { push: false });
4963
+ }
4964
+ }
4732
4965
  get title() {
4733
4966
  if (this.showsLiveHistory()) {
4734
4967
  return document.title;
4735
4968
  }
4736
4969
  else {
4737
- return this.savedTitle;
4970
+ return this._savedTitle;
4738
4971
  }
4739
4972
  }
4740
- set title(title) {
4741
- this.savedTitle = title;
4973
+ _updateTitle(title) {
4974
+ this._savedTitle = title;
4742
4975
  if (this.showsLiveHistory()) {
4743
4976
  document.title = title;
4744
4977
  }
@@ -4748,11 +4981,11 @@ up.Layer = class Layer extends up.Record {
4748
4981
  return up.history.findMetaTags();
4749
4982
  }
4750
4983
  else {
4751
- return this.savedMetaTags;
4984
+ return this._savedMetaTags;
4752
4985
  }
4753
4986
  }
4754
- set metaTags(metaTags) {
4755
- this.savedMetaTags = metaTags;
4987
+ _updateMetaTags(metaTags) {
4988
+ this._savedMetaTags = metaTags;
4756
4989
  if (this.showsLiveHistory()) {
4757
4990
  up.history.updateMetaTags(metaTags);
4758
4991
  }
@@ -4762,11 +4995,11 @@ up.Layer = class Layer extends up.Record {
4762
4995
  return up.history.getLang();
4763
4996
  }
4764
4997
  else {
4765
- return this.savedLang;
4998
+ return this._savedLang;
4766
4999
  }
4767
5000
  }
4768
- set lang(lang) {
4769
- this.savedLang = lang;
5001
+ _updateLang(lang) {
5002
+ this._savedLang = lang;
4770
5003
  if (this.showsLiveHistory()) {
4771
5004
  up.history.updateLang(lang);
4772
5005
  }
@@ -4776,20 +5009,18 @@ up.Layer = class Layer extends up.Record {
4776
5009
  return up.history.location;
4777
5010
  }
4778
5011
  else {
4779
- return this.savedLocation;
5012
+ return this._savedLocation;
4780
5013
  }
4781
5014
  }
4782
- set location(location) {
4783
- const previousLocation = this.location;
4784
- location = u.normalizeURL(location);
4785
- if (previousLocation !== location || this.opening) {
4786
- this.savedLocation = location;
4787
- if (this.showsLiveHistory()) {
4788
- up.history.push(location);
4789
- }
4790
- if (!this.opening) {
4791
- this.emit('up:layer:location:changed', { location });
4792
- }
5015
+ _updateLocation(newLocation, { push }) {
5016
+ let prevSavedLocation = this._savedLocation;
5017
+ let liveLocation = up.history.location;
5018
+ this._savedLocation = newLocation;
5019
+ if (newLocation !== liveLocation && this.showsLiveHistory() && push) {
5020
+ up.history.push(newLocation);
5021
+ }
5022
+ if (newLocation !== prevSavedLocation && !this.opening) {
5023
+ this.emit('up:layer:location:changed', { location: newLocation, previousLocation: prevSavedLocation, log: false });
4793
5024
  }
4794
5025
  }
4795
5026
  selector(part) {
@@ -4818,7 +5049,7 @@ up.Layer = class Layer extends up.Record {
4818
5049
 
4819
5050
 
4820
5051
  /***/ }),
4821
- /* 49 */
5052
+ /* 52 */
4822
5053
  /***/ (() => {
4823
5054
 
4824
5055
  var _a;
@@ -4918,14 +5149,14 @@ up.Layer.Overlay = (_a = class Overlay extends up.Layer {
4918
5149
  }
4919
5150
  if (this._supportsDismissMethod('outside')) {
4920
5151
  if (this.viewportElement) {
4921
- up.on(this.viewportElement, 'up:click', event => {
5152
+ up.on(this.viewportElement, 'up:click', (event) => {
4922
5153
  if (event.target === this.viewportElement) {
4923
5154
  this._onOutsideClicked(event, true);
4924
5155
  }
4925
5156
  });
4926
5157
  }
4927
5158
  else {
4928
- this.unbindParentClicked = this.parent.on('up:click', (event, element) => {
5159
+ this._unbindParentClicked = this.parent.on('up:click', (event, element) => {
4929
5160
  if (!up.layer.isWithinForeignOverlay(element)) {
4930
5161
  const originClicked = this.origin && this.origin.contains(element);
4931
5162
  this._onOutsideClicked(event, originClicked);
@@ -4934,17 +5165,17 @@ up.Layer.Overlay = (_a = class Overlay extends up.Layer {
4934
5165
  }
4935
5166
  }
4936
5167
  if (this._supportsDismissMethod('key')) {
4937
- this.unbindEscapePressed = up.event.onEscape(event => this.onEscapePressed(event));
5168
+ this._unbindEscapePressed = up.event.onEscape((event) => this.onEscapePressed(event));
4938
5169
  }
4939
- this.registerClickCloser('up-accept', (value, closeOptions) => {
5170
+ this.registerAttrCloser('up-accept', (value, closeOptions) => {
4940
5171
  this.accept(value, closeOptions);
4941
5172
  });
4942
- this.registerClickCloser('up-dismiss', (value, closeOptions) => {
5173
+ this.registerAttrCloser('up-dismiss', (value, closeOptions) => {
4943
5174
  this.dismiss(value, closeOptions);
4944
5175
  });
4945
5176
  up.migrate.registerLayerCloser?.(this);
4946
- this._registerEventCloser(this.acceptEvent, this.accept);
4947
- this._registerEventCloser(this.dismissEvent, this.dismiss);
5177
+ this._registerExternalEventCloser(this.acceptEvent, this.accept);
5178
+ this._registerExternalEventCloser(this.dismissEvent, this.dismiss);
4948
5179
  this.on('up:click', 'label[for]', (event, label) => this._onLabelClicked(event, label));
4949
5180
  }
4950
5181
  _onLabelClicked(event, label) {
@@ -4979,26 +5210,38 @@ up.Layer.Overlay = (_a = class Overlay extends up.Layer {
4979
5210
  }
4980
5211
  }
4981
5212
  }
4982
- registerClickCloser(attribute, closeFn) {
4983
- let selector = `[${attribute}]`;
4984
- this.on('up:click', selector, function (event) {
5213
+ registerAttrCloser(attribute, closeFn) {
5214
+ this._registerClickCloser(attribute, closeFn);
5215
+ this._registerSubmitCloser(attribute, closeFn);
5216
+ }
5217
+ _registerClickCloser(attribute, closeFn) {
5218
+ this.on('up:click', `[${attribute}]:not(form)`, (event, link) => {
5219
+ up.event.halt(event, { log: true });
5220
+ const value = e.jsonAttr(link, attribute);
5221
+ this._onAttrCloserActivated(link, value, closeFn);
5222
+ });
5223
+ }
5224
+ _registerSubmitCloser(attribute, closeFn) {
5225
+ this.on('submit', `[${attribute}]`, (event, form) => {
4985
5226
  up.event.halt(event, { log: true });
4986
- const origin = event.target.closest(selector);
4987
- const value = e.jsonAttr(origin, attribute);
4988
- const closeOptions = { origin };
4989
- const parser = new up.OptionsParser(origin, closeOptions);
4990
- parser.booleanOrString('animation');
4991
- parser.string('easing');
4992
- parser.number('duration');
4993
- parser.string('confirm');
4994
- up.error.muteUncriticalSync(() => closeFn(value, closeOptions));
5227
+ const value = up.Params.fromForm(form);
5228
+ this._onAttrCloserActivated(form, value, closeFn);
4995
5229
  });
4996
5230
  }
4997
- _registerEventCloser(eventTypes, closeFn) {
5231
+ _onAttrCloserActivated(origin, value, closeFn) {
5232
+ const closeOptions = { origin };
5233
+ const parser = new up.OptionsParser(origin, closeOptions);
5234
+ parser.booleanOrString('animation');
5235
+ parser.string('easing');
5236
+ parser.number('duration');
5237
+ parser.string('confirm');
5238
+ up.error.muteUncriticalSync(() => closeFn(value, closeOptions));
5239
+ }
5240
+ _registerExternalEventCloser(eventTypes, closeFn) {
4998
5241
  if (!eventTypes) {
4999
5242
  return;
5000
5243
  }
5001
- return this.on(eventTypes, event => {
5244
+ return this.on(eventTypes, (event) => {
5002
5245
  event.preventDefault();
5003
5246
  up.error.muteUncriticalSync(() => closeFn.call(this, event, { response: event.response }));
5004
5247
  });
@@ -5018,8 +5261,8 @@ up.Layer.Overlay = (_a = class Overlay extends up.Layer {
5018
5261
  }
5019
5262
  teardownHandlers() {
5020
5263
  super.teardownHandlers();
5021
- this.unbindParentClicked?.();
5022
- this.unbindEscapePressed?.();
5264
+ this._unbindParentClicked?.();
5265
+ this._unbindEscapePressed?.();
5023
5266
  this.overlayFocus.teardown();
5024
5267
  }
5025
5268
  destroyElements(options) {
@@ -5101,11 +5344,12 @@ up.Layer.Overlay = (_a = class Overlay extends up.Layer {
5101
5344
  'closeEasing',
5102
5345
  'trapFocus',
5103
5346
  ],
5347
+ _a.UNSET_VISUALS = u.spanObject(_a.VISUAL_KEYS, undefined),
5104
5348
  _a);
5105
5349
 
5106
5350
 
5107
5351
  /***/ }),
5108
- /* 50 */
5352
+ /* 53 */
5109
5353
  /***/ (() => {
5110
5354
 
5111
5355
  up.Layer.OverlayWithTether = class OverlayWithTether extends up.Layer.Overlay {
@@ -5144,7 +5388,7 @@ up.Layer.OverlayWithTether = class OverlayWithTether extends up.Layer.Overlay {
5144
5388
 
5145
5389
 
5146
5390
  /***/ }),
5147
- /* 51 */
5391
+ /* 54 */
5148
5392
  /***/ (() => {
5149
5393
 
5150
5394
  up.Layer.OverlayWithViewport = class OverlayWithViewport extends up.Layer.Overlay {
@@ -5173,7 +5417,7 @@ up.Layer.OverlayWithViewport = class OverlayWithViewport extends up.Layer.Overla
5173
5417
 
5174
5418
 
5175
5419
  /***/ }),
5176
- /* 52 */
5420
+ /* 55 */
5177
5421
  /***/ (() => {
5178
5422
 
5179
5423
  var _a;
@@ -5219,7 +5463,7 @@ up.Layer.Root = (_a = class Root extends up.Layer {
5219
5463
 
5220
5464
 
5221
5465
  /***/ }),
5222
- /* 53 */
5466
+ /* 56 */
5223
5467
  /***/ (() => {
5224
5468
 
5225
5469
  var _a;
@@ -5230,7 +5474,7 @@ up.Layer.Modal = (_a = class Modal extends up.Layer.OverlayWithViewport {
5230
5474
 
5231
5475
 
5232
5476
  /***/ }),
5233
- /* 54 */
5477
+ /* 57 */
5234
5478
  /***/ (() => {
5235
5479
 
5236
5480
  var _a;
@@ -5241,7 +5485,7 @@ up.Layer.Popup = (_a = class Popup extends up.Layer.OverlayWithTether {
5241
5485
 
5242
5486
 
5243
5487
  /***/ }),
5244
- /* 55 */
5488
+ /* 58 */
5245
5489
  /***/ (() => {
5246
5490
 
5247
5491
  var _a;
@@ -5252,7 +5496,7 @@ up.Layer.Drawer = (_a = class Drawer extends up.Layer.OverlayWithViewport {
5252
5496
 
5253
5497
 
5254
5498
  /***/ }),
5255
- /* 56 */
5499
+ /* 59 */
5256
5500
  /***/ (() => {
5257
5501
 
5258
5502
  var _a;
@@ -5263,7 +5507,7 @@ up.Layer.Cover = (_a = class Cover extends up.Layer.OverlayWithViewport {
5263
5507
 
5264
5508
 
5265
5509
  /***/ }),
5266
- /* 57 */
5510
+ /* 60 */
5267
5511
  /***/ (() => {
5268
5512
 
5269
5513
  var _a;
@@ -5279,7 +5523,7 @@ up.LayerLookup = (_a = class LayerLookup {
5279
5523
  this._values = u.getSimpleTokens(options.layer);
5280
5524
  }
5281
5525
  all() {
5282
- let results = u.flatMap(this._values, value => this._resolveValue(value));
5526
+ let results = u.flatMap(this._values, (value) => this._resolveValue(value));
5283
5527
  results = u.compact(results);
5284
5528
  results = u.uniq(results);
5285
5529
  return results;
@@ -5294,7 +5538,7 @@ up.LayerLookup = (_a = class LayerLookup {
5294
5538
  }
5295
5539
  _forElement(element) {
5296
5540
  element = e.get(element);
5297
- return u.find(this._stack.reversed(), layer => layer.contains(element));
5541
+ return u.find(this._stack.reversed(), (layer) => layer.contains(element));
5298
5542
  }
5299
5543
  _forIndex(value) {
5300
5544
  return this._stack.at(value);
@@ -5376,7 +5620,7 @@ up.LayerLookup = (_a = class LayerLookup {
5376
5620
 
5377
5621
 
5378
5622
  /***/ }),
5379
- /* 58 */
5623
+ /* 61 */
5380
5624
  /***/ (() => {
5381
5625
 
5382
5626
  const u = up.util;
@@ -5490,7 +5734,7 @@ up.LayerStack = class LayerStack {
5490
5734
 
5491
5735
 
5492
5736
  /***/ }),
5493
- /* 59 */
5737
+ /* 62 */
5494
5738
  /***/ (() => {
5495
5739
 
5496
5740
  const u = up.util;
@@ -5520,11 +5764,16 @@ up.LinkCurrentURLs = class LinkCurrentURLs {
5520
5764
  this._upHREF === normalizedLocation ||
5521
5765
  this._aliasPattern?.test?.(normalizedLocation, false));
5522
5766
  }
5767
+ isAnyCurrent(normalizedLocations) {
5768
+ return normalizedLocations.some((normalizedLocation) => (this._href === normalizedLocation ||
5769
+ this._upHREF === normalizedLocation ||
5770
+ this._aliasPattern?.test?.(normalizedLocation, false)));
5771
+ }
5523
5772
  };
5524
5773
 
5525
5774
 
5526
5775
  /***/ }),
5527
- /* 60 */
5776
+ /* 63 */
5528
5777
  /***/ (() => {
5529
5778
 
5530
5779
  const u = up.util;
@@ -5565,13 +5814,15 @@ up.LinkFollowIntent = class LinkFollowIntent {
5565
5814
  }
5566
5815
  _runCallback(event) {
5567
5816
  up.log.putsEvent(event);
5817
+ if (!up.fragment.isAlive(this._link))
5818
+ return;
5568
5819
  this._callback({ onRequestKnown: (request) => this._lastRequest = request });
5569
5820
  }
5570
5821
  };
5571
5822
 
5572
5823
 
5573
5824
  /***/ }),
5574
- /* 61 */
5825
+ /* 64 */
5575
5826
  /***/ (() => {
5576
5827
 
5577
5828
  const u = up.util;
@@ -5613,7 +5864,7 @@ up.MotionController = class MotionController {
5613
5864
  }
5614
5865
  _expandFinishRequest(elements) {
5615
5866
  if (elements) {
5616
- return u.flatMap(elements, el => e.list(el.closest(this._selector), el.querySelectorAll(this._selector)));
5867
+ return u.flatMap(elements, (el) => e.list(el.closest(this._selector), el.querySelectorAll(this._selector)));
5617
5868
  }
5618
5869
  else {
5619
5870
  return document.querySelectorAll(this._selector);
@@ -5667,10 +5918,9 @@ up.MotionController = class MotionController {
5667
5918
 
5668
5919
 
5669
5920
  /***/ }),
5670
- /* 62 */
5921
+ /* 65 */
5671
5922
  /***/ (() => {
5672
5923
 
5673
- const u = up.util;
5674
5924
  const e = up.element;
5675
5925
  up.NonceableCallback = class NonceableCallback {
5676
5926
  constructor(script, nonce) {
@@ -5724,37 +5974,11 @@ up.NonceableCallback = class NonceableCallback {
5724
5974
  }
5725
5975
  }
5726
5976
  }
5727
- _allowedBy(allowedNonces) {
5728
- return this.nonce && u.contains(allowedNonces, this.nonce);
5729
- }
5730
- static adoptNonces(element, allowedNonces) {
5731
- if (!allowedNonces?.length) {
5732
- return;
5733
- }
5734
- const getPageNonce = u.memoize(up.protocol.cspNonce);
5735
- u.each(up.script.config.nonceableAttributes, (attribute) => {
5736
- let matches = e.subtree(element, `[${attribute}^="nonce-"]`);
5737
- u.each(matches, (match) => {
5738
- let attributeValue = match.getAttribute(attribute);
5739
- let callback = this.fromString(attributeValue);
5740
- let warn = (message, ...args) => up.log.warn('up.render()', `Cannot use callback [${attribute}="${attributeValue}"]: ${message}`, ...args);
5741
- if (!callback._allowedBy(allowedNonces)) {
5742
- return warn("Callback's CSP nonce (%o) does not match response header (%o)", callback.nonce, allowedNonces);
5743
- }
5744
- let pageNonce = getPageNonce();
5745
- if (!pageNonce) {
5746
- return warn("Current page's CSP nonce is unknown");
5747
- }
5748
- callback.nonce = pageNonce;
5749
- match.setAttribute(attribute, callback.toString());
5750
- });
5751
- });
5752
- }
5753
5977
  };
5754
5978
 
5755
5979
 
5756
5980
  /***/ }),
5757
- /* 63 */
5981
+ /* 66 */
5758
5982
  /***/ (() => {
5759
5983
 
5760
5984
  const e = up.element;
@@ -5776,7 +6000,7 @@ up.OverlayFocus = class OverlayFocus {
5776
6000
  'aria-modal': this._trapFocus.toString()
5777
6001
  });
5778
6002
  if (this._trapFocus) {
5779
- this._untrapFocus = up.on('focusin', event => this._onFocus(event));
6003
+ this._untrapFocus = up.on('focusin', (event) => this._onFocus(event));
5780
6004
  this._focusTrapBefore = e.affix(this._focusElement, 'beforebegin', 'up-focus-trap[tabindex=0]');
5781
6005
  this._focusTrapAfter = e.affix(this._focusElement, 'afterend', 'up-focus-trap[tabindex=0]');
5782
6006
  }
@@ -5827,7 +6051,7 @@ up.OverlayFocus = class OverlayFocus {
5827
6051
 
5828
6052
 
5829
6053
  /***/ }),
5830
- /* 64 */
6054
+ /* 67 */
5831
6055
  /***/ (() => {
5832
6056
 
5833
6057
  const u = up.util;
@@ -5873,15 +6097,12 @@ up.Params = class Params {
5873
6097
  return formData;
5874
6098
  }
5875
6099
  toQuery() {
5876
- let parts = u.map(this.entries, this._arrayEntryToQuery.bind(this));
5877
- parts = u.compact(parts);
6100
+ let simpleEntries = this.withoutBinaryEntries().entries;
6101
+ let parts = simpleEntries.map(this._arrayEntryToQuery);
5878
6102
  return parts.join('&');
5879
6103
  }
5880
6104
  _arrayEntryToQuery(entry) {
5881
6105
  const { value } = entry;
5882
- if (this._isBinaryValue(value)) {
5883
- return;
5884
- }
5885
6106
  let query = encodeURIComponent(entry.name);
5886
6107
  if (u.isGiven(value)) {
5887
6108
  query += "=";
@@ -5889,12 +6110,15 @@ up.Params = class Params {
5889
6110
  }
5890
6111
  return query;
5891
6112
  }
5892
- _isBinaryValue(value) {
6113
+ _isBinaryEntry({ value }) {
5893
6114
  return value instanceof Blob;
5894
6115
  }
5895
- hasBinaryValues() {
5896
- const values = u.map(this.entries, 'value');
5897
- return u.some(values, this._isBinaryValue);
6116
+ hasBinaryEntries() {
6117
+ return u.some(this.entries, this._isBinaryEntry);
6118
+ }
6119
+ withoutBinaryEntries() {
6120
+ let simpleEntries = u.reject(this.entries, this._isBinaryEntry);
6121
+ return new this.constructor(simpleEntries);
5898
6122
  }
5899
6123
  toURL(base) {
5900
6124
  let parts = [base, this.toQuery()];
@@ -5924,9 +6148,15 @@ up.Params = class Params {
5924
6148
  this._addAllFromObject(raw);
5925
6149
  }
5926
6150
  else {
5927
- up.fail("Unsupport params type: %o", raw);
6151
+ up.fail("Unsupported params type: %o", raw);
5928
6152
  }
5929
6153
  }
6154
+ keys() {
6155
+ return u.map(this.entries, 'name');
6156
+ }
6157
+ values() {
6158
+ return u.map(this.entries, 'value');
6159
+ }
5930
6160
  _addAllFromObject(object) {
5931
6161
  for (let key in object) {
5932
6162
  const value = object[key];
@@ -5964,7 +6194,7 @@ up.Params = class Params {
5964
6194
  this.entries = u.reject(this.entries, this._matchEntryFn(name));
5965
6195
  }
5966
6196
  _matchEntryFn(name) {
5967
- return entry => entry.name === name;
6197
+ return (entry) => entry.name === name;
5968
6198
  }
5969
6199
  get(name) {
5970
6200
  if (this._isArrayKey(name)) {
@@ -5979,16 +6209,11 @@ up.Params = class Params {
5979
6209
  return entry?.value;
5980
6210
  }
5981
6211
  getAll(name) {
5982
- if (this._isArrayKey(name)) {
5983
- return this.getAll(name);
5984
- }
5985
- else {
5986
- const entries = u.map(this.entries, this._matchEntryFn(name));
5987
- return u.map(entries, 'value');
5988
- }
6212
+ const entries = u.filter(this.entries, this._matchEntryFn(name));
6213
+ return u.map(entries, 'value');
5989
6214
  }
5990
6215
  _isArrayKey(key) {
5991
- return key.endsWith('[]');
6216
+ return u.evalOption(up.form.config.arrayParam, key);
5992
6217
  }
5993
6218
  [u.isBlank.key]() {
5994
6219
  return this.entries.length === 0;
@@ -6051,17 +6276,21 @@ up.Params = class Params {
6051
6276
  static stripURL(url) {
6052
6277
  return u.normalizeURL(url, { search: false });
6053
6278
  }
6054
- static merge(...objects) {
6055
- return objects.reduce(function (allParams, params) {
6056
- allParams.addAll(params);
6057
- return allParams;
6058
- }, new up.Params());
6279
+ static merge(start, ...objects) {
6280
+ let merged = u.copy(start);
6281
+ for (let object of objects) {
6282
+ let other = u.wrapValue(this, object);
6283
+ for (let key of other.keys())
6284
+ merged.delete(key);
6285
+ merged.addAll(other);
6286
+ }
6287
+ return merged;
6059
6288
  }
6060
6289
  };
6061
6290
 
6062
6291
 
6063
6292
  /***/ }),
6064
- /* 65 */
6293
+ /* 68 */
6065
6294
  /***/ (() => {
6066
6295
 
6067
6296
  const u = up.util;
@@ -6132,7 +6361,7 @@ up.Preview = class Preview {
6132
6361
  }
6133
6362
  disable(...args) {
6134
6363
  let [element] = this._parseMutatorArgs(args, 'val');
6135
- this.undo(up.form.disable(element));
6364
+ this.undo(up.form.disableTemp(element));
6136
6365
  }
6137
6366
  insert(...args) {
6138
6367
  let [reference, position = 'beforeend', tempValue] = this._parseMutatorArgs(args, 'val', u.isAdjacentPosition, 'val');
@@ -6195,7 +6424,7 @@ up.Preview = class Preview {
6195
6424
 
6196
6425
 
6197
6426
  /***/ }),
6198
- /* 66 */
6427
+ /* 69 */
6199
6428
  /***/ (() => {
6200
6429
 
6201
6430
  const e = up.element;
@@ -6245,7 +6474,7 @@ up.ProgressBar = class ProgressBar {
6245
6474
 
6246
6475
 
6247
6476
  /***/ }),
6248
- /* 67 */
6477
+ /* 70 */
6249
6478
  /***/ (() => {
6250
6479
 
6251
6480
  const u = up.util;
@@ -6341,7 +6570,7 @@ up.RenderOptions = (function () {
6341
6570
  return u.merge(preprocessedOptions.defaults, lateDefaults, preprocessedOptions);
6342
6571
  }
6343
6572
  function assertContentGiven(options) {
6344
- if (!u.some(CONTENT_KEYS, contentKey => u.isGiven(options[contentKey]))) {
6573
+ if (!u.some(CONTENT_KEYS, (contentKey) => u.isGiven(options[contentKey]))) {
6345
6574
  if (options.defaultToEmptyContent) {
6346
6575
  options.content = '';
6347
6576
  }
@@ -6362,19 +6591,22 @@ up.RenderOptions = (function () {
6362
6591
  return overrides;
6363
6592
  }
6364
6593
  function deriveFailOptions(preprocessedOptions) {
6594
+ let markFailure = { didFail: true };
6365
6595
  let overrides = failOverrides(preprocessedOptions);
6366
6596
  if (preprocessedOptions.failOptions) {
6367
6597
  return {
6368
6598
  ...preprocessedOptions.defaults,
6369
6599
  ...u.pick(preprocessedOptions, SHARED_KEYS),
6370
6600
  ...overrides,
6371
- ...{ failPrefixForced: true }
6601
+ didForceFailOptions: true,
6602
+ ...markFailure,
6372
6603
  };
6373
6604
  }
6374
6605
  else {
6375
6606
  return {
6376
6607
  ...preprocessedOptions,
6377
6608
  ...overrides,
6609
+ ...markFailure,
6378
6610
  };
6379
6611
  }
6380
6612
  }
@@ -6391,7 +6623,7 @@ up.RenderOptions = (function () {
6391
6623
 
6392
6624
 
6393
6625
  /***/ }),
6394
- /* 68 */
6626
+ /* 71 */
6395
6627
  /***/ (() => {
6396
6628
 
6397
6629
  up.RenderResult = class RenderResult extends up.Record {
@@ -6400,13 +6632,14 @@ up.RenderResult = class RenderResult extends up.Record {
6400
6632
  'fragments',
6401
6633
  'layer',
6402
6634
  'target',
6403
- 'options',
6635
+ 'renderOptions',
6404
6636
  'finished',
6405
6637
  ];
6406
6638
  }
6407
6639
  defaults() {
6408
6640
  return {
6409
6641
  fragments: [],
6642
+ finished: Promise.resolve(),
6410
6643
  };
6411
6644
  }
6412
6645
  get none() {
@@ -6415,13 +6648,15 @@ up.RenderResult = class RenderResult extends up.Record {
6415
6648
  get fragment() {
6416
6649
  return this.fragments[0];
6417
6650
  }
6651
+ get ok() {
6652
+ return !this.renderOptions.didFail;
6653
+ }
6418
6654
  static both(main, extension, mergeFinished = true) {
6419
- if (!extension)
6655
+ if (!extension) {
6420
6656
  return main;
6657
+ }
6421
6658
  return new this({
6422
- target: main.target,
6423
- layer: main.layer,
6424
- options: main.options,
6659
+ ...main,
6425
6660
  fragments: main.fragments.concat(extension.fragments),
6426
6661
  finished: (mergeFinished && this.mergeFinished(main, extension))
6427
6662
  });
@@ -6429,17 +6664,11 @@ up.RenderResult = class RenderResult extends up.Record {
6429
6664
  static async mergeFinished(main, extension) {
6430
6665
  return this.both(await main.finished, await extension.finished, false);
6431
6666
  }
6432
- static buildNone() {
6433
- return new this({
6434
- target: ':none',
6435
- finished: Promise.resolve(),
6436
- });
6437
- }
6438
6667
  };
6439
6668
 
6440
6669
 
6441
6670
  /***/ }),
6442
- /* 69 */
6671
+ /* 72 */
6443
6672
  /***/ (() => {
6444
6673
 
6445
6674
  var _a;
@@ -6466,6 +6695,8 @@ up.Request = (_a = class Request extends up.Record {
6466
6695
  'failMode',
6467
6696
  'failContext',
6468
6697
  'origin',
6698
+ 'originLayer',
6699
+ 'originMode',
6469
6700
  'builtAt',
6470
6701
  'wrapMethod',
6471
6702
  'contentType',
@@ -6478,30 +6709,31 @@ up.Request = (_a = class Request extends up.Record {
6478
6709
  ];
6479
6710
  }
6480
6711
  defaults() {
6712
+ let config = up.network.config;
6481
6713
  return {
6482
6714
  state: 'new',
6483
6715
  abortable: true,
6484
6716
  headers: {},
6485
- timeout: up.network.config.timeout,
6717
+ timeout: config.timeout,
6486
6718
  builtAt: new Date(),
6487
6719
  previews: [],
6720
+ wrapMethod: config.wrapMethod,
6488
6721
  };
6489
6722
  }
6490
6723
  constructor(options) {
6491
6724
  super(options);
6492
6725
  this.params = new up.Params(this.params);
6493
- if (this.wrapMethod == null) {
6494
- this.wrapMethod = up.network.config.wrapMethod;
6495
- }
6496
6726
  this._normalize();
6497
6727
  if ((this.target || this.layer || this.origin) && !options.basic) {
6498
6728
  const layerLookupOptions = { origin: this.origin };
6499
6729
  this.layer = up.layer.get(this.layer, layerLookupOptions);
6500
- this.failLayer = up.layer.get(this.failLayer, layerLookupOptions);
6501
6730
  this.context ||= this.layer.context || {};
6502
- this.failContext ||= this.failLayer?.context || {};
6503
6731
  this.mode ||= this.layer.mode;
6732
+ this.failLayer = up.layer.get(this.failLayer, layerLookupOptions);
6733
+ this.failContext ||= this.failLayer?.context || {};
6504
6734
  this.failMode ||= this.failLayer?.mode;
6735
+ this.originLayer ||= up.layer.get(this.origin) || up.layer.current;
6736
+ this.originMode ||= this.originLayer?.mode;
6505
6737
  }
6506
6738
  this.bindLayer = options.bindLayer || this.layer;
6507
6739
  this._fragments = options.fragments;
@@ -6548,8 +6780,9 @@ up.Request = (_a = class Request extends up.Record {
6548
6780
  u.task(() => {
6549
6781
  this.layer = undefined;
6550
6782
  this.failLayer = undefined;
6551
- this._bindLayer = undefined;
6783
+ this.bindLayer = undefined;
6552
6784
  this.origin = undefined;
6785
+ this.originLayer = undefined;
6553
6786
  this._fragments = undefined;
6554
6787
  this._bindFragments = undefined;
6555
6788
  });
@@ -6703,6 +6936,7 @@ up.Request = (_a = class Request extends up.Record {
6703
6936
  status: this.xhr.status,
6704
6937
  title: up.protocol.titleFromXHR(this.xhr),
6705
6938
  target: up.protocol.targetFromXHR(this.xhr),
6939
+ openLayer: up.protocol.openLayerFromXHR(this.xhr),
6706
6940
  acceptLayer: up.protocol.acceptLayerFromXHR(this.xhr),
6707
6941
  dismissLayer: up.protocol.dismissLayerFromXHR(this.xhr),
6708
6942
  eventPlans: up.protocol.eventPlansFromXHR(this.xhr),
@@ -6756,7 +6990,7 @@ up.Request = (_a = class Request extends up.Record {
6756
6990
  return this.headers[name];
6757
6991
  }
6758
6992
  _setAutoHeaders() {
6759
- for (let key of ['target', 'failTarget', 'mode', 'failMode', 'context', 'failContext']) {
6993
+ for (let key of ['target', 'failTarget', 'mode', 'failMode', 'context', 'failContext', 'originMode']) {
6760
6994
  this._setPropertyHeader(key);
6761
6995
  }
6762
6996
  let csrfHeader, csrfToken;
@@ -6817,7 +7051,7 @@ up.Request = (_a = class Request extends up.Record {
6817
7051
 
6818
7052
 
6819
7053
  /***/ }),
6820
- /* 70 */
7054
+ /* 73 */
6821
7055
  /***/ (() => {
6822
7056
 
6823
7057
  const u = up.util;
@@ -6898,15 +7132,6 @@ up.Request.Cache = class Cache {
6898
7132
  this._requests.push(request);
6899
7133
  this._limitSize();
6900
7134
  }
6901
- alias(existingCachedRequest, newRequest) {
6902
- existingCachedRequest = this.get(existingCachedRequest);
6903
- if (!existingCachedRequest)
6904
- return;
6905
- newRequest = this._wrap(newRequest);
6906
- this.track(existingCachedRequest, newRequest, { force: true });
6907
- this.put(newRequest);
6908
- return newRequest;
6909
- }
6910
7135
  async track(existingRequest, newRequest, options = {}) {
6911
7136
  newRequest.trackedRequest = existingRequest;
6912
7137
  newRequest.state = 'tracking';
@@ -6982,7 +7207,7 @@ up.Request.Cache = class Cache {
6982
7207
 
6983
7208
 
6984
7209
  /***/ }),
6985
- /* 71 */
7210
+ /* 74 */
6986
7211
  /***/ (() => {
6987
7212
 
6988
7213
  const u = up.util;
@@ -7000,7 +7225,7 @@ up.Request.Queue = class Queue {
7000
7225
  }
7001
7226
  asap(request) {
7002
7227
  request.runQueuedCallbacks();
7003
- u.always(request, responseOrError => this._onRequestSettled(request, responseOrError));
7228
+ u.always(request, () => this._onRequestSettled(request));
7004
7229
  this._scheduleSlowTimer(request);
7005
7230
  this._queueRequest(request);
7006
7231
  queueMicrotask(() => this._poke());
@@ -7031,7 +7256,7 @@ up.Request.Queue = class Queue {
7031
7256
  this._queuedRequests.push(request);
7032
7257
  }
7033
7258
  _pluckNextRequest() {
7034
- let request = u.find(this._queuedRequests, request => !request.background);
7259
+ let request = u.find(this._queuedRequests, (request) => !request.background);
7035
7260
  request ||= this._queuedRequests[0];
7036
7261
  return u.remove(this._queuedRequests, request);
7037
7262
  }
@@ -7040,11 +7265,8 @@ up.Request.Queue = class Queue {
7040
7265
  this._currentRequests.push(request);
7041
7266
  }
7042
7267
  }
7043
- _onRequestSettled(request, responseOrError) {
7268
+ _onRequestSettled(request) {
7044
7269
  u.remove(this._currentRequests, request) || u.remove(this._queuedRequests, request);
7045
- if ((responseOrError instanceof up.Response) && responseOrError.ok) {
7046
- up.network.registerAliasForRedirect(request, responseOrError);
7047
- }
7048
7270
  queueMicrotask(() => this._poke());
7049
7271
  u.task(() => this._checkForRecover());
7050
7272
  }
@@ -7093,7 +7315,7 @@ up.Request.Queue = class Queue {
7093
7315
 
7094
7316
 
7095
7317
  /***/ }),
7096
- /* 72 */
7318
+ /* 75 */
7097
7319
  /***/ (() => {
7098
7320
 
7099
7321
  const u = up.util;
@@ -7104,7 +7326,7 @@ up.Request.FormRenderer = class FormRenderer {
7104
7326
  this._request = request;
7105
7327
  }
7106
7328
  buildAndSubmit() {
7107
- this.params = u.copy(this._request.params);
7329
+ this.params = this._request.params.withoutBinaryEntries();
7108
7330
  let action = this._request.url;
7109
7331
  let { method } = this._request;
7110
7332
  const paramsFromQuery = up.Params.fromURL(action);
@@ -7132,7 +7354,7 @@ up.Request.FormRenderer = class FormRenderer {
7132
7354
 
7133
7355
 
7134
7356
  /***/ }),
7135
- /* 73 */
7357
+ /* 76 */
7136
7358
  /***/ (() => {
7137
7359
 
7138
7360
  var _a;
@@ -7181,7 +7403,7 @@ up.Request.XHRRenderer = (_a = class XHRRenderer {
7181
7403
  this._contentType = this._request.contentType;
7182
7404
  if (!this._payload && this._request.allowsPayload()) {
7183
7405
  if (!this._contentType) {
7184
- this._contentType = this._params.hasBinaryValues() ? CONTENT_TYPE_FORM_DATA : CONTENT_TYPE_URL_ENCODED;
7406
+ this._contentType = this._params.hasBinaryEntries() ? CONTENT_TYPE_FORM_DATA : CONTENT_TYPE_URL_ENCODED;
7185
7407
  }
7186
7408
  if (this._contentType === CONTENT_TYPE_FORM_DATA) {
7187
7409
  this._contentType = null;
@@ -7203,7 +7425,7 @@ up.Request.XHRRenderer = (_a = class XHRRenderer {
7203
7425
 
7204
7426
 
7205
7427
  /***/ }),
7206
- /* 74 */
7428
+ /* 77 */
7207
7429
  /***/ (() => {
7208
7430
 
7209
7431
  const u = up.util;
@@ -7218,6 +7440,7 @@ up.Response = class Response extends up.Record {
7218
7440
  'xhr',
7219
7441
  'target',
7220
7442
  'title',
7443
+ 'openLayer',
7221
7444
  'acceptLayer',
7222
7445
  'dismissLayer',
7223
7446
  'eventPlans',
@@ -7232,7 +7455,7 @@ up.Response = class Response extends up.Record {
7232
7455
  defaults() {
7233
7456
  return {
7234
7457
  headers: {},
7235
- loadedAt: new Date()
7458
+ loadedAt: new Date(),
7236
7459
  };
7237
7460
  }
7238
7461
  get ok() {
@@ -7251,8 +7474,9 @@ up.Response = class Response extends up.Record {
7251
7474
  get contentType() {
7252
7475
  return this.header('Content-Type');
7253
7476
  }
7254
- get cspNonces() {
7255
- return up.protocol.cspNoncesFromHeader(this.header('Content-Security-Policy') || this.header('Content-Security-Policy-Report-Only'));
7477
+ get cspInfo() {
7478
+ let policy = this.header('Content-Security-Policy') || this.header('Content-Security-Policy-Report-Only');
7479
+ return up.protocol.cspInfoFromHeader(policy);
7256
7480
  }
7257
7481
  get lastModified() {
7258
7482
  let header = this.header('Last-Modified');
@@ -7277,19 +7501,33 @@ up.Response = class Response extends up.Record {
7277
7501
  get description() {
7278
7502
  return `HTTP ${this.status} response to ${this.request.description}`;
7279
7503
  }
7504
+ get redirect() {
7505
+ return (this.url !== this.request.url) || (this.method !== this.request.method);
7506
+ }
7507
+ get redirectRequest() {
7508
+ if (!this.redirect)
7509
+ return;
7510
+ let finalRequest = u.variant(this.request, {
7511
+ method: this.method,
7512
+ url: this.url,
7513
+ cacheRoute: null,
7514
+ });
7515
+ up.cache.track(this.request, finalRequest, { force: true });
7516
+ return finalRequest;
7517
+ }
7280
7518
  };
7281
7519
 
7282
7520
 
7283
7521
  /***/ }),
7284
- /* 75 */
7522
+ /* 78 */
7285
7523
  /***/ (() => {
7286
7524
 
7287
7525
  var _a;
7288
7526
  const u = up.util;
7289
7527
  const e = up.element;
7290
- const FULL_DOCUMENT_PATTERN = /^\s*<(html|!DOCTYPE)\b/i;
7528
+ const FULL_DOCUMENT_PATTERN = /^\s*(<!--[^-]*.*?-->\s*)*<(html|!DOCTYPE)\b/i;
7291
7529
  up.ResponseDoc = (_a = class ResponseDoc {
7292
- constructor({ document, fragment, content, target, origin, data, cspNonces, match }) {
7530
+ constructor({ document, fragment, content, target, origin, data, cspInfo, match }) {
7293
7531
  if (document) {
7294
7532
  this._parseDocument(document, origin, data);
7295
7533
  }
@@ -7299,7 +7537,7 @@ up.ResponseDoc = (_a = class ResponseDoc {
7299
7537
  else {
7300
7538
  this._parseContent(content || '', origin, target, data);
7301
7539
  }
7302
- this._cspNonces = cspNonces;
7540
+ this._cspInfo = cspInfo || {};
7303
7541
  if (origin) {
7304
7542
  let originSelector = up.fragment.tryToTarget(origin);
7305
7543
  if (originSelector) {
@@ -7328,9 +7566,6 @@ up.ResponseDoc = (_a = class ResponseDoc {
7328
7566
  this._document = this._buildFauxDocument(value);
7329
7567
  }
7330
7568
  }
7331
- _parseDocumentFromHTML(html) {
7332
- return e.createBrokenDocumentFromHTML(html);
7333
- }
7334
7569
  _parseFragment(value, origin, data) {
7335
7570
  let element = e.extractSingular(up.fragment.provideNodes(value, { origin, data }));
7336
7571
  this._document = this._buildFauxDocument(element);
@@ -7368,7 +7603,14 @@ up.ResponseDoc = (_a = class ResponseDoc {
7368
7603
  return this._fromHead(up.history.findMetaTags);
7369
7604
  }
7370
7605
  get assets() {
7371
- return this._fromHead(up.script.findAssets);
7606
+ return this._fromHead((head) => {
7607
+ let assets = up.script.findAssets(head);
7608
+ return u.map(assets, (asset) => {
7609
+ this._adoptNoncesInSubtree(asset);
7610
+ let clone = this._reviveElementAsClone(asset);
7611
+ return clone;
7612
+ });
7613
+ });
7372
7614
  }
7373
7615
  get lang() {
7374
7616
  if (this._isFullDocument) {
@@ -7420,21 +7662,43 @@ up.ResponseDoc = (_a = class ResponseDoc {
7420
7662
  throw new up.CannotMatch();
7421
7663
  }
7422
7664
  }
7665
+ _disableScriptsInSubtree(element) {
7666
+ let pageNonce = up.protocol.cspNonce();
7667
+ up.script.disableSubtree(element, (script) => !this._isScriptAllowed(script, pageNonce));
7668
+ }
7669
+ _isScriptAllowed(scriptElement, pageNonce) {
7670
+ let strategy = up.fragment.config.runScripts;
7671
+ if (strategy === true && this._cspInfo.declaration?.includes("'strict-dynamic'")) {
7672
+ return pageNonce && (pageNonce === scriptElement.nonce);
7673
+ }
7674
+ else {
7675
+ return u.evalOption(strategy, scriptElement);
7676
+ }
7677
+ }
7678
+ _reviveElementAsClone(element) {
7679
+ return e.revivedClone(element);
7680
+ }
7681
+ _reviveSubtreeInPlace(element) {
7682
+ if (this._document instanceof Document) {
7683
+ for (let brokenElement of e.subtree(element, ':is(noscript, script, audio, video):not(.up-keeping, .up-keeping *)')) {
7684
+ let clone = this._reviveElementAsClone(brokenElement);
7685
+ brokenElement.replaceWith(clone);
7686
+ }
7687
+ }
7688
+ }
7689
+ _adoptNoncesInSubtree(element) {
7690
+ up.script.adoptNoncesInSubtree(element, this._cspInfo.nonces);
7691
+ }
7423
7692
  commitElement(element) {
7424
7693
  if (this._document.contains(element)) {
7425
- if (!up.fragment.config.runScripts) {
7426
- up.script.disableSubtree(element);
7427
- }
7694
+ this._adoptNoncesInSubtree(element);
7695
+ this._disableScriptsInSubtree(element);
7428
7696
  element.remove();
7429
7697
  return true;
7430
7698
  }
7431
7699
  }
7432
7700
  finalizeElement(element) {
7433
- up.NonceableCallback.adoptNonces(element, this._cspNonces);
7434
- if (this._document instanceof Document) {
7435
- let brokenElements = e.subtree(element, ':is(noscript,script,audio,video):not(.up-keeping, .up-keeping *)');
7436
- u.each(brokenElements, e.fixParserDamage);
7437
- }
7701
+ this._reviveSubtreeInPlace(element);
7438
7702
  }
7439
7703
  },
7440
7704
  (() => {
@@ -7446,7 +7710,7 @@ up.ResponseDoc = (_a = class ResponseDoc {
7446
7710
 
7447
7711
 
7448
7712
  /***/ }),
7449
- /* 76 */
7713
+ /* 79 */
7450
7714
  /***/ (() => {
7451
7715
 
7452
7716
  const e = up.element;
@@ -7536,7 +7800,7 @@ up.RevealMotion = class RevealMotion {
7536
7800
 
7537
7801
 
7538
7802
  /***/ }),
7539
- /* 77 */
7803
+ /* 80 */
7540
7804
  /***/ (() => {
7541
7805
 
7542
7806
  const u = up.util;
@@ -7558,7 +7822,7 @@ up.Selector = class Selector {
7558
7822
  this._layers = up.layer.getAll(options);
7559
7823
  if (!this._layers.length)
7560
7824
  throw new up.CannotMatch(["Unknown layer: %o", options.layer]);
7561
- this._filters.push(match => u.some(this._layers, layer => layer.contains(match)));
7825
+ this._filters.push((match) => u.some(this._layers, (layer) => layer.contains(match)));
7562
7826
  expandTargetLayer = this._layers[0];
7563
7827
  }
7564
7828
  this._selectors = up.fragment.expandTargets(selector, { ...options, layer: expandTargetLayer });
@@ -7593,7 +7857,7 @@ up.Selector = class Selector {
7593
7857
  });
7594
7858
  }
7595
7859
  _passesFilter(element) {
7596
- return element && u.every(this._filters, filter => filter(element));
7860
+ return element && u.every(this._filters, (filter) => filter(element));
7597
7861
  }
7598
7862
  _filterOne(element) {
7599
7863
  return u.presence(element, this._passesFilter.bind(this));
@@ -7605,7 +7869,7 @@ up.Selector = class Selector {
7605
7869
 
7606
7870
 
7607
7871
  /***/ }),
7608
- /* 78 */
7872
+ /* 81 */
7609
7873
  /***/ (() => {
7610
7874
 
7611
7875
  const u = up.util;
@@ -7725,7 +7989,7 @@ up.Tether = class Tether {
7725
7989
 
7726
7990
 
7727
7991
  /***/ }),
7728
- /* 79 */
7992
+ /* 82 */
7729
7993
  /***/ (() => {
7730
7994
 
7731
7995
  const u = up.util;
@@ -7798,7 +8062,7 @@ up.URLPattern = class URLPattern {
7798
8062
 
7799
8063
 
7800
8064
  /***/ }),
7801
- /* 80 */
8065
+ /* 83 */
7802
8066
  /***/ (() => {
7803
8067
 
7804
8068
  up.framework = (function () {
@@ -7806,7 +8070,7 @@ up.framework = (function () {
7806
8070
  function emitReset() {
7807
8071
  up.emit('up:framework:reset', { log: false });
7808
8072
  }
7809
- function boot() {
8073
+ function boot({ mode = 'manual' } = {}) {
7810
8074
  if (readyState !== 'configuring') {
7811
8075
  console.error('Unpoly has already booted');
7812
8076
  return;
@@ -7814,9 +8078,9 @@ up.framework = (function () {
7814
8078
  let issue = supportIssue();
7815
8079
  if (!issue) {
7816
8080
  readyState = 'booting';
7817
- up.emit('up:framework:boot', { log: false });
8081
+ up.emit('up:framework:boot', { mode, log: false });
7818
8082
  readyState = 'booted';
7819
- up.emit('up:framework:booted', { log: false });
8083
+ up.emit('up:framework:booted', { mode, log: false });
7820
8084
  }
7821
8085
  else {
7822
8086
  console.error("Unpoly cannot boot: %s", issue);
@@ -7840,7 +8104,7 @@ up.framework = (function () {
7840
8104
  console.debug('Call up.boot() after you have configured Unpoly');
7841
8105
  }
7842
8106
  else {
7843
- document.addEventListener('DOMContentLoaded', boot);
8107
+ document.addEventListener('DOMContentLoaded', () => boot({ mode: 'auto' }));
7844
8108
  }
7845
8109
  readyState = 'configuring';
7846
8110
  }
@@ -7887,7 +8151,7 @@ up.boot = up.framework.boot;
7887
8151
 
7888
8152
 
7889
8153
  /***/ }),
7890
- /* 81 */
8154
+ /* 84 */
7891
8155
  /***/ (() => {
7892
8156
 
7893
8157
  up.event = (function () {
@@ -7939,9 +8203,8 @@ up.event = (function () {
7939
8203
  event.preventDefault();
7940
8204
  }
7941
8205
  const keyModifiers = ['metaKey', 'shiftKey', 'ctrlKey', 'altKey'];
7942
- function isUnmodified(event) {
7943
- return (u.isUndefined(event.button) || (event.button === 0)) &&
7944
- !u.some(keyModifiers, modifier => event[modifier]);
8206
+ function isModified(event) {
8207
+ return (event.button > 0) || u.some(keyModifiers, (modifier) => event[modifier]);
7945
8208
  }
7946
8209
  function isSyntheticClick(event) {
7947
8210
  return u.isMissing(event.clientX);
@@ -7962,7 +8225,7 @@ up.event = (function () {
7962
8225
  return newEvent;
7963
8226
  }
7964
8227
  function executeEmitAttr(event, element) {
7965
- if (!isUnmodified(event)) {
8228
+ if (isModified(event)) {
7966
8229
  return;
7967
8230
  }
7968
8231
  const eventType = e.attr(element, 'up-emit');
@@ -7991,7 +8254,7 @@ up.event = (function () {
7991
8254
  assertEmitted,
7992
8255
  onEscape,
7993
8256
  halt,
7994
- isUnmodified,
8257
+ isModified,
7995
8258
  isSyntheticClick,
7996
8259
  fork,
7997
8260
  keyModifiers,
@@ -8004,14 +8267,14 @@ up.emit = up.event.emit;
8004
8267
 
8005
8268
 
8006
8269
  /***/ }),
8007
- /* 82 */
8270
+ /* 85 */
8008
8271
  /***/ (() => {
8009
8272
 
8010
8273
  up.protocol = (function () {
8011
8274
  const u = up.util;
8012
8275
  const e = up.element;
8013
8276
  const headerize = function (camel) {
8014
- const header = camel.replace(/(^.|[A-Z])/g, char => '-' + char.toUpperCase());
8277
+ const header = camel.replace(/(^.|[A-Z])/g, (char) => '-' + char.toUpperCase());
8015
8278
  return 'X-Up' + header;
8016
8279
  };
8017
8280
  const extractHeader = function (xhr, shortHeader, parseFn = u.identity) {
@@ -8049,6 +8312,9 @@ up.protocol = (function () {
8049
8312
  function eventPlansFromXHR(xhr) {
8050
8313
  return extractHeader(xhr, 'events', u.parseRelaxedJSON);
8051
8314
  }
8315
+ function openLayerFromXHR(xhr) {
8316
+ return extractHeader(xhr, 'openLayer', u.parseRelaxedJSON);
8317
+ }
8052
8318
  function acceptLayerFromXHR(xhr) {
8053
8319
  return extractHeader(xhr, 'acceptLayer', u.parseRelaxedJSON);
8054
8320
  }
@@ -8084,21 +8350,26 @@ up.protocol = (function () {
8084
8350
  function cspNonce() {
8085
8351
  return u.evalOption(config.cspNonce);
8086
8352
  }
8087
- function cspNoncesFromHeader(cspHeader) {
8088
- let nonces = [];
8353
+ const NONCE_PATTERN = /'nonce-([^']+)'/g;
8354
+ function findNonces(cspPart) {
8355
+ let matches = cspPart.matchAll(NONCE_PATTERN);
8356
+ return u.map(matches, '1');
8357
+ }
8358
+ function cspInfoFromHeader(cspHeader) {
8359
+ let results = {};
8089
8360
  if (cspHeader) {
8090
- let parts = cspHeader.split(/\s*;\s*/);
8091
- for (let part of parts) {
8092
- if (part.indexOf('script-src') === 0) {
8093
- let noncePattern = /'nonce-([^']+)'/g;
8094
- let match;
8095
- while (match = noncePattern.exec(part)) {
8096
- nonces.push(match[1]);
8097
- }
8361
+ let declarations = cspHeader.split(/\s*;\s*/);
8362
+ for (let declaration of declarations) {
8363
+ let directive = declaration.match(/^(script|default)-src:/)?.[1];
8364
+ if (directive) {
8365
+ results[directive] = {
8366
+ declaration: declaration,
8367
+ nonces: findNonces(declaration)
8368
+ };
8098
8369
  }
8099
8370
  }
8100
8371
  }
8101
- return nonces;
8372
+ return results.script || results.default || {};
8102
8373
  }
8103
8374
  function wrapMethod(method, params) {
8104
8375
  params.add(config.methodParam, method);
@@ -8110,6 +8381,7 @@ up.protocol = (function () {
8110
8381
  titleFromXHR,
8111
8382
  targetFromXHR,
8112
8383
  methodFromXHR,
8384
+ openLayerFromXHR,
8113
8385
  acceptLayerFromXHR,
8114
8386
  contextFromXHR,
8115
8387
  dismissLayerFromXHR,
@@ -8123,13 +8395,13 @@ up.protocol = (function () {
8123
8395
  initialRequestMethod,
8124
8396
  headerize,
8125
8397
  wrapMethod,
8126
- cspNoncesFromHeader,
8398
+ cspInfoFromHeader,
8127
8399
  };
8128
8400
  })();
8129
8401
 
8130
8402
 
8131
8403
  /***/ }),
8132
- /* 83 */
8404
+ /* 86 */
8133
8405
  /***/ (() => {
8134
8406
 
8135
8407
  up.log = (function () {
@@ -8142,24 +8414,26 @@ up.log = (function () {
8142
8414
  }
8143
8415
  const printToWarn = (...args) => printToStream('warn', ...args);
8144
8416
  const printToError = (...args) => printToStream('error', ...args);
8145
- function printToStream(stream, trace, message, ...args) {
8146
- printToStreamStyled(stream, trace, '', message, ...args);
8417
+ function printToStream(stream, prefix, message, ...args) {
8418
+ printToStreamStyled(stream, prefix, '', message, ...args);
8147
8419
  }
8148
- function printToStreamStyled(stream, trace, customStyles, message, ...args) {
8420
+ function printToStreamStyled(stream, prefix, customStyles, message, ...args) {
8149
8421
  if (message) {
8150
8422
  if (config.format) {
8151
- console[stream](`%c${trace}%c ${message}`, 'color: #666666; padding: 1px 3px; border: 1px solid #bbbbbb; border-radius: 2px; font-size: 90%; display: inline-block;' + customStyles, '', ...args);
8423
+ console[stream](`%c${prefix}%c ${message}`, 'color: #666666; padding: 1px 3px; border: 1px solid #bbbbbb; border-radius: 2px; font-size: 90%; display: inline-block;' + customStyles, '', ...args);
8152
8424
  }
8153
8425
  else {
8154
- console[stream](`[${trace}] ${u.sprintf(message, ...args)}`);
8426
+ console[stream](`[${prefix}] ${u.sprintf(message, ...args)}`);
8155
8427
  }
8156
8428
  }
8157
8429
  }
8430
+ let lastPrintedUserEvent;
8158
8431
  function printUserEvent(event) {
8159
- if (config.enabled) {
8160
- event = event.originalEvent || event;
8432
+ if (config.enabled && lastPrintedUserEvent !== event) {
8433
+ lastPrintedUserEvent = event;
8434
+ let originalEvent = event.originalEvent || event;
8161
8435
  let color = '#5566cc';
8162
- printToStreamStyled('log', event.type, `color: white; border-color: ${color}; background-color: ${color}`, 'Interaction on %o', event.target);
8436
+ printToStreamStyled('log', originalEvent.type, `color: white; border-color: ${color}; background-color: ${color}`, 'Interaction on %o', originalEvent.target);
8163
8437
  }
8164
8438
  }
8165
8439
  function printBanner() {
@@ -8210,7 +8484,7 @@ up.warn = up.log.warn;
8210
8484
 
8211
8485
 
8212
8486
  /***/ }),
8213
- /* 84 */
8487
+ /* 87 */
8214
8488
  /***/ (() => {
8215
8489
 
8216
8490
  up.script = (function () {
@@ -8261,6 +8535,7 @@ up.script = (function () {
8261
8535
  '[up-expand]': -300,
8262
8536
  '[data-method]': -400,
8263
8537
  '[data-confirm]': -400,
8538
+ '[up-keep]': 9999999999,
8264
8539
  };
8265
8540
  let registeredCompilers = [];
8266
8541
  let registeredMacros = [];
@@ -8392,16 +8667,41 @@ up.script = (function () {
8392
8667
  up.event.assertEmitted('up:assets:changed', { oldAssets, newAssets, renderOptions });
8393
8668
  }
8394
8669
  }
8395
- function disableScript(scriptElement) {
8396
- scriptElement.type = 'up-disabled-script';
8670
+ function disableScriptsInSubtree(root, guard = () => true) {
8671
+ for (let script of findScripts(root)) {
8672
+ if (guard(script)) {
8673
+ script.type = 'up-disabled-script';
8674
+ }
8675
+ }
8397
8676
  }
8398
- function disableScriptsInSubtree(root) {
8399
- let selector = config.selector('scriptSelectors');
8400
- u.each(e.subtree(root, selector), disableScript);
8677
+ function findScripts(root, selectorSuffix = '') {
8678
+ let selector = config.selector('scriptSelectors') + selectorSuffix;
8679
+ return e.subtree(root, selector);
8401
8680
  }
8402
8681
  function isScript(value) {
8403
8682
  return config.matches(value, 'scriptSelectors');
8404
8683
  }
8684
+ function adoptNoncesInSubtree(root, responseNonces) {
8685
+ let pageNonce = up.protocol.cspNonce();
8686
+ if (!responseNonces?.length || !pageNonce)
8687
+ return;
8688
+ for (let script of findScripts(root, '[nonce]')) {
8689
+ if (responseNonces.includes(script.nonce)) {
8690
+ script.nonce = pageNonce;
8691
+ }
8692
+ }
8693
+ for (let attribute of config.nonceableAttributes) {
8694
+ let matches = e.subtree(root, `[${attribute}^="nonce-"]`);
8695
+ for (let match of matches) {
8696
+ let attributeValue = match.getAttribute(attribute);
8697
+ let callback = up.NonceableCallback.fromString(attributeValue);
8698
+ if (responseNonces.includes(callback.nonce)) {
8699
+ callback.nonce = pageNonce;
8700
+ match.setAttribute(attribute, callback.toString());
8701
+ }
8702
+ }
8703
+ }
8704
+ }
8405
8705
  function reset() {
8406
8706
  registeredCompilers = u.filter(registeredCompilers, 'isDefault');
8407
8707
  registeredMacros = u.filter(registeredMacros, 'isDefault');
@@ -8419,6 +8719,7 @@ up.script = (function () {
8419
8719
  findAssets,
8420
8720
  assertAssetsOK,
8421
8721
  disableSubtree: disableScriptsInSubtree,
8722
+ adoptNoncesInSubtree,
8422
8723
  isScript,
8423
8724
  };
8424
8725
  })();
@@ -8431,7 +8732,7 @@ up.attribute = up.script.attrCompiler;
8431
8732
 
8432
8733
 
8433
8734
  /***/ }),
8434
- /* 85 */
8735
+ /* 88 */
8435
8736
  /***/ (() => {
8436
8737
 
8437
8738
  up.history = (function () {
@@ -8457,59 +8758,77 @@ up.history = (function () {
8457
8758
  }));
8458
8759
  let previousLocation;
8459
8760
  let nextPreviousLocation;
8761
+ let nextTrackOptions;
8762
+ let adoptedBases = new up.FIFOCache({ capacity: 100, normalizeKey: getBase });
8763
+ function isAdopted(location) {
8764
+ return !!adoptedBases.get(location);
8765
+ }
8460
8766
  function reset() {
8461
8767
  previousLocation = undefined;
8462
8768
  nextPreviousLocation = undefined;
8463
- trackCurrentLocation();
8769
+ nextTrackOptions = undefined;
8770
+ adoptedBases.clear();
8771
+ trackCurrentLocation({ reason: null, alreadyHandled: true });
8772
+ adopt();
8464
8773
  }
8465
8774
  function currentLocation() {
8466
8775
  return u.normalizeURL(location.href);
8467
8776
  }
8468
- function trackCurrentLocation() {
8469
- const url = currentLocation();
8470
- if (nextPreviousLocation !== url) {
8777
+ function trackCurrentLocation(trackOptions) {
8778
+ let { reason, alreadyHandled } = nextTrackOptions || trackOptions;
8779
+ let location = currentLocation();
8780
+ if (nextPreviousLocation !== location) {
8471
8781
  previousLocation = nextPreviousLocation;
8472
- nextPreviousLocation = url;
8782
+ nextPreviousLocation = location;
8783
+ if (reason === 'detect') {
8784
+ reason = (getBase(location) === getBase(previousLocation)) ? 'hash' : 'pop';
8785
+ }
8786
+ let willHandle = !alreadyHandled && isAdopted(location);
8787
+ let locationChangedEvent = up.event.build('up:location:changed', {
8788
+ reason,
8789
+ location,
8790
+ previousLocation,
8791
+ alreadyHandled,
8792
+ willHandle,
8793
+ log: `New location is ${location}`
8794
+ });
8795
+ up.migrate.prepareLocationChangedEvent?.(locationChangedEvent);
8796
+ if (reason) {
8797
+ up.emit(locationChangedEvent);
8798
+ reactToChange(locationChangedEvent);
8799
+ }
8473
8800
  }
8474
8801
  }
8475
- trackCurrentLocation();
8802
+ function splitLocation(location) {
8803
+ return location?.split(/(?=#)/) || [];
8804
+ }
8805
+ function getBase(location) {
8806
+ return splitLocation(location)[0];
8807
+ }
8476
8808
  function isLocation(url, options) {
8477
8809
  return u.matchURLs(url, location.href, { hash: true, ...options });
8478
8810
  }
8479
- function replace(location, options = {}) {
8480
- location = u.normalizeURL(location);
8481
- if (manipulate('replaceState', location) && (options.event !== false)) {
8482
- emitLocationChanged({ location, reason: 'replace', log: `Replaced state for ${location}` });
8483
- }
8484
- }
8485
- function push(location) {
8486
- location = u.normalizeURL(location);
8487
- if (!isLocation(location) && manipulate('pushState', location)) {
8488
- emitLocationChanged({ location, reason: 'push', log: `Advanced to location ${location}` });
8489
- }
8811
+ function replace(location, trackOptions) {
8812
+ placeAdoptedHistoryEntry('replaceState', location, trackOptions);
8490
8813
  }
8491
- function emitLocationChanged(props) {
8492
- let event = up.event.build('up:location:changed', props);
8493
- up.migrate?.renamedProperty?.(event, 'url', 'location');
8494
- up.emit(event);
8814
+ function push(location, trackOptions) {
8815
+ if (isLocation(location))
8816
+ return;
8817
+ placeAdoptedHistoryEntry('pushState', location, trackOptions);
8495
8818
  }
8496
- function manipulate(method, url) {
8819
+ function placeAdoptedHistoryEntry(method, location, trackOptions) {
8820
+ adopt(location);
8497
8821
  if (config.enabled) {
8498
- const state = buildState();
8499
- window.history[method](state, '', url);
8500
- trackCurrentLocation();
8501
- return true;
8822
+ nextTrackOptions = trackOptions;
8823
+ history[method](null, '', location);
8824
+ nextTrackOptions = undefined;
8502
8825
  }
8503
8826
  }
8504
- function buildState() {
8505
- return { up: {} };
8827
+ function adopt(location = currentLocation()) {
8828
+ location = u.normalizeURL(location);
8829
+ adoptedBases.set(location, true);
8506
8830
  }
8507
- function restoreStateOnPop(state) {
8508
- if (!state?.up) {
8509
- up.puts('popstate', 'Ignoring a history state not owned by Unpoly');
8510
- return;
8511
- }
8512
- let location = currentLocation();
8831
+ function restoreLocation(location) {
8513
8832
  up.error.muteUncriticalRejection(up.render({
8514
8833
  guardEvent: up.event.build('up:location:restore', { location, log: `Restoring location ${location}` }),
8515
8834
  url: location,
@@ -8527,28 +8846,23 @@ up.history = (function () {
8527
8846
  focus: ['restore', 'auto'],
8528
8847
  }));
8529
8848
  }
8530
- function onPop(event) {
8531
- trackCurrentLocation();
8532
- let location = currentLocation();
8533
- emitLocationChanged({ location, reason: 'pop', log: `Navigated to history entry ${location}` });
8534
- up.viewport.saveFocus({ location: previousLocation });
8535
- up.viewport.saveScroll({ location: previousLocation });
8536
- restoreStateOnPop(event.state);
8537
- }
8538
- function register() {
8539
- window.addEventListener('popstate', onPop);
8540
- if (up.protocol.initialRequestMethod() === 'GET') {
8541
- replace(currentLocation(), { event: false });
8849
+ function reactToChange(event) {
8850
+ if (event.alreadyHandled) {
8851
+ return;
8542
8852
  }
8543
- }
8544
- up.on('up:framework:boot', function () {
8545
- if ('jasmine' in window) {
8546
- register();
8853
+ if (!event.willHandle) {
8854
+ up.puts('up.history', 'Ignoring history entry owned by foreign script');
8855
+ return;
8547
8856
  }
8548
- else {
8549
- setTimeout(register, 100);
8857
+ if (event.reason === 'pop') {
8858
+ up.viewport.saveFocus({ location: event.previousLocation });
8859
+ up.viewport.saveScroll({ location: event.previousLocation });
8860
+ restoreLocation(event.location);
8550
8861
  }
8551
- });
8862
+ else if (event.reason === 'hash') {
8863
+ up.viewport.revealHash(location.hash, { strong: true });
8864
+ }
8865
+ }
8552
8866
  function findMetaTags(head = document.head) {
8553
8867
  return head.querySelectorAll(config.selector('metaTagSelectors'));
8554
8868
  }
@@ -8570,6 +8884,61 @@ up.history = (function () {
8570
8884
  function updateLang(newLang) {
8571
8885
  e.setAttrPresence(e.root, 'lang', newLang, !!newLang);
8572
8886
  }
8887
+ function patchHistoryAPI() {
8888
+ const originalPushState = history.pushState;
8889
+ history.pushState = function (...args) {
8890
+ originalPushState.apply(this, args);
8891
+ trackCurrentLocation({ reason: 'push', alreadyHandled: true });
8892
+ };
8893
+ const originalReplaceState = history.replaceState;
8894
+ history.replaceState = function (...args) {
8895
+ originalReplaceState.apply(this, args);
8896
+ trackCurrentLocation({ reason: 'replace', alreadyHandled: true });
8897
+ };
8898
+ }
8899
+ function adoptInitialHistoryEntry() {
8900
+ if (up.protocol.initialRequestMethod() === 'GET') {
8901
+ adopt();
8902
+ }
8903
+ }
8904
+ up.on('up:framework:boot', function ({ mode }) {
8905
+ trackCurrentLocation({ reason: null, alreadyHandled: true });
8906
+ patchHistoryAPI();
8907
+ adoptInitialHistoryEntry();
8908
+ if (mode === 'auto') {
8909
+ up.viewport.revealHash(location.hash, { strong: true });
8910
+ }
8911
+ });
8912
+ up.on(window, 'hashchange, popstate', () => {
8913
+ trackCurrentLocation({ reason: 'detect', alreadyHandled: false });
8914
+ });
8915
+ function onJumpLinkClicked(event, link) {
8916
+ if (event.defaultPrevented)
8917
+ return;
8918
+ if (up.event.isModified(event))
8919
+ return;
8920
+ let [currentBase, currentHash] = splitLocation(up.layer.current.location);
8921
+ let [linkBase, linkHash] = splitLocation(u.normalizeURL(link));
8922
+ let verbatimHREF = link.getAttribute('href');
8923
+ let isJumpLink = (currentBase === linkBase) || verbatimHREF.startsWith('#');
8924
+ if (!isJumpLink)
8925
+ return;
8926
+ let behavior = link.getAttribute('up-scroll-behavior') ?? 'auto';
8927
+ let layer = up.layer.get(link);
8928
+ let revealFn = up.viewport.revealHashFn(linkHash, { layer, behavior });
8929
+ if (revealFn) {
8930
+ up.event.halt(event);
8931
+ up.log.putsEvent(event);
8932
+ if (linkHash !== currentHash && layer.showsLiveHistory()) {
8933
+ let newHREF = currentBase + linkHash;
8934
+ push(newHREF, { reason: 'hash', alreadyHandled: true });
8935
+ }
8936
+ revealFn();
8937
+ }
8938
+ else {
8939
+ }
8940
+ }
8941
+ up.on('up:click', 'a[href*="#"]', onJumpLinkClicked);
8573
8942
  up.macro('[up-back]', function (link) {
8574
8943
  if (previousLocation) {
8575
8944
  e.setMissingAttrs(link, {
@@ -8597,10 +8966,10 @@ up.history = (function () {
8597
8966
 
8598
8967
 
8599
8968
  /***/ }),
8600
- /* 86 */
8969
+ /* 89 */
8601
8970
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
8602
8971
 
8603
- __webpack_require__(87);
8972
+ __webpack_require__(90);
8604
8973
  const u = up.util;
8605
8974
  const e = up.element;
8606
8975
  up.fragment = (function () {
@@ -8645,6 +9014,7 @@ up.fragment = (function () {
8645
9014
  saveScroll: true,
8646
9015
  saveFocus: true,
8647
9016
  focus: 'keep',
9017
+ focusVisible: 'auto',
8648
9018
  abort: 'target',
8649
9019
  failOptions: true,
8650
9020
  feedback: true,
@@ -8659,12 +9029,13 @@ up.fragment = (function () {
8659
9029
  peel: true,
8660
9030
  },
8661
9031
  match: 'region',
8662
- runScripts: true,
9032
+ runScripts: false,
8663
9033
  autoHistoryTargets: [':main'],
8664
9034
  autoFocus: ['hash', 'autofocus', 'main-if-main', 'keep', 'target-if-lost'],
8665
9035
  autoScroll: ['hash', 'layer-if-main'],
8666
9036
  autoRevalidate: (response) => response.expired,
8667
9037
  skipResponse: defaultSkipResponse,
9038
+ normalizeKeepHTML: defaultNormalizeKeepHTML
8668
9039
  }));
8669
9040
  u.delegate(config, ['mainTargets'], () => up.layer.config.any);
8670
9041
  function defaultSkipResponse({ response, expiredResponse }) {
@@ -8700,17 +9071,84 @@ up.fragment = (function () {
8700
9071
  const options = parseTargetAndOptions(args);
8701
9072
  return render({ ...options, navigate: true });
8702
9073
  });
9074
+ function emitFragmentKeep(keepPlan) {
9075
+ let { oldElement, newElement: newFragment, newData, renderOptions } = keepPlan;
9076
+ const log = ['Keeping fragment %o', oldElement];
9077
+ const callback = e.callbackAttr(keepPlan.oldElement, 'up-on-keep', { exposedKeys: ['newFragment', 'newData'] });
9078
+ const event = up.event.build('up:fragment:keep', { newFragment, newData, renderOptions });
9079
+ return up.emit(oldElement, event, { log, callback });
9080
+ }
9081
+ function findKeepPlan(options) {
9082
+ if (options.keep === false)
9083
+ return;
9084
+ const { oldElement, newElement } = options;
9085
+ let oldElementMode = keepMode(oldElement);
9086
+ if (!oldElementMode) {
9087
+ return;
9088
+ }
9089
+ let partner;
9090
+ let partnerSelector = up.fragment.toTarget(oldElement);
9091
+ const lookupOpts = { layer: options.layer };
9092
+ if (options.descendantsOnly) {
9093
+ partner = up.fragment.get(newElement, partnerSelector, lookupOpts);
9094
+ }
9095
+ else {
9096
+ partner = e.subtreeFirst(newElement, partnerSelector, lookupOpts);
9097
+ }
9098
+ if (!partner)
9099
+ return;
9100
+ let partnerMode = keepMode(partner);
9101
+ if (partnerMode === false)
9102
+ return;
9103
+ let oldIdentity = keepIdentity(oldElement, oldElementMode);
9104
+ let partnerIdentity = keepIdentity(partner, oldElementMode);
9105
+ if (!u.isEqual(oldIdentity, partnerIdentity))
9106
+ return;
9107
+ const plan = {
9108
+ oldElement,
9109
+ newElement: partner,
9110
+ newData: up.script.data(partner),
9111
+ renderOptions: options,
9112
+ };
9113
+ if (emitFragmentKeep(plan).defaultPrevented)
9114
+ return;
9115
+ return plan;
9116
+ }
9117
+ function keepIdentity(element, mode = keepMode(element)) {
9118
+ return element.upKeepIdentity ??= u.copy(buildKeepIdentity(element, mode));
9119
+ }
9120
+ function defaultNormalizeKeepHTML(html) {
9121
+ let tagPattern = /<[^<]+>/g;
9122
+ let attrs = ['up-etag', 'up-source', 'up-time', 'nonce', ...up.script.config.nonceableAttributes];
9123
+ let attrPattern = new RegExp(`\\s+(${attrs.join('|')})="[^"]*"`, 'g');
9124
+ let cleanTag = (match) => match.replace(attrPattern, '');
9125
+ html = html.replace(tagPattern, cleanTag);
9126
+ html = html.replace(/^[ \t]+/mg, '');
9127
+ return html;
9128
+ }
9129
+ function buildKeepIdentity(element, mode) {
9130
+ if (mode === 'same-html') {
9131
+ return config.normalizeKeepHTML(element.outerHTML);
9132
+ }
9133
+ else if (mode === 'same-data') {
9134
+ return up.data(element);
9135
+ }
9136
+ else {
9137
+ return true;
9138
+ }
9139
+ }
9140
+ up.macro('[up-keep]', (element) => keepIdentity(element));
9141
+ function keepMode(element) {
9142
+ return e.booleanOrStringAttr(element, 'up-keep');
9143
+ }
8703
9144
  function emitFragmentInserted(element) {
9145
+ if (element.upInserted)
9146
+ return;
9147
+ element.upInserted = true;
8704
9148
  return up.emit(element, 'up:fragment:inserted', {
8705
9149
  log: ['Inserted fragment %o', element],
8706
9150
  });
8707
9151
  }
8708
- function emitFragmentKeep(keepPlan) {
8709
- let { oldElement, newElement: newFragment, newData, renderOptions } = keepPlan;
8710
- const log = ['Keeping fragment %o', oldElement];
8711
- const callback = e.callbackAttr(oldElement, 'up-on-keep', { exposedKeys: ['newFragment', 'newData'] });
8712
- return up.emit(oldElement, 'up:fragment:keep', { newFragment, newData, renderOptions, log, callback });
8713
- }
8714
9152
  function emitFragmentDestroyed(fragment, options) {
8715
9153
  const log = options.log ?? ['Destroyed fragment %o', fragment];
8716
9154
  const parent = options.parent || document;
@@ -8786,7 +9224,7 @@ up.fragment = (function () {
8786
9224
  }
8787
9225
  function markFragmentAsDestroying(element) {
8788
9226
  element.classList.add('up-destroying');
8789
- element.setAttribute('aria-hidden', 'true');
9227
+ element.setAttribute('inert', '');
8790
9228
  }
8791
9229
  function reload(...args) {
8792
9230
  const options = parseTargetAndOptions(args);
@@ -8843,8 +9281,8 @@ up.fragment = (function () {
8843
9281
  function toTarget(element, options) {
8844
9282
  return u.presence(element, u.isString) || tryToTarget(element, options) || cannotTarget(element);
8845
9283
  }
8846
- function isTargetable(element) {
8847
- return !!tryToTarget(element);
9284
+ function isTargetable(element, options) {
9285
+ return !!tryToTarget(element, options);
8848
9286
  }
8849
9287
  function untargetableMessage(element) {
8850
9288
  return `Cannot derive good target selector from a <${e.tagName(element)}> element without identifying attributes. Try setting an [id] or configure up.fragment.config.targetDerivers.`;
@@ -9064,7 +9502,7 @@ up.fragment = (function () {
9064
9502
  if (steps.length < 2)
9065
9503
  return steps;
9066
9504
  let compressed = u.uniqBy(steps, 'oldElement');
9067
- compressed = u.reject(compressed, step => isContainedByRivalStep(compressed, step));
9505
+ compressed = u.reject(compressed, (step) => isContainedByRivalStep(compressed, step));
9068
9506
  return compressed;
9069
9507
  }
9070
9508
  function abort(...args) {
@@ -9161,10 +9599,15 @@ up.fragment = (function () {
9161
9599
  return () => up.destroy(tempElement);
9162
9600
  }
9163
9601
  }
9602
+ function trackSelector(...args) {
9603
+ let parsedArgs = u.args(args, 'val', 'options', 'callback');
9604
+ let tracker = new up.SelectorTracker(...parsedArgs);
9605
+ return tracker.start();
9606
+ }
9164
9607
  up.on('up:framework:boot', function () {
9165
9608
  const { documentElement } = document;
9166
- documentElement.setAttribute('up-source', normalizeSource(location.href));
9167
9609
  up.hello(documentElement);
9610
+ documentElement.setAttribute('up-source', normalizeSource(location.href));
9168
9611
  if (!up.browser.canPushState()) {
9169
9612
  return up.warn('Cannot push history changes. Next render pass with history will load a full page.');
9170
9613
  }
@@ -9188,6 +9631,8 @@ up.fragment = (function () {
9188
9631
  emitInserted: emitFragmentInserted,
9189
9632
  emitDestroyed: emitFragmentDestroyed,
9190
9633
  emitKeep: emitFragmentKeep,
9634
+ keepPlan: findKeepPlan,
9635
+ defaultNormalizeKeepHTML,
9191
9636
  successKey,
9192
9637
  failKey,
9193
9638
  expandTargets,
@@ -9213,6 +9658,7 @@ up.fragment = (function () {
9213
9658
  insertTemp,
9214
9659
  provideNodes,
9215
9660
  cloneTemplate,
9661
+ trackSelector,
9216
9662
  };
9217
9663
  })();
9218
9664
  up.reload = up.fragment.reload;
@@ -9225,7 +9671,7 @@ u.delegate(up, ['context'], () => up.layer.current);
9225
9671
 
9226
9672
 
9227
9673
  /***/ }),
9228
- /* 87 */
9674
+ /* 90 */
9229
9675
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
9230
9676
 
9231
9677
  "use strict";
@@ -9234,10 +9680,10 @@ __webpack_require__.r(__webpack_exports__);
9234
9680
 
9235
9681
 
9236
9682
  /***/ }),
9237
- /* 88 */
9683
+ /* 91 */
9238
9684
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
9239
9685
 
9240
- __webpack_require__(89);
9686
+ __webpack_require__(92);
9241
9687
  up.viewport = (function () {
9242
9688
  const u = up.util;
9243
9689
  const e = up.element;
@@ -9299,10 +9745,25 @@ up.viewport = (function () {
9299
9745
  doFocus(element, options);
9300
9746
  return element === document.activeElement;
9301
9747
  }
9302
- function revealHash(hash = location.hash, options) {
9303
- let match = firstHashTarget(hash, options);
9748
+ function revealHash(...args) {
9749
+ return revealHashFn(...args)?.();
9750
+ }
9751
+ function revealHashFn(hash, { strong, layer, origin, behavior = 'instant' } = {}) {
9752
+ if (!hash)
9753
+ return;
9754
+ let match = firstHashTarget(hash, { layer, origin });
9304
9755
  if (match) {
9305
- return reveal(match, { top: true });
9756
+ return () => {
9757
+ let doReveal = () => reveal(match, { top: true, behavior });
9758
+ if (strong)
9759
+ u.task(doReveal);
9760
+ return doReveal();
9761
+ };
9762
+ }
9763
+ else if (hash === '#top') {
9764
+ return () => {
9765
+ return scrollTo(0, { behavior });
9766
+ };
9306
9767
  }
9307
9768
  }
9308
9769
  function allSelector() {
@@ -9374,7 +9835,7 @@ up.viewport = (function () {
9374
9835
  const { location } = options.layer;
9375
9836
  const locationScrollTops = options.layer.lastScrollTops.get(location);
9376
9837
  if (locationScrollTops) {
9377
- setScrollTops(viewports, locationScrollTops);
9838
+ setScrollPositions(viewports, locationScrollTops, 0);
9378
9839
  up.puts('up.viewport.restoreScroll()', 'Restored scroll positions to %o', locationScrollTops);
9379
9840
  return true;
9380
9841
  }
@@ -9420,14 +9881,16 @@ up.viewport = (function () {
9420
9881
  }
9421
9882
  return [viewports, options];
9422
9883
  }
9423
- function resetScroll(...args) {
9424
- const [viewports, _options] = parseOptions(args);
9425
- setScrollTops(viewports, {});
9884
+ function scrollTo(position, ...args) {
9885
+ const [viewports, options] = parseOptions(args);
9886
+ setScrollPositions(viewports, {}, position, options.behavior);
9887
+ return true;
9426
9888
  }
9427
- function setScrollTops(viewports, tops) {
9889
+ function setScrollPositions(viewports, tops, defaultTop, behavior = 'instant') {
9428
9890
  for (let viewport of viewports) {
9429
9891
  const key = scrollTopKey(viewport);
9430
- viewport.scrollTop = tops[key] || 0;
9892
+ const top = tops[key] || defaultTop;
9893
+ viewport.scrollTo({ top, behavior });
9431
9894
  }
9432
9895
  }
9433
9896
  function absolutize(element, options = {}) {
@@ -9468,7 +9931,8 @@ up.viewport = (function () {
9468
9931
  };
9469
9932
  }
9470
9933
  function firstHashTarget(hash, options = {}) {
9471
- if (hash = pureHash(hash)) {
9934
+ hash = pureHash(hash);
9935
+ if (hash) {
9472
9936
  const selector = [
9473
9937
  e.idSelector(hash),
9474
9938
  'a' + e.attrSelector('name', hash)
@@ -9496,22 +9960,10 @@ up.viewport = (function () {
9496
9960
  }
9497
9961
  return to;
9498
9962
  }
9499
- document.addEventListener('DOMContentLoaded', function () {
9500
- revealHash();
9501
- u.task(revealHash);
9502
- });
9503
- up.on(window, 'hashchange', () => revealHash());
9504
- up.on('up:click', 'a[href^="#"]', function (event, link) {
9505
- if (link.hash !== location.hash)
9506
- return;
9507
- if (up.link.isFollowable(link))
9508
- return;
9509
- if (revealHash(link.hash))
9510
- up.event.halt(event);
9511
- });
9512
9963
  return {
9513
9964
  reveal,
9514
9965
  revealHash,
9966
+ revealHashFn,
9515
9967
  firstHashTarget,
9516
9968
  config,
9517
9969
  get: closest,
@@ -9524,7 +9976,7 @@ up.viewport = (function () {
9524
9976
  rootScrollbarWidth,
9525
9977
  saveScroll,
9526
9978
  restoreScroll,
9527
- resetScroll,
9979
+ scrollTo,
9528
9980
  saveFocus,
9529
9981
  restoreFocus,
9530
9982
  absolutize,
@@ -9541,7 +9993,7 @@ up.reveal = up.viewport.reveal;
9541
9993
 
9542
9994
 
9543
9995
  /***/ }),
9544
- /* 89 */
9996
+ /* 92 */
9545
9997
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
9546
9998
 
9547
9999
  "use strict";
@@ -9550,27 +10002,22 @@ __webpack_require__.r(__webpack_exports__);
9550
10002
 
9551
10003
 
9552
10004
  /***/ }),
9553
- /* 90 */
10005
+ /* 93 */
9554
10006
  /***/ (() => {
9555
10007
 
9556
10008
  up.motion = (function () {
9557
10009
  const u = up.util;
9558
10010
  const e = up.element;
9559
- let namedAnimations = {};
9560
- let namedTransitions = {};
9561
10011
  const motionController = new up.MotionController('motion');
9562
10012
  const config = new up.Config(() => ({
9563
10013
  duration: 175,
9564
10014
  easing: 'ease',
9565
10015
  enabled: !matchMedia('(prefers-reduced-motion: reduce)').matches
9566
10016
  }));
9567
- function pickDefault(registry) {
9568
- return u.pickBy(registry, 'isDefault');
9569
- }
10017
+ let namedAnimations = new up.Registry('animation', findAnimationFn);
10018
+ let namedTransitions = new up.Registry('transition', findTransitionFn);
9570
10019
  function reset() {
9571
10020
  motionController.reset();
9572
- namedAnimations = pickDefault(namedAnimations);
9573
- namedTransitions = pickDefault(namedTransitions);
9574
10021
  }
9575
10022
  function isEnabled() {
9576
10023
  return config.enabled;
@@ -9601,7 +10048,7 @@ up.motion = (function () {
9601
10048
  }
9602
10049
  function animateNow(element, lastFrame, options) {
9603
10050
  if (up.migrate.loaded)
9604
- lastFrame = up.migrate.fixStyleProps(lastFrame);
10051
+ lastFrame = up.migrate.fixSetStyleProps(lastFrame);
9605
10052
  options = { ...options, finishEvent: motionController.finishEvent };
9606
10053
  const cssTransition = new up.CSSTransition(element, lastFrame, options);
9607
10054
  return cssTransition.start();
@@ -9610,9 +10057,6 @@ up.motion = (function () {
9610
10057
  options.easing ??= config.easing;
9611
10058
  options.duration ??= config.duration;
9612
10059
  }
9613
- function findNamedAnimation(name) {
9614
- return namedAnimations[name] || up.fail("Unknown animation %o", name);
9615
- }
9616
10060
  function finish(element) {
9617
10061
  return motionController.finish(element);
9618
10062
  }
@@ -9663,27 +10107,21 @@ up.motion = (function () {
9663
10107
  return Promise.resolve();
9664
10108
  }
9665
10109
  }
9666
- function findTransitionFn(object) {
9667
- if (isNone(object)) {
10110
+ function findTransitionFn(value) {
10111
+ if (isNone(value)) {
9668
10112
  return undefined;
9669
10113
  }
9670
- else if (u.isFunction(object)) {
9671
- return object;
10114
+ else if (u.isFunction(value)) {
10115
+ return value;
9672
10116
  }
9673
- else if (u.isArray(object)) {
9674
- return composeTransitionFn(...object);
10117
+ else if (u.isArray(value)) {
10118
+ return composeTransitionFn(...value);
9675
10119
  }
9676
- else if (u.isString(object)) {
9677
- let namedTransition;
9678
- if (object.indexOf('/') >= 0) {
9679
- return composeTransitionFn(...object.split('/'));
9680
- }
9681
- else if (namedTransition = namedTransitions[object]) {
9682
- return findTransitionFn(namedTransition);
9683
- }
10120
+ else if (u.isString(value) && value.includes('/')) {
10121
+ return composeTransitionFn(...value.split('/'));
9684
10122
  }
9685
10123
  else {
9686
- up.fail("Unknown transition %o", object);
10124
+ return namedTransitions.get(value);
9687
10125
  }
9688
10126
  }
9689
10127
  function composeTransitionFn(oldAnimation, newAnimation) {
@@ -9696,21 +10134,18 @@ up.motion = (function () {
9696
10134
  ]);
9697
10135
  }
9698
10136
  }
9699
- function findAnimationFn(object) {
9700
- if (isNone(object)) {
10137
+ function findAnimationFn(value) {
10138
+ if (isNone(value)) {
9701
10139
  return undefined;
9702
10140
  }
9703
- else if (u.isFunction(object)) {
9704
- return object;
9705
- }
9706
- else if (u.isString(object)) {
9707
- return findNamedAnimation(object);
10141
+ else if (u.isFunction(value)) {
10142
+ return value;
9708
10143
  }
9709
- else if (u.isOptions(object)) {
9710
- return (element, options) => animateNow(element, object, options);
10144
+ else if (u.isOptions(value)) {
10145
+ return (element, options) => animateNow(element, value, options);
9711
10146
  }
9712
10147
  else {
9713
- up.fail('Unknown animation %o', object);
10148
+ return namedAnimations.get(value);
9714
10149
  }
9715
10150
  }
9716
10151
  const swapElementsDirectly = up.mockable(function (oldElement, newElement) {
@@ -9725,16 +10160,6 @@ up.motion = (function () {
9725
10160
  parser.number('duration');
9726
10161
  return options;
9727
10162
  }
9728
- function registerTransition(name, transition) {
9729
- const fn = findTransitionFn(transition);
9730
- fn.isDefault = up.framework.evaling;
9731
- namedTransitions[name] = fn;
9732
- }
9733
- function registerAnimation(name, animation) {
9734
- const fn = findAnimationFn(animation);
9735
- fn.isDefault = up.framework.evaling;
9736
- namedAnimations[name] = fn;
9737
- }
9738
10163
  up.on('up:framework:boot', function () {
9739
10164
  if (!isEnabled()) {
9740
10165
  up.puts('up.motion', 'Animations are disabled');
@@ -9744,9 +10169,8 @@ up.motion = (function () {
9744
10169
  return !animationOrTransition || animationOrTransition === 'none';
9745
10170
  }
9746
10171
  function registerOpacityAnimation(name, from, to) {
9747
- registerAnimation(name, function (element, options) {
9748
- element.style.opacity = 0;
9749
- e.setStyle(element, { opacity: from });
10172
+ namedAnimations.put(name, function (element, options) {
10173
+ element.style.opacity = from;
9750
10174
  return animateNow(element, { opacity: to }, options);
9751
10175
  });
9752
10176
  }
@@ -9765,12 +10189,12 @@ up.motion = (function () {
9765
10189
  function registerMoveAnimations(direction, boxToTransform) {
9766
10190
  const animationToName = `move-to-${direction}`;
9767
10191
  const animationFromName = `move-from-${direction}`;
9768
- registerAnimation(animationToName, function (element, options) {
10192
+ namedAnimations.put(animationToName, function (element, options) {
9769
10193
  const box = untranslatedBox(element);
9770
10194
  const transform = boxToTransform(box);
9771
10195
  return animateNow(element, transform, options);
9772
10196
  });
9773
- registerAnimation(animationFromName, function (element, options) {
10197
+ namedAnimations.put(animationFromName, function (element, options) {
9774
10198
  const box = untranslatedBox(element);
9775
10199
  const transform = boxToTransform(box);
9776
10200
  e.setStyle(element, transform);
@@ -9793,19 +10217,19 @@ up.motion = (function () {
9793
10217
  const travelDistance = up.viewport.rootWidth() - box.left;
9794
10218
  return translateCSS(travelDistance, 0);
9795
10219
  });
9796
- registerTransition('cross-fade', ['fade-out', 'fade-in']);
9797
- registerTransition('move-left', ['move-to-left', 'move-from-right']);
9798
- registerTransition('move-right', ['move-to-right', 'move-from-left']);
9799
- registerTransition('move-up', ['move-to-top', 'move-from-bottom']);
9800
- registerTransition('move-down', ['move-to-bottom', 'move-from-top']);
10220
+ namedTransitions.put('cross-fade', ['fade-out', 'fade-in']);
10221
+ namedTransitions.put('move-left', ['move-to-left', 'move-from-right']);
10222
+ namedTransitions.put('move-right', ['move-to-right', 'move-from-left']);
10223
+ namedTransitions.put('move-up', ['move-to-top', 'move-from-bottom']);
10224
+ namedTransitions.put('move-down', ['move-to-bottom', 'move-from-top']);
9801
10225
  up.on('up:framework:reset', reset);
9802
10226
  return {
9803
10227
  morph,
9804
10228
  animate,
9805
10229
  finish,
9806
10230
  finishCount() { return motionController.finishCount; },
9807
- transition: registerTransition,
9808
- animation: registerAnimation,
10231
+ transition: namedTransitions.put,
10232
+ animation: namedAnimations.put,
9809
10233
  config,
9810
10234
  isEnabled,
9811
10235
  isNone,
@@ -9821,10 +10245,10 @@ up.animate = up.motion.animate;
9821
10245
 
9822
10246
 
9823
10247
  /***/ }),
9824
- /* 91 */
10248
+ /* 94 */
9825
10249
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
9826
10250
 
9827
- __webpack_require__(92);
10251
+ __webpack_require__(95);
9828
10252
  const u = up.util;
9829
10253
  up.network = (function () {
9830
10254
  const config = new up.Config(() => ({
@@ -9836,7 +10260,7 @@ up.network = (function () {
9836
10260
  lateDelay: 400,
9837
10261
  fail(response) { return (response.status < 200 || response.status > 299) && response.status !== 304; },
9838
10262
  autoCache(request) { return request.isSafe(); },
9839
- expireCache(request, _response) { return !request.isSafe(); },
10263
+ expireCache(request) { return !request.isSafe(); },
9840
10264
  evictCache: false,
9841
10265
  progressBar: true,
9842
10266
  timeout: 90000,
@@ -9863,6 +10287,8 @@ up.network = (function () {
9863
10287
  return options;
9864
10288
  }
9865
10289
  function processRequest(request) {
10290
+ cache.expire(request.expireCache ?? u.evalOption(config.expireCache, request) ?? false);
10291
+ cache.evict(request.evictCache ?? u.evalOption(config.evictCache, request) ?? false);
9866
10292
  useCachedRequest(request) || queueRequest(request);
9867
10293
  }
9868
10294
  function useCachedRequest(newRequest) {
@@ -9888,28 +10314,27 @@ up.network = (function () {
9888
10314
  request.onLoading = () => cache.reindex(request);
9889
10315
  }
9890
10316
  u.always(request, function (responseOrError) {
9891
- let expireCache = responseOrError.expireCache ?? request.expireCache ?? u.evalOption(config.expireCache, request, responseOrError);
9892
- if (expireCache) {
9893
- cache.expire(expireCache, { except: request });
9894
- }
9895
- let evictCache = responseOrError.evictCache ?? request.evictCache ?? u.evalOption(config.evictCache, request, responseOrError);
9896
- if (evictCache) {
9897
- cache.evict(evictCache, { except: request });
9898
- }
9899
- let hasCacheEntry = cache.get(request);
10317
+ cache.expire(responseOrError.expireCache ?? false, { except: request });
10318
+ cache.evict(responseOrError.evictCache ?? false, { except: request });
9900
10319
  let isResponse = responseOrError instanceof up.Response;
9901
10320
  let isNetworkError = !isResponse;
9902
10321
  let isSuccessResponse = isResponse && responseOrError.ok;
9903
10322
  let isErrorResponse = isResponse && !responseOrError.ok;
9904
10323
  let isEmptyResponse = isResponse && responseOrError.none;
10324
+ let redirectRequest = isResponse && responseOrError.redirectRequest;
9905
10325
  if (isErrorResponse) {
9906
10326
  cache.evict(request.url);
9907
10327
  }
9908
10328
  else if (isNetworkError || isEmptyResponse) {
9909
10329
  cache.evict(request);
9910
10330
  }
9911
- else if (isSuccessResponse && hasCacheEntry) {
9912
- cache.put(request);
10331
+ else if (isSuccessResponse) {
10332
+ if (cache.get(request)) {
10333
+ cache.put(request);
10334
+ }
10335
+ if (redirectRequest && (redirectRequest.willCache() || cache.get(redirectRequest))) {
10336
+ cache.put(redirectRequest);
10337
+ }
9913
10338
  }
9914
10339
  });
9915
10340
  }
@@ -9923,16 +10348,6 @@ up.network = (function () {
9923
10348
  up.migrate.preprocessAbortArgs?.(args);
9924
10349
  queue.abort(...args);
9925
10350
  }
9926
- function registerAliasForRedirect(request, response) {
9927
- if (request.cache && response.url && request.url !== response.url) {
9928
- const newRequest = u.variant(request, {
9929
- method: response.method,
9930
- url: response.url,
9931
- cacheRoute: null,
9932
- });
9933
- cache.alias(request, newRequest);
9934
- }
9935
- }
9936
10351
  function isSafeMethod(method) {
9937
10352
  return u.contains(['GET', 'OPTIONS', 'HEAD'], u.normalizeMethod(method));
9938
10353
  }
@@ -9954,7 +10369,6 @@ up.network = (function () {
9954
10369
  isSafeMethod,
9955
10370
  config,
9956
10371
  abort: abortRequests,
9957
- registerAliasForRedirect,
9958
10372
  queue,
9959
10373
  loadPage,
9960
10374
  };
@@ -9964,7 +10378,7 @@ up.cache = up.network.cache;
9964
10378
 
9965
10379
 
9966
10380
  /***/ }),
9967
- /* 92 */
10381
+ /* 95 */
9968
10382
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
9969
10383
 
9970
10384
  "use strict";
@@ -9973,10 +10387,10 @@ __webpack_require__.r(__webpack_exports__);
9973
10387
 
9974
10388
 
9975
10389
  /***/ }),
9976
- /* 93 */
10390
+ /* 96 */
9977
10391
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
9978
10392
 
9979
- __webpack_require__(94);
10393
+ __webpack_require__(97);
9980
10394
  const u = up.util;
9981
10395
  const e = up.element;
9982
10396
  up.layer = (function () {
@@ -10151,7 +10565,7 @@ up.layer = (function () {
10151
10565
  });
10152
10566
  }
10153
10567
  function anySelector() {
10154
- return u.map(LAYER_CLASSES, Class => Class.selector()).join();
10568
+ return u.map(LAYER_CLASSES, (Class) => Class.selector()).join();
10155
10569
  }
10156
10570
  function optionToString(option) {
10157
10571
  if (u.isString(option)) {
@@ -10221,7 +10635,7 @@ up.layer = (function () {
10221
10635
 
10222
10636
 
10223
10637
  /***/ }),
10224
- /* 94 */
10638
+ /* 97 */
10225
10639
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
10226
10640
 
10227
10641
  "use strict";
@@ -10230,14 +10644,16 @@ __webpack_require__.r(__webpack_exports__);
10230
10644
 
10231
10645
 
10232
10646
  /***/ }),
10233
- /* 95 */
10647
+ /* 98 */
10234
10648
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
10235
10649
 
10236
- __webpack_require__(96);
10650
+ __webpack_require__(99);
10237
10651
  up.link = (function () {
10238
10652
  const u = up.util;
10239
10653
  const e = up.element;
10654
+ let lastTouchstartTarget = null;
10240
10655
  let lastMousedownTarget = null;
10656
+ let lastInstantTarget = null;
10241
10657
  const ATTRS_WITH_LOCAL_HTML = '[up-content], [up-fragment], [up-document]';
10242
10658
  const ATTRS_SUGGESTING_FOLLOW = `${ATTRS_WITH_LOCAL_HTML}, [up-target], [up-layer], [up-transition], [up-preload]`;
10243
10659
  const DEFAULT_INTERACTIVE_ELEMENT = 'a[href], button';
@@ -10267,7 +10683,9 @@ up.link = (function () {
10267
10683
  }
10268
10684
  }
10269
10685
  function reset() {
10686
+ lastTouchstartTarget = null;
10270
10687
  lastMousedownTarget = null;
10688
+ lastInstantTarget = null;
10271
10689
  }
10272
10690
  const follow = up.mockable(function (link, options, parserOptions) {
10273
10691
  return up.render(followOptions(link, options, parserOptions));
@@ -10289,6 +10707,7 @@ up.link = (function () {
10289
10707
  parser.string('contentType');
10290
10708
  parser.booleanOrNumber('lateDelay');
10291
10709
  parser.number('timeout');
10710
+ parser.booleanOrString('fail');
10292
10711
  return options;
10293
10712
  }
10294
10713
  function followOptions(link, options, parserOptions) {
@@ -10297,7 +10716,6 @@ up.link = (function () {
10297
10716
  const parser = new up.OptionsParser(link, options, { fail: true, ...parserOptions });
10298
10717
  parser.include(parseRequestOptions);
10299
10718
  options.origin ||= link;
10300
- parser.boolean('fail');
10301
10719
  parser.boolean('navigate', { default: true });
10302
10720
  parser.string('confirm', { attr: ['up-confirm', 'data-confirm'] });
10303
10721
  parser.string('target');
@@ -10331,9 +10749,12 @@ up.link = (function () {
10331
10749
  parser.string('dismissEvent');
10332
10750
  parser.string('acceptLocation');
10333
10751
  parser.string('dismissLocation');
10334
- parser.booleanOrString('history');
10752
+ parser.booleanOrString('closeAnimation');
10753
+ parser.string('closeEasing');
10754
+ parser.number('closeDuration');
10335
10755
  parser.include(up.status.statusOptions);
10336
10756
  parser.booleanOrString('focus');
10757
+ parser.booleanOrString('focusVisible');
10337
10758
  parser.boolean('saveScroll');
10338
10759
  parser.boolean('saveFocus');
10339
10760
  parser.booleanOrString('scroll');
@@ -10363,9 +10784,9 @@ up.link = (function () {
10363
10784
  abortable: false,
10364
10785
  background: true,
10365
10786
  cache: true,
10787
+ ...options,
10366
10788
  ...up.RenderOptions.NO_INPUT_INTERFERENCE,
10367
10789
  ...up.RenderOptions.NO_PREVIEWS,
10368
- ...options,
10369
10790
  guardEvent,
10370
10791
  preload: true,
10371
10792
  });
@@ -10424,27 +10845,37 @@ up.link = (function () {
10424
10845
  }
10425
10846
  function convertClicks(layer) {
10426
10847
  layer.on('click', function (event, element) {
10427
- if (!up.event.isUnmodified(event)) {
10848
+ if (up.event.isModified(event)) {
10428
10849
  return;
10429
10850
  }
10430
- if (isInstant(element) && lastMousedownTarget) {
10851
+ if (isInstant(element) && lastInstantTarget === element) {
10431
10852
  up.event.halt(event);
10432
10853
  }
10433
10854
  else if (up.event.inputDevice === 'key' || up.event.isSyntheticClick(event) || (layer.wasHitByMouseEvent(event) && !didUserDragAway(event))) {
10434
10855
  forkEventAsUpClick(event);
10435
10856
  }
10436
- return lastMousedownTarget = null;
10857
+ lastMousedownTarget = null;
10858
+ lastInstantTarget = null;
10859
+ });
10860
+ layer.on('touchstart', { passive: true }, function (event, element) {
10861
+ lastTouchstartTarget = element;
10437
10862
  });
10438
10863
  layer.on('mousedown', function (event, element) {
10439
- if (!up.event.isUnmodified(event)) {
10864
+ if (up.event.isModified(event)) {
10440
10865
  return;
10441
10866
  }
10442
- lastMousedownTarget = event.target;
10443
- if (isInstant(element)) {
10867
+ lastMousedownTarget = element;
10868
+ if (isInstant(element) && !isLongPressPossible(event)) {
10869
+ lastInstantTarget = element;
10444
10870
  forkEventAsUpClick(event);
10445
10871
  }
10872
+ lastTouchstartTarget = null;
10446
10873
  });
10447
10874
  }
10875
+ function isLongPressPossible(mousedownEvent) {
10876
+ let mousedownTarget = mousedownEvent.target;
10877
+ return (lastTouchstartTarget === mousedownTarget) && mousedownTarget.closest('[href]');
10878
+ }
10448
10879
  function didUserDragAway(clickEvent) {
10449
10880
  return lastMousedownTarget && (lastMousedownTarget !== clickEvent.target);
10450
10881
  }
@@ -10540,7 +10971,7 @@ up.deferred = { load: up.link.loadDeferred };
10540
10971
 
10541
10972
 
10542
10973
  /***/ }),
10543
- /* 96 */
10974
+ /* 99 */
10544
10975
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
10545
10976
 
10546
10977
  "use strict";
@@ -10549,7 +10980,7 @@ __webpack_require__.r(__webpack_exports__);
10549
10980
 
10550
10981
 
10551
10982
  /***/ }),
10552
- /* 97 */
10983
+ /* 100 */
10553
10984
  /***/ (() => {
10554
10985
 
10555
10986
  up.form = (function () {
@@ -10562,12 +10993,15 @@ up.form = (function () {
10562
10993
  noSubmitSelectors: ['[up-submit=false]', '[target]', e.crossOriginSelector('action')],
10563
10994
  submitButtonSelectors: ['input[type=submit]', 'input[type=image]', 'button[type=submit]', 'button:not([type])'],
10564
10995
  genericButtonSelectors: ['input[type=button]', 'button[type=button]'],
10996
+ validateBatch: true,
10565
10997
  watchInputEvents: ['input', 'change'],
10566
10998
  watchInputDelay: 0,
10567
10999
  watchChangeEvents: ['change'],
11000
+ watchableEvents: ['input', 'change'],
11001
+ arrayParam: (name) => name.endsWith('[]'),
10568
11002
  }));
10569
11003
  function fieldSelector(suffix = '') {
10570
- return config.fieldSelectors.map(field => field + suffix).join();
11004
+ return config.fieldSelectors.map((field) => field + suffix).join();
10571
11005
  }
10572
11006
  function isField(element) {
10573
11007
  return element.matches(fieldSelector());
@@ -10578,11 +11012,17 @@ up.form = (function () {
10578
11012
  if (root.matches('form[id]')) {
10579
11013
  const outsideFieldSelector = fieldSelector(e.attrSelector('form', root.getAttribute('id')));
10580
11014
  const outsideFields = up.fragment.all(outsideFieldSelector, { layer: root });
10581
- fields.push(...outsideFields);
10582
- fields = u.uniq(fields);
11015
+ fields = u.uniq([...fields, ...outsideFields]);
10583
11016
  }
10584
11017
  return fields;
10585
11018
  }
11019
+ function findFieldsAndButtons(container) {
11020
+ return [
11021
+ ...findFields(container),
11022
+ ...findSubmitButtons(container),
11023
+ ...findGenericButtons(container),
11024
+ ];
11025
+ }
10586
11026
  function findSubmitButtons(root) {
10587
11027
  return e.subtree(root, submitButtonSelector());
10588
11028
  }
@@ -10617,8 +11057,10 @@ up.form = (function () {
10617
11057
  }
10618
11058
  function watchOptions(field, options, parserOptions = {}) {
10619
11059
  options = u.options(options);
10620
- let parser = new up.OptionsParser(field, options, { ...parserOptions, closest: true, attrPrefix: 'up-watch-' });
10621
- parser.include(up.status.statusOptions);
11060
+ parserOptions.closest ??= true;
11061
+ parserOptions.attrPrefix ??= 'up-watch-';
11062
+ let parser = new up.OptionsParser(field, options, parserOptions);
11063
+ parser.include(up.status.statusOptions, parserOptions);
10622
11064
  parser.string('event');
10623
11065
  parser.number('delay');
10624
11066
  let config = up.form.config;
@@ -10632,15 +11074,22 @@ up.form = (function () {
10632
11074
  options.origin ||= field;
10633
11075
  return options;
10634
11076
  }
10635
- function disableContainer(container) {
10636
- let controls = [
10637
- ...findFields(container),
10638
- ...findSubmitButtons(container),
10639
- ...findGenericButtons(container),
10640
- ];
10641
- return u.sequence(u.map(controls, disableControl));
11077
+ function validateOptions(field, options, parserOptions = {}) {
11078
+ options = u.options(options);
11079
+ let parser = new up.OptionsParser(field, options, { ...parserOptions, closest: true, attrPrefix: 'up-validate-' });
11080
+ parser.string('url');
11081
+ parser.string('method', { normalize: u.normalizeMethod });
11082
+ parser.boolean('batch', { default: config.validateBatch });
11083
+ parser.json('params');
11084
+ parser.json('headers');
11085
+ parser.include(watchOptions, { defaults: { event: 'change' } });
11086
+ return options;
10642
11087
  }
10643
- function disableControl(control) {
11088
+ function disableContainerTemp(container) {
11089
+ let controls = findFieldsAndButtons(container);
11090
+ return u.sequence(u.map(controls, disableControlTemp));
11091
+ }
11092
+ function disableControlTemp(control) {
10644
11093
  if (control.disabled)
10645
11094
  return;
10646
11095
  let focusFallback;
@@ -10655,7 +11104,7 @@ up.form = (function () {
10655
11104
  return () => { control.disabled = false; };
10656
11105
  }
10657
11106
  function getDisableContainers(disable, origin) {
10658
- let originScope = () => getScope(origin);
11107
+ let originScope = () => getRegion(origin);
10659
11108
  if (disable === true) {
10660
11109
  return [originScope()];
10661
11110
  }
@@ -10680,6 +11129,11 @@ up.form = (function () {
10680
11129
  }
10681
11130
  };
10682
11131
  }
11132
+ function setContainerDisabled(container, disabled) {
11133
+ for (let control of findFieldsAndButtons(container)) {
11134
+ control.disabled = disabled;
11135
+ }
11136
+ }
10683
11137
  function destinationOptions(form, options, parserOptions) {
10684
11138
  options = u.options(options);
10685
11139
  form = getForm(form);
@@ -10693,8 +11147,7 @@ up.form = (function () {
10693
11147
  options.method ||= submitButton.getAttribute('formmethod');
10694
11148
  options.url ||= submitButton.getAttribute('formaction');
10695
11149
  }
10696
- params.addAll(options.params);
10697
- options.params = params;
11150
+ options.params = up.Params.merge(params, options.params);
10698
11151
  parser.string('url', { attr: 'action', default: up.fragment.source(form) });
10699
11152
  parser.string('method', {
10700
11153
  attr: ['up-method', 'data-method', 'method'],
@@ -10711,8 +11164,7 @@ up.form = (function () {
10711
11164
  root = up.element.get(root);
10712
11165
  callback ||= watchCallbackFromElement(root) || up.fail('No callback given for up.watch()');
10713
11166
  const watcher = new up.FieldWatcher(root, options, callback);
10714
- watcher.start();
10715
- return () => watcher.stop();
11167
+ return watcher.start();
10716
11168
  }
10717
11169
  function watchCallbackFromElement(element) {
10718
11170
  let rawCallback = element.getAttribute('up-watch');
@@ -10722,7 +11174,7 @@ up.form = (function () {
10722
11174
  }
10723
11175
  function autosubmit(target, options = {}) {
10724
11176
  const onChange = (_diff, renderOptions) => submit(target, renderOptions);
10725
- return watch(target, { ...options, batch: true }, onChange);
11177
+ return watch(target, { logPrefix: 'up.autosubmit()', ...options, batch: true }, onChange);
10726
11178
  }
10727
11179
  function getGroupSelectors() {
10728
11180
  return up.migrate.migratedFormGroupSelectors?.() || config.groupSelectors;
@@ -10750,7 +11202,8 @@ up.form = (function () {
10750
11202
  }
10751
11203
  function validate(...args) {
10752
11204
  let options = parseValidateArgs(...args);
10753
- let validator = up.FormValidator.forElement(options.origin);
11205
+ let form = getForm(options.origin);
11206
+ let validator = getFormValidator(form);
10754
11207
  return validator.validate(options);
10755
11208
  }
10756
11209
  function parseValidateArgs(originOrTarget, ...args) {
@@ -10763,88 +11216,20 @@ up.form = (function () {
10763
11216
  }
10764
11217
  return options;
10765
11218
  }
10766
- function switcherValues(field) {
10767
- let value;
10768
- let meta;
10769
- if (field.matches('input[type=checkbox]')) {
10770
- if (field.checked) {
10771
- value = field.value;
10772
- meta = ':checked';
10773
- }
10774
- else {
10775
- meta = ':unchecked';
10776
- }
10777
- }
10778
- else if (field.matches('input[type=radio]')) {
10779
- const form = getScope(field);
10780
- const groupName = field.getAttribute('name');
10781
- const checkedButton = form.querySelector(`input[type=radio]${e.attrSelector('name', groupName)}:checked`);
10782
- if (checkedButton) {
10783
- meta = ':checked';
10784
- value = checkedButton.value;
10785
- }
10786
- else {
10787
- meta = ':unchecked';
10788
- }
10789
- }
10790
- else {
10791
- value = field.value;
10792
- }
10793
- const values = [];
10794
- if (u.isPresent(value)) {
10795
- values.push(value);
10796
- values.push(':present');
10797
- }
10798
- else {
10799
- values.push(':blank');
10800
- }
10801
- if (u.isPresent(meta)) {
10802
- values.push(meta);
10803
- }
10804
- return values;
10805
- }
10806
- function switchTargets(switcher, options = {}) {
10807
- const targetSelector = options.target || options.target || switcher.getAttribute('up-switch');
10808
- const form = getScope(switcher);
10809
- targetSelector || up.fail("No switch target given for %o", switcher);
10810
- const fieldValues = switcherValues(switcher);
10811
- for (let target of up.fragment.all(form, targetSelector)) {
10812
- switchTarget(target, fieldValues);
10813
- }
10814
- }
10815
- const switchTarget = up.mockable(function (target, fieldValues) {
10816
- let show;
10817
- fieldValues ||= switcherValues(findSwitcherForTarget(target));
10818
- let hideValues = target.getAttribute('up-hide-for');
10819
- if (hideValues) {
10820
- hideValues = parseSwitchTokens(hideValues);
10821
- show = u.intersect(fieldValues, hideValues).length === 0;
10822
- }
10823
- else {
10824
- let showValues = target.getAttribute('up-show-for');
10825
- showValues = showValues ? parseSwitchTokens(showValues) : [':present', ':checked'];
10826
- show = u.intersect(fieldValues, showValues).length > 0;
10827
- }
10828
- e.toggle(target, show);
10829
- target.classList.add('up-switched');
10830
- });
10831
- function parseSwitchTokens(str) {
10832
- return u.getSimpleTokens(str, { json: true });
10833
- }
10834
- function findSwitcherForTarget(target) {
10835
- const form = getScope(target);
10836
- const switchers = form.querySelectorAll('[up-switch]');
10837
- const switcher = u.find(switchers, function (switcher) {
10838
- const targetSelector = switcher.getAttribute('up-switch');
10839
- return target.matches(targetSelector);
10840
- });
10841
- return switcher || up.fail('Could not find [up-switch] field for %o', target);
10842
- }
10843
11219
  function getForm(elementOrSelector, options = {}) {
10844
11220
  const element = up.fragment.get(elementOrSelector, options);
10845
11221
  return element.form || element.closest('form');
10846
11222
  }
10847
- function getScope(origin, options) {
11223
+ function getFormValidator(form) {
11224
+ return form.upFormValidator ||= setupFormValidator(form);
11225
+ }
11226
+ function setupFormValidator(form) {
11227
+ const validator = new up.FormValidator(form);
11228
+ const stop = validator.start();
11229
+ up.destructor(form, stop);
11230
+ return validator;
11231
+ }
11232
+ function getRegion(origin, options) {
10848
11233
  if (origin) {
10849
11234
  return getForm(origin, options) || up.layer.get(origin).element;
10850
11235
  }
@@ -10852,6 +11237,19 @@ up.form = (function () {
10852
11237
  return up.layer.current.element;
10853
11238
  }
10854
11239
  }
11240
+ function trackFields(...args) {
11241
+ let [root, { guard }, callback] = u.args(args, 'val', 'options', 'callback');
11242
+ let filter = function (fields) {
11243
+ let region = getRegion(root);
11244
+ return u.filter(fields, function (field) {
11245
+ return (root === region || root.contains(field))
11246
+ && (getRegion(field) === region)
11247
+ && (!guard || guard(field));
11248
+ });
11249
+ };
11250
+ const live = true;
11251
+ return up.fragment.trackSelector(fieldSelector(), { filter, live }, callback);
11252
+ }
10855
11253
  function focusedField() {
10856
11254
  return u.presence(document.activeElement, isField);
10857
11255
  }
@@ -10866,49 +11264,39 @@ up.form = (function () {
10866
11264
  up.event.halt(event, { log: true });
10867
11265
  up.error.muteUncriticalRejection(submit(form, { submitButton }));
10868
11266
  });
10869
- up.compiler(validatingFieldSelector, function (fieldOrForm) {
10870
- let validator = up.FormValidator.forElement(fieldOrForm);
10871
- validator.watchContainer(fieldOrForm);
11267
+ up.compiler('form', function (form) {
11268
+ getFormValidator(form);
10872
11269
  });
10873
- function validatingFieldSelector() {
10874
- let includes = config.fieldSelectors.map((selector) => `${selector}[up-validate], [up-validate] ${selector}`);
10875
- let excludes = ['[up-validate=false]'];
10876
- return e.unionSelector(includes, excludes);
10877
- }
10878
11270
  up.compiler('[up-switch]', (switcher) => {
10879
- switchTargets(switcher);
10880
- });
10881
- up.on('change', '[up-switch]', (_event, switcher) => {
10882
- switchTargets(switcher);
10883
- });
10884
- up.compiler('[up-show-for]:not(.up-switched), [up-hide-for]:not(.up-switched)', (element) => {
10885
- switchTarget(element);
11271
+ return new up.Switcher(switcher).start();
10886
11272
  });
10887
11273
  up.attribute('up-watch', (formOrField) => watch(formOrField));
10888
- up.attribute('up-autosubmit', (formOrField) => autosubmit(formOrField));
11274
+ up.attribute('up-autosubmit', (formOrField) => autosubmit(formOrField, { logPrefix: '[up-autosubmit]' }));
10889
11275
  return {
10890
11276
  config,
10891
11277
  submit,
10892
11278
  submitOptions,
10893
11279
  destinationOptions,
10894
11280
  watchOptions,
11281
+ validateOptions,
10895
11282
  isSubmittable,
10896
11283
  watch,
10897
11284
  validate,
10898
11285
  autosubmit,
10899
11286
  fieldSelector,
10900
11287
  fields: findFields,
11288
+ trackFields,
10901
11289
  isField,
10902
11290
  submitButtons: findSubmitButtons,
10903
11291
  focusedField,
10904
- switchTarget,
10905
- disable: disableContainer,
11292
+ disableTemp: disableContainerTemp,
11293
+ setDisabled: setContainerDisabled,
10906
11294
  getDisablePreviewFn,
10907
11295
  group: findGroup,
10908
11296
  groupSolution: findGroupSolution,
10909
11297
  groupSelectors: getGroupSelectors,
10910
11298
  get: getForm,
10911
- getScope,
11299
+ getRegion,
10912
11300
  };
10913
11301
  })();
10914
11302
  up.submit = up.form.submit;
@@ -10918,13 +11306,12 @@ up.validate = up.form.validate;
10918
11306
 
10919
11307
 
10920
11308
  /***/ }),
10921
- /* 98 */
11309
+ /* 101 */
10922
11310
  /***/ (() => {
10923
11311
 
10924
11312
  up.status = (function () {
10925
11313
  const u = up.util;
10926
11314
  const e = up.element;
10927
- let namedPreviewFns = {};
10928
11315
  const config = new up.Config(() => ({
10929
11316
  currentClasses: ['up-current'],
10930
11317
  activeClasses: ['up-active'],
@@ -10932,30 +11319,39 @@ up.status = (function () {
10932
11319
  navSelectors: ['[up-nav]', 'nav'],
10933
11320
  noNavSelectors: ['[up-nav=false]'],
10934
11321
  }));
10935
- function reset() {
10936
- up.layer.root.feedbackLocation = null;
10937
- namedPreviewFns = u.pickBy(namedPreviewFns, 'isDefault');
10938
- }
11322
+ let namedPreviewFns = new up.Registry('preview');
10939
11323
  const SELECTOR_LINK = 'a, [up-href]';
10940
11324
  function linkCurrentURLs(link) {
10941
11325
  return link.upCurrentURLs ||= new up.LinkCurrentURLs(link);
10942
11326
  }
10943
- function updateFragment(fragment, { layer } = {}) {
10944
- layer ||= up.layer.get(fragment);
10945
- let layerLocation = getMatchableLayerLocation(layer);
10946
- const navSelector = config.selector('navSelectors');
10947
- const navLinkSelector = `${navSelector} :is(${SELECTOR_LINK}), ${navSelector}:is(${SELECTOR_LINK})`;
10948
- const links = up.fragment.all(navLinkSelector, { layer });
10949
- for (let link of links) {
10950
- const isCurrent = linkCurrentURLs(link).isCurrent(layerLocation);
10951
- for (let currentClass of config.currentClasses) {
10952
- link.classList.toggle(currentClass, isCurrent);
11327
+ function getNavLocations(nav) {
11328
+ let layerRef = e.attr(nav, 'up-layer') || 'origin';
11329
+ let layers = up.layer.getAll(layerRef, { origin: nav });
11330
+ return u.compact(layers.map(getMatchableLayerLocation));
11331
+ }
11332
+ function updateNav(nav, links, { newLinks, anyLocationChanged }) {
11333
+ let currentLocations = (!anyLocationChanged && nav.upNavLocations) || getNavLocations(nav);
11334
+ if (newLinks || !u.isEqual(nav.upNavLocations, currentLocations)) {
11335
+ for (let link of links) {
11336
+ const isCurrent = linkCurrentURLs(link).isAnyCurrent(currentLocations);
11337
+ for (let currentClass of config.currentClasses) {
11338
+ link.classList.toggle(currentClass, isCurrent);
11339
+ }
11340
+ e.setAttrPresence(link, 'aria-current', 'page', isCurrent);
10953
11341
  }
10954
- e.setAttrPresence(link, 'aria-current', 'page', isCurrent);
11342
+ nav.upNavLocations = currentLocations;
11343
+ }
11344
+ }
11345
+ function updateNavsAround(root, opts) {
11346
+ const navSelector = config.selector('navSelectors');
11347
+ const fullNavs = e.around(root, navSelector);
11348
+ for (let fullNav of fullNavs) {
11349
+ let links = e.subtree(fullNav, SELECTOR_LINK);
11350
+ updateNav(fullNav, links, opts);
10955
11351
  }
10956
11352
  }
10957
11353
  function getMatchableLayerLocation(layer) {
10958
- return layer.feedbackLocation || u.matchableURL(layer.location);
11354
+ return u.matchableURL(layer.location);
10959
11355
  }
10960
11356
  function findActivatableArea(element) {
10961
11357
  return e.ancestor(element, SELECTOR_LINK) || element;
@@ -11010,7 +11406,7 @@ up.status = (function () {
11010
11406
  }
11011
11407
  function resolvePreviewString(str) {
11012
11408
  return u.map(u.parseScalarJSONPairs(str), ([name, parsedOptions]) => {
11013
- let previewFn = namedPreviewFns[name] || up.fail('Unknown preview "%s"', name);
11409
+ let previewFn = namedPreviewFns.get(name);
11014
11410
  return function (preview, runOptions) {
11015
11411
  up.puts('[up-preview]', 'Showing preview %o', name);
11016
11412
  return previewFn(preview, parsedOptions || runOptions);
@@ -11021,10 +11417,6 @@ up.status = (function () {
11021
11417
  activeElements ||= u.wrapList(origin);
11022
11418
  return activeElements.map(findActivatableArea);
11023
11419
  }
11024
- function registerPreview(name, previewFn) {
11025
- previewFn.isDefault = up.framework.evaling;
11026
- namedPreviewFns[name] = previewFn;
11027
- }
11028
11420
  function getFeedbackClassesPreviewFn(feedbackOption, fragments) {
11029
11421
  if (!feedbackOption)
11030
11422
  return;
@@ -11043,33 +11435,15 @@ up.status = (function () {
11043
11435
  parser.string('placeholder');
11044
11436
  return options;
11045
11437
  }
11046
- function updateLayerIfLocationChanged(layer) {
11047
- const processedLocation = layer.feedbackLocation;
11048
- const layerLocation = getMatchableLayerLocation(layer.location);
11049
- if (!processedLocation || (processedLocation !== layerLocation)) {
11050
- layer.feedbackLocation = layerLocation;
11051
- updateFragment(layer.element, { layer });
11052
- }
11053
- }
11054
- function onBrowserLocationChanged() {
11055
- const frontLayer = up.layer.front;
11056
- if (frontLayer.showsLiveHistory()) {
11057
- updateLayerIfLocationChanged(frontLayer);
11058
- }
11059
- }
11060
- up.on('up:location:changed', (_event) => {
11061
- onBrowserLocationChanged();
11062
- });
11063
11438
  up.on('up:fragment:compile', (_event, newFragment) => {
11064
- updateFragment(newFragment);
11439
+ updateNavsAround(newFragment, { newLinks: true, anyLocationChanged: false });
11065
11440
  });
11066
- up.on('up:layer:location:changed', (event) => {
11067
- updateLayerIfLocationChanged(event.layer);
11441
+ up.on('up:layer:location:changed up:layer:opened up:layer:dismissed up:layer:accepted', () => {
11442
+ updateNavsAround(document.body, { newLinks: false, anyLocationChanged: true });
11068
11443
  });
11069
- up.on('up:framework:reset', reset);
11070
11444
  return {
11071
11445
  config,
11072
- preview: registerPreview,
11446
+ preview: namedPreviewFns.put,
11073
11447
  resolvePreviewFns,
11074
11448
  runPreviews,
11075
11449
  statusOptions,
@@ -11079,7 +11453,7 @@ up.preview = up.status.preview;
11079
11453
 
11080
11454
 
11081
11455
  /***/ }),
11082
- /* 99 */
11456
+ /* 102 */
11083
11457
  /***/ (() => {
11084
11458
 
11085
11459
  up.radio = (function () {
@@ -11173,7 +11547,7 @@ up.radio = (function () {
11173
11547
 
11174
11548
 
11175
11549
  /***/ }),
11176
- /* 100 */
11550
+ /* 103 */
11177
11551
  /***/ (() => {
11178
11552
 
11179
11553
  (function () {
@@ -11236,7 +11610,7 @@ up.radio = (function () {
11236
11610
  /******/
11237
11611
  /************************************************************************/
11238
11612
  var __webpack_exports__ = {};
11239
- // This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
11613
+ // This entry needs to be wrapped in an IIFE because it needs to be isolated against other modules in the chunk.
11240
11614
  (() => {
11241
11615
  __webpack_require__(1);
11242
11616
  __webpack_require__(2);
@@ -11323,15 +11697,18 @@ __webpack_require__(83);
11323
11697
  __webpack_require__(84);
11324
11698
  __webpack_require__(85);
11325
11699
  __webpack_require__(86);
11700
+ __webpack_require__(87);
11326
11701
  __webpack_require__(88);
11327
- __webpack_require__(90);
11702
+ __webpack_require__(89);
11328
11703
  __webpack_require__(91);
11329
11704
  __webpack_require__(93);
11330
- __webpack_require__(95);
11331
- __webpack_require__(97);
11705
+ __webpack_require__(94);
11706
+ __webpack_require__(96);
11332
11707
  __webpack_require__(98);
11333
- __webpack_require__(99);
11334
11708
  __webpack_require__(100);
11709
+ __webpack_require__(101);
11710
+ __webpack_require__(102);
11711
+ __webpack_require__(103);
11335
11712
  up.framework.onEvaled();
11336
11713
 
11337
11714
  })();