unpoly-rails 3.10.0 → 3.11.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,7 +5,7 @@
5
5
  /***/ (() => {
6
6
 
7
7
  window.up = {
8
- version: '3.10.0'
8
+ version: '3.11.0-rc1'
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,15 @@ 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;
152
148
  }
153
- function isUndefined(object) {
154
- return object === undefined;
149
+ function isUndefined(value) {
150
+ return value === undefined;
155
151
  }
156
152
  const isDefined = negate(isUndefined);
157
- function isMissing(object) {
158
- return isUndefined(object) || isNull(object);
153
+ function isMissing(value) {
154
+ return isUndefined(value) || isNull(value);
159
155
  }
160
156
  const isGiven = negate(isMissing);
161
157
  function isBlank(value) {
@@ -180,49 +176,49 @@ up.util = (function () {
180
176
  }
181
177
  }
182
178
  const isPresent = negate(isBlank);
183
- function isFunction(object) {
184
- return typeof (object) === 'function';
179
+ function isFunction(value) {
180
+ return typeof (value) === 'function';
185
181
  }
186
- function isString(object) {
187
- return (typeof (object) === 'string') || object instanceof String;
182
+ function isString(value) {
183
+ return (typeof (value) === 'string') || value instanceof String;
188
184
  }
189
- function isBoolean(object) {
190
- return (typeof (object) === 'boolean') || object instanceof Boolean;
185
+ function isBoolean(value) {
186
+ return (typeof (value) === 'boolean') || value instanceof Boolean;
191
187
  }
192
- function isNumber(object) {
193
- return (typeof (object) === 'number') || object instanceof Number;
188
+ function isNumber(value) {
189
+ return (typeof (value) === 'number') || value instanceof Number;
194
190
  }
195
- function isOptions(object) {
196
- return (typeof (object) === 'object') && !isNull(object) && (isUndefined(object.constructor) || (object.constructor === Object));
191
+ function isOptions(value) {
192
+ return (typeof (value) === 'object') && !isNull(value) && (isUndefined(value.constructor) || (value.constructor === Object));
197
193
  }
198
- function isObject(object) {
199
- const typeOfResult = typeof (object);
200
- return ((typeOfResult === 'object') && !isNull(object)) || (typeOfResult === 'function');
194
+ function isObject(value) {
195
+ const typeOfResult = typeof (value);
196
+ return ((typeOfResult === 'object') && !isNull(value)) || (typeOfResult === 'function');
201
197
  }
202
- function isElement(object) {
203
- return object instanceof Element;
198
+ function isElement(value) {
199
+ return value instanceof Element;
204
200
  }
205
- function isTextNode(object) {
206
- return object instanceof Text;
201
+ function isTextNode(value) {
202
+ return value instanceof Text;
207
203
  }
208
- function isRegExp(object) {
209
- return object instanceof RegExp;
204
+ function isRegExp(value) {
205
+ return value instanceof RegExp;
210
206
  }
211
- function isError(object) {
212
- return object instanceof Error;
207
+ function isError(value) {
208
+ return value instanceof Error;
213
209
  }
214
- function isJQuery(object) {
215
- return up.browser.canJQuery() && object instanceof jQuery;
210
+ function isJQuery(value) {
211
+ return up.browser.canJQuery() && value instanceof jQuery;
216
212
  }
217
- function isElementLike(object) {
218
- return !!(object && (object.addEventListener || (isJQuery(object) && object[0]?.addEventListener)));
213
+ function isElementLike(value) {
214
+ return !!(value && (value.addEventListener || (isJQuery(value) && value[0]?.addEventListener)));
219
215
  }
220
- function isPromise(object) {
221
- return isObject(object) && isFunction(object.then);
216
+ function isPromise(value) {
217
+ return isObject(value) && isFunction(value.then);
222
218
  }
223
219
  const { isArray } = Array;
224
- function isFormData(object) {
225
- return object instanceof FormData;
220
+ function isFormData(value) {
221
+ return value instanceof FormData;
226
222
  }
227
223
  function toArray(value) {
228
224
  return isArray(value) ? value : copyArrayLike(value);
@@ -389,13 +385,15 @@ up.util = (function () {
389
385
  return filterList(list, tester);
390
386
  }
391
387
  function intersect(array1, array2) {
392
- return filterList(array1, element => contains(array2, element));
388
+ return filterList(array1, (element) => contains(array2, element));
393
389
  }
394
390
  function scheduleTimer(millis, callback) {
395
391
  return setTimeout(callback, millis);
396
392
  }
397
393
  function queueTask(task) {
398
- return setTimeout(task);
394
+ const channel = new MessageChannel();
395
+ channel.port1.onmessage = () => task();
396
+ channel.port2.postMessage(0);
399
397
  }
400
398
  function last(value) {
401
399
  return value[value.length - 1];
@@ -462,7 +460,7 @@ up.util = (function () {
462
460
  "'": '''
463
461
  };
464
462
  function escapeHTML(string) {
465
- return string.replace(/[&<>"']/g, char => ESCAPE_HTML_ENTITY_MAP[char]);
463
+ return string.replace(/[&<>"']/g, (char) => ESCAPE_HTML_ENTITY_MAP[char]);
466
464
  }
467
465
  function escapeRegExp(string) {
468
466
  return string.replace(/[\\^$*+?.()|[\]{}]/g, '\\$&');
@@ -491,9 +489,9 @@ up.util = (function () {
491
489
  function identity(arg) {
492
490
  return arg;
493
491
  }
494
- function sequence(functions) {
495
- functions = compact(functions);
496
- return (...args) => map(functions, fn => fn(...args));
492
+ function sequence(...args) {
493
+ let functions = scanFunctions(...args);
494
+ return (...args) => map(functions, (fn) => fn(...args));
497
495
  }
498
496
  function flatten(array) {
499
497
  const flattened = [];
@@ -547,7 +545,7 @@ up.util = (function () {
547
545
  const aKeys = Object.keys(a);
548
546
  const bKeys = Object.keys(b);
549
547
  if (isEqualList(aKeys, bKeys)) {
550
- return every(aKeys, aKey => isEqual(a[aKey], b[aKey]));
548
+ return every(aKeys, (aKey) => isEqual(a[aKey], b[aKey]));
551
549
  }
552
550
  else {
553
551
  return false;
@@ -611,7 +609,7 @@ up.util = (function () {
611
609
  return renamed;
612
610
  }
613
611
  function camelToKebabCase(str) {
614
- return str.replace(/[A-Z]/g, char => '-' + char.toLowerCase());
612
+ return str.replace(/[A-Z]/g, (char) => '-' + char.toLowerCase());
615
613
  }
616
614
  function lowerCaseFirst(str) {
617
615
  return str[0].toLowerCase() + str.slice(1);
@@ -637,8 +635,8 @@ up.util = (function () {
637
635
  });
638
636
  }
639
637
  }
640
- function delegatePromise(object, promiseProp) {
641
- return defineDelegates(object, ['then', 'catch', 'finally'], function () { return this[promiseProp]; });
638
+ function delegatePromise(object, targetProvider) {
639
+ return defineDelegates(object, ['then', 'catch', 'finally'], targetProvider);
642
640
  }
643
641
  function stringifyArg(arg, placeholder = '%o') {
644
642
  let string;
@@ -865,6 +863,9 @@ up.util = (function () {
865
863
  ];
866
864
  });
867
865
  }
866
+ function spanObject(keys, value) {
867
+ return mapObject(keys, (key) => [key, value]);
868
+ }
868
869
  return {
869
870
  parseURL,
870
871
  normalizeURL,
@@ -882,6 +883,7 @@ up.util = (function () {
882
883
  map,
883
884
  flatMap,
884
885
  mapObject,
886
+ spanObject,
885
887
  findResult,
886
888
  some,
887
889
  every,
@@ -1085,12 +1087,13 @@ up.element = (function () {
1085
1087
  return root.querySelector(selector);
1086
1088
  }
1087
1089
  function subtree(root, selector) {
1088
- const results = [];
1090
+ const descendantMatches = root.querySelectorAll(selector);
1089
1091
  if (elementLikeMatches(root, selector)) {
1090
- results.push(root);
1092
+ return [root, ...descendantMatches];
1093
+ }
1094
+ else {
1095
+ return descendantMatches;
1091
1096
  }
1092
- results.push(...root.querySelectorAll(selector));
1093
- return results;
1094
1097
  }
1095
1098
  function subtreeFirst(root, selector) {
1096
1099
  return elementLikeMatches(root, selector) ? root : root.querySelector(selector);
@@ -1196,7 +1199,7 @@ up.element = (function () {
1196
1199
  }
1197
1200
  function metaContent(name) {
1198
1201
  const selector = "meta" + attrSelector('name', name);
1199
- return first(selector)?.getAttribute('content');
1202
+ return document.head.querySelector(selector)?.getAttribute('content');
1200
1203
  }
1201
1204
  function insertBefore(existingNode, newNode) {
1202
1205
  existingNode.parentNode.insertBefore(newNode, existingNode);
@@ -1306,7 +1309,7 @@ up.element = (function () {
1306
1309
  return element;
1307
1310
  }
1308
1311
  const SINGLETON_TAG_NAMES = ['HTML', 'BODY', 'HEAD', 'TITLE'];
1309
- const isSingleton = up.mockable(element => element.matches(SINGLETON_TAG_NAMES.join()));
1312
+ const isSingleton = up.mockable((element) => element.matches(SINGLETON_TAG_NAMES.join()));
1310
1313
  function elementTagName(element) {
1311
1314
  return element.tagName.toLowerCase();
1312
1315
  }
@@ -1334,9 +1337,11 @@ up.element = (function () {
1334
1337
  function createBrokenDocumentFromHTML(html) {
1335
1338
  return new DOMParser().parseFromString(html, 'text/html');
1336
1339
  }
1337
- function fixParserDamage(scriptish) {
1338
- let clone = createFromHTML(scriptish.outerHTML);
1339
- scriptish.replaceWith(clone);
1340
+ function revivedClone(element) {
1341
+ let clone = createFromHTML(element.outerHTML);
1342
+ if ('nonce' in element)
1343
+ clone.nonce = element.nonce;
1344
+ return clone;
1340
1345
  }
1341
1346
  function createFromHTML(html) {
1342
1347
  return extractSingular(createNodesFromHTML(html));
@@ -1618,6 +1623,18 @@ up.element = (function () {
1618
1623
  return [element.parentElement, 'beforeend'];
1619
1624
  }
1620
1625
  }
1626
+ function moveBefore(parent, movedElement, referenceElement) {
1627
+ let fn = parent.moveBefore || parent.insertBefore;
1628
+ fn.call(parent, movedElement, referenceElement);
1629
+ }
1630
+ function preservingAppend(parent, newNode) {
1631
+ moveBefore(parent, newNode, null);
1632
+ }
1633
+ function preservingReplace(oldElement, newElement) {
1634
+ let parent = oldElement.parentElement;
1635
+ moveBefore(parent, newElement, oldElement);
1636
+ oldElement.remove();
1637
+ }
1621
1638
  return {
1622
1639
  subtree,
1623
1640
  subtreeFirst,
@@ -1644,7 +1661,7 @@ up.element = (function () {
1644
1661
  attrSelector,
1645
1662
  tagName: elementTagName,
1646
1663
  createBrokenDocumentFromHTML,
1647
- fixParserDamage,
1664
+ revivedClone,
1648
1665
  createNodesFromHTML,
1649
1666
  createFromHTML,
1650
1667
  extractSingular,
@@ -1686,6 +1703,8 @@ up.element = (function () {
1686
1703
  matchSelectorMap,
1687
1704
  elementLikeMatches,
1688
1705
  documentPosition,
1706
+ preservingAppend,
1707
+ preservingReplace,
1689
1708
  };
1690
1709
  })();
1691
1710
 
@@ -1779,7 +1798,7 @@ up.Record = class Record {
1779
1798
  return {};
1780
1799
  }
1781
1800
  constructor(options) {
1782
- Object.assign(this, this.defaults(options), this.attributes(options));
1801
+ Object.assign(this, u.mergeDefined(this.defaults(options), this.attributes(options)));
1783
1802
  }
1784
1803
  attributes(source = this) {
1785
1804
  return u.pick(source, this.keys());
@@ -1858,13 +1877,39 @@ up.LogConfig = class LogConfig extends up.Config {
1858
1877
  /* 19 */
1859
1878
  /***/ (() => {
1860
1879
 
1880
+ const u = up.util;
1881
+ up.Registry = class Registry {
1882
+ constructor(valueDescription, normalize = u.identity) {
1883
+ this._data = {};
1884
+ this._normalize = normalize;
1885
+ this._valueDescription = valueDescription;
1886
+ this.put = this.put.bind(this);
1887
+ document.addEventListener('up:framework:reset', () => this.reset());
1888
+ }
1889
+ put(key, object) {
1890
+ object = this._normalize(object);
1891
+ object.isDefault = up.framework.evaling;
1892
+ this._data[key] = object;
1893
+ }
1894
+ get(name) {
1895
+ return this._data[name] || up.fail("Unknown %s %o", this._valueDescription, name);
1896
+ }
1897
+ reset() {
1898
+ this._data = u.pickBy(this._data, 'isDefault');
1899
+ }
1900
+ };
1901
+
1902
+
1903
+ /***/ }),
1904
+ /* 20 */
1905
+ /***/ (() => {
1906
+
1861
1907
  const u = up.util;
1862
1908
  const e = up.element;
1863
1909
  up.OptionsParser = class OptionsParser {
1864
1910
  constructor(element, options, parserOptions = {}) {
1865
1911
  this._options = options;
1866
1912
  this._element = element;
1867
- this._parserOptions = parserOptions;
1868
1913
  this._fail = parserOptions.fail;
1869
1914
  this._closest = parserOptions.closest;
1870
1915
  this._attrPrefix = parserOptions.attrPrefix || 'up-';
@@ -1899,11 +1944,11 @@ up.OptionsParser = class OptionsParser {
1899
1944
  value ??= this._parseFromAttr(attrValueFn, this._element, attrName);
1900
1945
  }
1901
1946
  value ??= keyOptions.default ?? this._defaults[key];
1902
- let normalizeFn = keyOptions.normalize;
1903
- if (normalizeFn) {
1904
- value = normalizeFn(value);
1905
- }
1906
1947
  if (u.isDefined(value)) {
1948
+ let normalizeFn = keyOptions.normalize;
1949
+ if (normalizeFn) {
1950
+ value = normalizeFn(value);
1951
+ }
1907
1952
  this._options[key] = value;
1908
1953
  }
1909
1954
  let failKey;
@@ -1912,8 +1957,8 @@ up.OptionsParser = class OptionsParser {
1912
1957
  this.parse(attrValueFn, failKey, { ...keyOptions, attr: failAttrNames });
1913
1958
  }
1914
1959
  }
1915
- include(optionsFn) {
1916
- let fnResult = optionsFn(this._element, this._options, this._parserOptions);
1960
+ include(optionsFn, parserOptions) {
1961
+ let fnResult = optionsFn(this._element, this._options, { defaults: this._defaults, ...parserOptions });
1917
1962
  Object.assign(this._options, fnResult);
1918
1963
  }
1919
1964
  _parseFromAttr(attrValueFn, element, attrName) {
@@ -1940,7 +1985,7 @@ up.OptionsParser = class OptionsParser {
1940
1985
 
1941
1986
 
1942
1987
  /***/ }),
1943
- /* 20 */
1988
+ /* 21 */
1944
1989
  /***/ (() => {
1945
1990
 
1946
1991
  const u = up.util;
@@ -1969,7 +2014,7 @@ up.FIFOCache = class FIFOCache {
1969
2014
 
1970
2015
 
1971
2016
  /***/ }),
1972
- /* 21 */
2017
+ /* 22 */
1973
2018
  /***/ (() => {
1974
2019
 
1975
2020
  up.Rect = class Rect extends up.Record {
@@ -2000,7 +2045,7 @@ up.Rect = class Rect extends up.Record {
2000
2045
 
2001
2046
 
2002
2047
  /***/ }),
2003
- /* 22 */
2048
+ /* 23 */
2004
2049
  /***/ (() => {
2005
2050
 
2006
2051
  const e = up.element;
@@ -2048,7 +2093,7 @@ up.BodyShifter = class BodyShifter {
2048
2093
 
2049
2094
 
2050
2095
  /***/ }),
2051
- /* 23 */
2096
+ /* 24 */
2052
2097
  /***/ (() => {
2053
2098
 
2054
2099
  const u = up.util;
@@ -2074,7 +2119,7 @@ up.Change = class Change {
2074
2119
 
2075
2120
 
2076
2121
  /***/ }),
2077
- /* 24 */
2122
+ /* 25 */
2078
2123
  /***/ (() => {
2079
2124
 
2080
2125
  const u = up.util;
@@ -2149,7 +2194,7 @@ up.Change.Addition = class Addition extends up.Change {
2149
2194
 
2150
2195
 
2151
2196
  /***/ }),
2152
- /* 25 */
2197
+ /* 26 */
2153
2198
  /***/ (() => {
2154
2199
 
2155
2200
  var _a;
@@ -2262,7 +2307,7 @@ up.RenderJob = (_a = class RenderJob {
2262
2307
  }
2263
2308
  },
2264
2309
  (() => {
2265
- u.delegatePromise(_a.prototype, '_rendered');
2310
+ u.delegatePromise(_a.prototype, function () { return this._rendered; });
2266
2311
  u.memoizeMethod(_a.prototype, {
2267
2312
  _awaitFinished: true,
2268
2313
  _getChange: true,
@@ -2272,7 +2317,7 @@ up.RenderJob = (_a = class RenderJob {
2272
2317
 
2273
2318
 
2274
2319
  /***/ }),
2275
- /* 26 */
2320
+ /* 27 */
2276
2321
  /***/ (() => {
2277
2322
 
2278
2323
  up.Change.DestroyFragment = class DestroyFragment extends up.Change {
@@ -2297,18 +2342,18 @@ up.Change.DestroyFragment = class DestroyFragment extends up.Change {
2297
2342
  async _destroyAfterAnimation() {
2298
2343
  this._emitDestroyed();
2299
2344
  await this._animate();
2300
- this._wipe();
2345
+ this._erase();
2301
2346
  this._onFinished?.();
2302
2347
  }
2303
2348
  _destroyNow() {
2304
- this._wipe();
2349
+ this._erase();
2305
2350
  this._emitDestroyed();
2306
2351
  this._onFinished?.();
2307
2352
  }
2308
2353
  _animate() {
2309
2354
  return up.motion.animate(this._element, this._animation, this.options);
2310
2355
  }
2311
- _wipe() {
2356
+ _erase() {
2312
2357
  this._layer.asCurrent(() => {
2313
2358
  up.fragment.abort(this._element);
2314
2359
  up.script.clean(this._element, { layer: this._layer });
@@ -2323,7 +2368,7 @@ up.Change.DestroyFragment = class DestroyFragment extends up.Change {
2323
2368
 
2324
2369
 
2325
2370
  /***/ }),
2326
- /* 27 */
2371
+ /* 28 */
2327
2372
  /***/ (() => {
2328
2373
 
2329
2374
  let u = up.util;
@@ -2414,7 +2459,7 @@ up.Change.OpenLayer = class OpenLayer extends up.Change.Addition {
2414
2459
  }
2415
2460
  _buildLayer() {
2416
2461
  const buildOptions = { ...this.options, opening: true };
2417
- const beforeNew = optionsWithLayerDefaults => {
2462
+ const beforeNew = (optionsWithLayerDefaults) => {
2418
2463
  return this.options = up.RenderOptions.finalize(optionsWithLayerDefaults);
2419
2464
  };
2420
2465
  return up.layer.build(buildOptions, beforeNew);
@@ -2478,7 +2523,7 @@ up.Change.OpenLayer = class OpenLayer extends up.Change.Addition {
2478
2523
 
2479
2524
 
2480
2525
  /***/ }),
2481
- /* 28 */
2526
+ /* 29 */
2482
2527
  /***/ (() => {
2483
2528
 
2484
2529
  var _a;
@@ -2629,7 +2674,7 @@ up.Change.UpdateLayer = (_a = class UpdateLayer extends up.Change.Addition {
2629
2674
 
2630
2675
 
2631
2676
  /***/ }),
2632
- /* 29 */
2677
+ /* 30 */
2633
2678
  /***/ (() => {
2634
2679
 
2635
2680
  const u = up.util;
@@ -2652,7 +2697,7 @@ up.Change.UpdateSteps = class UpdateSteps extends up.Change.Addition {
2652
2697
  target: up.fragment.targetForSteps(this._steps),
2653
2698
  });
2654
2699
  this._steps.reverse();
2655
- const motionEndPromises = this._steps.map(step => this._executeStep(step));
2700
+ const motionEndPromises = this._steps.map((step) => this._executeStep(step));
2656
2701
  this.renderResult.finished = this._finish(motionEndPromises);
2657
2702
  return this.renderResult;
2658
2703
  }
@@ -2683,7 +2728,7 @@ up.Change.UpdateSteps = class UpdateSteps extends up.Change.Addition {
2683
2728
  return Promise.resolve();
2684
2729
  }
2685
2730
  else {
2686
- this._preserveKeepables(step);
2731
+ this._preserveDescendantKeepables(step);
2687
2732
  const parent = step.oldElement.parentNode;
2688
2733
  const morphOptions = {
2689
2734
  ...step,
@@ -2691,9 +2736,9 @@ up.Change.UpdateSteps = class UpdateSteps extends up.Change.Addition {
2691
2736
  up.fragment.markAsDestroying(step.oldElement);
2692
2737
  },
2693
2738
  afterInsert: () => {
2694
- this._restoreKeepables(step);
2739
+ this._restoreDescendantKeepables(step);
2695
2740
  this.responseDoc.finalizeElement(step.newElement);
2696
- this._unmarkKeepables(step);
2741
+ this._finalizeDescendantKeepables(step);
2697
2742
  up.hello(step.newElement, step);
2698
2743
  this._addToResult(step.newElement);
2699
2744
  },
@@ -2774,8 +2819,8 @@ up.Change.UpdateSteps = class UpdateSteps extends up.Change.Addition {
2774
2819
  }
2775
2820
  }
2776
2821
  }
2777
- _preserveKeepables(step) {
2778
- const keepPlans = [];
2822
+ _preserveDescendantKeepables(step) {
2823
+ const descendantKeepPlans = [];
2779
2824
  if (step.keep) {
2780
2825
  for (let keepable of step.oldElement.querySelectorAll('[up-keep]')) {
2781
2826
  let keepPlan = this._findKeepPlan({ ...step, oldElement: keepable, descendantsOnly: true });
@@ -2785,37 +2830,42 @@ up.Change.UpdateSteps = class UpdateSteps extends up.Change.Addition {
2785
2830
  keepable.classList.add('up-keeping');
2786
2831
  up.script.disableSubtree(keepPlan.newElement);
2787
2832
  let viewports = up.viewport.subtree(keepPlan.oldElement);
2788
- keepPlan.revivers = viewports.map(function (viewport) {
2833
+ keepPlan.revivers = u.map(viewports, function (viewport) {
2789
2834
  let cursorProps = up.viewport.copyCursorProps(viewport);
2790
2835
  return () => up.viewport.copyCursorProps(cursorProps, viewport);
2791
2836
  });
2792
- if (this._willChangeElement(document.body)) {
2837
+ if (this._willChangeBody()) {
2793
2838
  keepPlan.newElement.replaceWith(keepable);
2794
2839
  }
2795
2840
  else {
2796
- document.body.append(keepable);
2841
+ e.preservingAppend(document.body, keepable);
2797
2842
  }
2798
- keepPlans.push(keepPlan);
2843
+ descendantKeepPlans.push(keepPlan);
2799
2844
  }
2800
2845
  }
2801
2846
  }
2802
- step.keepPlans = keepPlans;
2847
+ step.descendantKeepPlans = descendantKeepPlans;
2803
2848
  }
2804
- _restoreKeepables(step) {
2805
- for (let keepPlan of step.keepPlans) {
2806
- keepPlan.newElement.replaceWith(keepPlan.oldElement);
2849
+ _restoreDescendantKeepables(step) {
2850
+ for (let keepPlan of step.descendantKeepPlans) {
2851
+ if (this._willChangeBody()) {
2852
+ keepPlan.newElement.replaceWith(keepPlan.oldElement);
2853
+ }
2854
+ else {
2855
+ e.preservingReplace(keepPlan.newElement, keepPlan.oldElement);
2856
+ }
2807
2857
  for (let reviver of keepPlan.revivers) {
2808
2858
  reviver();
2809
2859
  }
2810
2860
  }
2811
2861
  }
2812
- _unmarkKeepables(step) {
2813
- for (let keepPlan of step.keepPlans) {
2862
+ _finalizeDescendantKeepables(step) {
2863
+ for (let keepPlan of step.descendantKeepPlans) {
2814
2864
  keepPlan.oldElement.classList.remove('up-keeping');
2815
2865
  }
2816
2866
  }
2817
- _willChangeElement(element) {
2818
- return u.some(this._steps, (step) => step.oldElement.contains(element));
2867
+ _willChangeBody() {
2868
+ return u.some(this._steps, (step) => step.oldElement.matches('body'));
2819
2869
  }
2820
2870
  _handleFocus(fragment, options) {
2821
2871
  const fragmentFocus = new up.FragmentFocus({
@@ -2837,7 +2887,7 @@ up.Change.UpdateSteps = class UpdateSteps extends up.Change.Addition {
2837
2887
 
2838
2888
 
2839
2889
  /***/ }),
2840
- /* 30 */
2890
+ /* 31 */
2841
2891
  /***/ (() => {
2842
2892
 
2843
2893
  const u = up.util;
@@ -2853,9 +2903,8 @@ up.Change.CloseLayer = class CloseLayer extends up.Change {
2853
2903
  this._history = options.history ?? true;
2854
2904
  }
2855
2905
  execute() {
2856
- if (!this._layer.isOpen()) {
2857
- return Promise.resolve();
2858
- }
2906
+ if (!this._layer.isOpen())
2907
+ return;
2859
2908
  up.browser.assertConfirmed(this.options);
2860
2909
  if (this._emitCloseEvent().defaultPrevented && this._preventable) {
2861
2910
  throw new up.Aborted('Close event was prevented');
@@ -2904,16 +2953,19 @@ up.Change.CloseLayer = class CloseLayer extends up.Change {
2904
2953
  });
2905
2954
  }
2906
2955
  _handleFocus(formerParent) {
2956
+ let hadFocus = this._layer.hasFocus();
2907
2957
  this._layer.overlayFocus.teardown();
2908
2958
  formerParent.overlayFocus?.moveToFront();
2909
- let newFocusElement = this._layer.origin || formerParent.element;
2910
- up.focus(newFocusElement, { preventScroll: true });
2959
+ if (hadFocus) {
2960
+ let newFocusElement = this._layer.origin || formerParent.element;
2961
+ up.focus(newFocusElement, { preventScroll: true });
2962
+ }
2911
2963
  }
2912
2964
  };
2913
2965
 
2914
2966
 
2915
2967
  /***/ }),
2916
- /* 31 */
2968
+ /* 32 */
2917
2969
  /***/ (() => {
2918
2970
 
2919
2971
  var _a;
@@ -2932,7 +2984,7 @@ up.Change.FromURL = (_a = class FromURL extends up.Change {
2932
2984
  return request;
2933
2985
  this.options.handleAbort?.(request);
2934
2986
  request.runPreviews(this.options);
2935
- return await u.always(request, responseOrError => this._onRequestSettled(responseOrError));
2987
+ return await u.always(request, (responseOrError) => this._onRequestSettled(responseOrError));
2936
2988
  }
2937
2989
  _newPageReason() {
2938
2990
  if (u.isCrossOrigin(this.options.url)) {
@@ -2990,7 +3042,7 @@ up.Change.FromURL = (_a = class FromURL extends up.Change {
2990
3042
 
2991
3043
 
2992
3044
  /***/ }),
2993
- /* 32 */
3045
+ /* 33 */
2994
3046
  /***/ (() => {
2995
3047
 
2996
3048
  var _a;
@@ -3108,6 +3160,17 @@ up.Change.FromResponse = (_a = class FromResponse extends up.Change {
3108
3160
  renderOptions.source = this.improveHistoryValue(renderOptions.source, 'keep');
3109
3161
  renderOptions.history = !!renderOptions.location;
3110
3162
  }
3163
+ let openLayerOptions = this._response.openLayer;
3164
+ if (openLayerOptions) {
3165
+ Object.assign(renderOptions, {
3166
+ ...up.Layer.Overlay.UNSET_VISUALS,
3167
+ target: undefined,
3168
+ ...up.fragment.config.navigateOptions,
3169
+ ...openLayerOptions,
3170
+ layer: 'new',
3171
+ });
3172
+ Object.assign(renderOptions, openLayerOptions);
3173
+ }
3111
3174
  renderOptions.location = this.improveHistoryValue(renderOptions.location, serverLocation);
3112
3175
  renderOptions.title = this.improveHistoryValue(renderOptions.title, this._response.title);
3113
3176
  renderOptions.eventPlans = this._response.eventPlans;
@@ -3122,7 +3185,7 @@ up.Change.FromResponse = (_a = class FromResponse extends up.Change {
3122
3185
  renderOptions.target = ':none';
3123
3186
  }
3124
3187
  renderOptions.context = u.merge(renderOptions.context, this._response.context);
3125
- renderOptions.cspNonces = this._response.cspNonces;
3188
+ renderOptions.cspInfo = this._response.cspInfo;
3126
3189
  renderOptions.time ??= this._response.lastModified;
3127
3190
  renderOptions.etag ??= this._response.etag;
3128
3191
  }
@@ -3136,7 +3199,7 @@ up.Change.FromResponse = (_a = class FromResponse extends up.Change {
3136
3199
 
3137
3200
 
3138
3201
  /***/ }),
3139
- /* 33 */
3202
+ /* 34 */
3140
3203
  /***/ (() => {
3141
3204
 
3142
3205
  var _a;
@@ -3208,7 +3271,7 @@ up.Change.FromContent = (_a = class FromContent extends up.Change {
3208
3271
  'fragment',
3209
3272
  'document',
3210
3273
  'html',
3211
- 'cspNonces',
3274
+ 'cspInfo',
3212
3275
  'origin',
3213
3276
  'data',
3214
3277
  ]);
@@ -3239,7 +3302,7 @@ up.Change.FromContent = (_a = class FromContent extends up.Change {
3239
3302
  return this._expandTargets(target || ':main', layer)[0];
3240
3303
  }
3241
3304
  getPreflightProps(opts = {}) {
3242
- const getPlanProps = plan => plan.getPreflightProps();
3305
+ const getPlanProps = (plan) => plan.getPreflightProps();
3243
3306
  return this._seekPlan(getPlanProps) || opts.optional || this._cannotMatchPreflightTarget();
3244
3307
  }
3245
3308
  _cannotMatchPreflightTarget() {
@@ -3291,7 +3354,7 @@ up.Change.FromContent = (_a = class FromContent extends up.Change {
3291
3354
 
3292
3355
 
3293
3356
  /***/ }),
3294
- /* 34 */
3357
+ /* 35 */
3295
3358
  /***/ (() => {
3296
3359
 
3297
3360
  const u = up.util;
@@ -3386,7 +3449,7 @@ up.CompilerPass = class CompilerPass {
3386
3449
 
3387
3450
 
3388
3451
  /***/ }),
3389
- /* 35 */
3452
+ /* 36 */
3390
3453
  /***/ (() => {
3391
3454
 
3392
3455
  const u = up.util;
@@ -3491,7 +3554,7 @@ up.CSSTransition = class CSSTransition {
3491
3554
 
3492
3555
 
3493
3556
  /***/ }),
3494
- /* 36 */
3557
+ /* 37 */
3495
3558
  /***/ (() => {
3496
3559
 
3497
3560
  const u = up.util;
@@ -3514,7 +3577,7 @@ up.DestructorPass = class DestructorPass {
3514
3577
 
3515
3578
 
3516
3579
  /***/ }),
3517
- /* 37 */
3580
+ /* 38 */
3518
3581
  /***/ (() => {
3519
3582
 
3520
3583
  const u = up.util;
@@ -3613,7 +3676,7 @@ up.EventEmitter = class EventEmitter extends up.Record {
3613
3676
 
3614
3677
 
3615
3678
  /***/ }),
3616
- /* 38 */
3679
+ /* 39 */
3617
3680
  /***/ (() => {
3618
3681
 
3619
3682
  const u = up.util;
@@ -3664,7 +3727,8 @@ up.EventListener = class EventListener extends up.Record {
3664
3727
  }
3665
3728
  let element = event.target;
3666
3729
  if (this.selector) {
3667
- element = element.closest(u.evalOption(this.selector));
3730
+ let selector = u.evalOption(this.selector);
3731
+ element = element.closest(selector);
3668
3732
  }
3669
3733
  if (this.guard && !this.guard(event)) {
3670
3734
  return;
@@ -3717,7 +3781,7 @@ up.EventListener = class EventListener extends up.Record {
3717
3781
 
3718
3782
 
3719
3783
  /***/ }),
3720
- /* 39 */
3784
+ /* 40 */
3721
3785
  /***/ (() => {
3722
3786
 
3723
3787
  const u = up.util;
@@ -3763,7 +3827,7 @@ up.EventListenerGroup = class EventListenerGroup extends up.Record {
3763
3827
  }
3764
3828
  });
3765
3829
  }
3766
- static fromBindArgs(args, defaults) {
3830
+ static fromBindArgs(args, overrides) {
3767
3831
  args = u.copy(args);
3768
3832
  const callback = args.pop();
3769
3833
  let elements;
@@ -3783,14 +3847,63 @@ up.EventListenerGroup = class EventListenerGroup extends up.Record {
3783
3847
  }
3784
3848
  const options = u.extractOptions(args);
3785
3849
  const selector = args[0];
3786
- const attributes = { elements, eventTypes, selector, callback, ...options, ...defaults };
3850
+ const attributes = { elements, eventTypes, selector, callback, ...options, ...overrides };
3787
3851
  return new (this)(attributes);
3788
3852
  }
3789
3853
  };
3790
3854
 
3791
3855
 
3792
3856
  /***/ }),
3793
- /* 40 */
3857
+ /* 41 */
3858
+ /***/ (() => {
3859
+
3860
+ const u = up.util;
3861
+ up.SelectorTracker = class SelectorTracker {
3862
+ constructor(selector, options, addCallback) {
3863
+ this._selector = selector;
3864
+ this._addCallback = addCallback;
3865
+ this._layer = options.layer || 'any';
3866
+ this._filter = options.filter || u.identity;
3867
+ this._live = options.live ?? true;
3868
+ this._knownMatches = new Map();
3869
+ }
3870
+ start() {
3871
+ this._sync();
3872
+ return u.sequence(this._trackFragments(), () => this._removeAllMatches());
3873
+ }
3874
+ _trackFragments() {
3875
+ if (this._live) {
3876
+ return up.on('up:fragment:inserted up:fragment:destroyed', () => this._sync());
3877
+ }
3878
+ }
3879
+ _sync() {
3880
+ let removeMap = new Map(this._knownMatches);
3881
+ this._knownMatches.clear();
3882
+ for (let newMatch of this._currentMatches) {
3883
+ let knownRemoveCallback = removeMap.get(newMatch);
3884
+ removeMap.delete(newMatch);
3885
+ let removeCallback = knownRemoveCallback || this._addCallback(newMatch) || u.noop;
3886
+ this._knownMatches.set(newMatch, removeCallback);
3887
+ }
3888
+ this._runRemoveCallbacks(removeMap);
3889
+ }
3890
+ get _currentMatches() {
3891
+ let allMatches = up.fragment.all(this._selector, { layer: this._layer });
3892
+ return this._filter(allMatches);
3893
+ }
3894
+ _removeAllMatches() {
3895
+ this._runRemoveCallbacks(this._knownMatches);
3896
+ }
3897
+ _runRemoveCallbacks(map) {
3898
+ for (let [element, removeCallback] of map) {
3899
+ removeCallback(element);
3900
+ }
3901
+ }
3902
+ };
3903
+
3904
+
3905
+ /***/ }),
3906
+ /* 42 */
3794
3907
  /***/ (() => {
3795
3908
 
3796
3909
  const u = up.util;
@@ -3798,40 +3911,46 @@ up.FieldWatcher = class FieldWatcher {
3798
3911
  constructor(root, options, callback) {
3799
3912
  this._options = options;
3800
3913
  this._root = root;
3801
- this._scope = up.form.getScope(root);
3802
3914
  this._callback = callback;
3803
3915
  this._batch = options.batch;
3916
+ this._logPrefix = options.logPrefix ?? 'up.watch()';
3917
+ this._ensureWatchable();
3804
3918
  }
3805
3919
  start() {
3806
3920
  this._scheduledValues = null;
3807
3921
  this._processedValues = this._readFieldValues();
3808
3922
  this._currentTimer = null;
3809
3923
  this._callbackRunning = false;
3810
- this._cleaner = u.cleaner();
3811
- this._watchFieldsWithin(this._root);
3812
- this._root.addEventListener('up:fragment:inserted', ({ target }) => {
3813
- if (target !== this._root)
3814
- this._watchFieldsWithin(target);
3815
- });
3816
- this._cleaner(up.fragment.onAborted(this._scope, () => this._abort()));
3817
- this._cleaner(up.on(this._scope, 'reset', () => this._onFormReset()));
3924
+ return u.sequence(up.form.trackFields(this._root, (field) => this._watchField(field)), this._trackAbort(), this._trackReset(), () => this._abort());
3818
3925
  }
3819
- stop() {
3820
- this._abort();
3821
- this._cleaner.clean();
3926
+ _ensureWatchable() {
3927
+ const fail = (message) => up.fail(message, this._logPrefix, this._root);
3928
+ if (!this._callback) {
3929
+ fail('No callback provided for %s (%o)');
3930
+ }
3931
+ if (this._root.matches('input[type=radio]')) {
3932
+ fail('Use %s with the container of a radio group, not with an individual radio button (%o)');
3933
+ }
3934
+ }
3935
+ _trackAbort() {
3936
+ let guard = ({ target }) => target.contains(this._region);
3937
+ return up.on('up:fragment:aborted', { guard }, () => this._abort());
3938
+ }
3939
+ _trackReset() {
3940
+ let guard = ({ target }) => target === this._region;
3941
+ return up.on('reset', { guard }, (event) => this._onFormReset(event));
3942
+ }
3943
+ get _region() {
3944
+ return up.form.getRegion(this._root);
3822
3945
  }
3823
3946
  _fieldOptions(field) {
3824
3947
  let rootOptions = u.copy(this._options);
3825
3948
  return up.form.watchOptions(field, rootOptions, { defaults: { event: 'input' } });
3826
3949
  }
3827
- _watchFieldsWithin(container) {
3828
- for (let field of up.form.fields(container)) {
3829
- this._watchField(field);
3830
- }
3831
- }
3832
3950
  _watchField(field) {
3833
3951
  let fieldOptions = this._fieldOptions(field);
3834
- this._cleaner(up.on(field, fieldOptions.event, () => this._check(fieldOptions)));
3952
+ let eventType = fieldOptions.event;
3953
+ return up.on(field, eventType, (event) => this._check(event, fieldOptions));
3835
3954
  }
3836
3955
  _abort() {
3837
3956
  this._scheduledValues = null;
@@ -3856,7 +3975,7 @@ up.FieldWatcher = class FieldWatcher {
3856
3975
  return;
3857
3976
  if (this._currentTimer)
3858
3977
  return;
3859
- if (!this._scope.isConnected)
3978
+ if (!up.fragment.isAlive(this._region))
3860
3979
  return;
3861
3980
  let callbackOptions = u.omit(this._scheduledFieldOptions, ['event', 'delay']);
3862
3981
  const diff = this._changedValues(this._processedValues, this._scheduledValues);
@@ -3901,20 +4020,141 @@ up.FieldWatcher = class FieldWatcher {
3901
4020
  _readFieldValues() {
3902
4021
  return up.Params.fromContainer(this._root).toObject();
3903
4022
  }
3904
- _check(fieldOptions = {}) {
4023
+ _check(event, fieldOptions = {}) {
4024
+ up.log.putsEvent(event);
3905
4025
  const values = this._readFieldValues();
3906
4026
  if (this._isNewValues(values)) {
3907
4027
  this._scheduleValues(values, fieldOptions);
3908
4028
  }
3909
4029
  }
3910
- _onFormReset() {
3911
- u.task(() => this._check());
4030
+ _onFormReset(event) {
4031
+ u.task(() => this._check(event));
3912
4032
  }
3913
4033
  };
3914
4034
 
3915
4035
 
3916
4036
  /***/ }),
3917
- /* 41 */
4037
+ /* 43 */
4038
+ /***/ (() => {
4039
+
4040
+ const u = up.util;
4041
+ const e = up.element;
4042
+ const BUILTIN_SWITCH_EFFECTS = [
4043
+ { attr: 'up-hide-for', toggle(target, active) { e.toggle(target, !active); } },
4044
+ { attr: 'up-show-for', toggle(target, active) { e.toggle(target, active); } },
4045
+ { attr: 'up-disable-for', toggle(target, active) { up.form.setDisabled(target, active); } },
4046
+ { attr: 'up-enable-for', toggle(target, active) { up.form.setDisabled(target, !active); } },
4047
+ ];
4048
+ up.Switcher = class Switcher {
4049
+ constructor(root) {
4050
+ this._root = root;
4051
+ this._switcheeSelector = root.getAttribute('up-switch') || up.fail("No switch target given for %o", root);
4052
+ this._regionSelector = root.getAttribute('up-switch-region');
4053
+ }
4054
+ start() {
4055
+ this._switchRegion();
4056
+ return u.sequence(this._trackFieldChanges(), this._trackNewSwitchees());
4057
+ }
4058
+ _trackFieldChanges() {
4059
+ let callback = () => this._onFieldChanged();
4060
+ return up.migrate.watchForSwitch?.(this._root, callback)
4061
+ || up.watch(this._root, { logPrefix: '[up-switch]' }, callback);
4062
+ }
4063
+ _trackNewSwitchees() {
4064
+ let filter = (matches) => {
4065
+ let scope = this._scope;
4066
+ return u.filter(matches, (match) => scope.contains(match));
4067
+ };
4068
+ let onSwitcheeAdded = (switchee) => this._switchSwitchee(switchee);
4069
+ return up.fragment.trackSelector(this._switcheeSelector, { filter }, onSwitcheeAdded);
4070
+ }
4071
+ _onFieldChanged() {
4072
+ this._switchRegion();
4073
+ }
4074
+ _switchRegion() {
4075
+ const fieldTokens = this._buildFieldTokens();
4076
+ for (let switchee of this._findSwitchees()) {
4077
+ this._switchSwitchee(switchee, fieldTokens);
4078
+ }
4079
+ }
4080
+ _switchSwitchee(switchee, fieldTokens = this._buildFieldTokens()) {
4081
+ let previousValues = switchee.upSwitchValues;
4082
+ if (!u.isEqual(previousValues, fieldTokens)) {
4083
+ switchee.upSwitchValues = fieldTokens;
4084
+ this._switchSwitcheeNow(switchee, fieldTokens);
4085
+ }
4086
+ }
4087
+ _switchSwitcheeNow(switchee, fieldTokens) {
4088
+ for (let { attr, toggle } of BUILTIN_SWITCH_EFFECTS) {
4089
+ let attrValue = switchee.getAttribute(attr);
4090
+ if (attrValue) {
4091
+ let activeTokens = this._parseSwitcheeTokens(attrValue);
4092
+ let isActive = u.intersect(fieldTokens, activeTokens).length > 0;
4093
+ toggle(switchee, isActive);
4094
+ }
4095
+ }
4096
+ let log = ['Switching %o', switchee];
4097
+ up.emit(switchee, 'up:form:switch', { field: this._root, tokens: fieldTokens, log });
4098
+ }
4099
+ _findSwitchees() {
4100
+ return up.fragment.subtree(this._scope, this._switcheeSelector);
4101
+ }
4102
+ get _scope() {
4103
+ if (this._regionSelector) {
4104
+ return up.fragment.get(this._regionSelector, { origin: this._root });
4105
+ }
4106
+ else {
4107
+ return up.form.getRegion(this._root);
4108
+ }
4109
+ }
4110
+ _parseSwitcheeTokens(str) {
4111
+ return u.getSimpleTokens(str, { json: true });
4112
+ }
4113
+ _buildFieldTokens() {
4114
+ let fields = up.form.fields(this._root);
4115
+ let field = fields[0];
4116
+ let value;
4117
+ let meta;
4118
+ if (field.matches('input[type=checkbox]')) {
4119
+ if (field.checked) {
4120
+ value = field.value;
4121
+ meta = ':checked';
4122
+ }
4123
+ else {
4124
+ meta = ':unchecked';
4125
+ }
4126
+ }
4127
+ else if (field.matches('input[type=radio]')) {
4128
+ let checkedButton = up.migrate.checkedRadioButtonForSwitch?.(field) || u.find(fields, 'checked');
4129
+ if (checkedButton) {
4130
+ meta = ':checked';
4131
+ value = checkedButton.value;
4132
+ }
4133
+ else {
4134
+ meta = ':unchecked';
4135
+ }
4136
+ }
4137
+ else {
4138
+ value = field.value;
4139
+ }
4140
+ const values = [];
4141
+ if (u.isPresent(value)) {
4142
+ values.push(value);
4143
+ values.push(':present');
4144
+ }
4145
+ else {
4146
+ values.push(':blank');
4147
+ }
4148
+ if (u.isPresent(meta)) {
4149
+ values.push(meta);
4150
+ }
4151
+ return values;
4152
+ }
4153
+ };
4154
+
4155
+
4156
+ /***/ }),
4157
+ /* 44 */
3918
4158
  /***/ (() => {
3919
4159
 
3920
4160
  const u = up.util;
@@ -3925,41 +4165,51 @@ up.FormValidator = class FormValidator {
3925
4165
  this._dirtySolutions = [];
3926
4166
  this._nextRenderTimer = null;
3927
4167
  this._rendering = false;
3928
- this._resetNextRenderPromise();
3929
4168
  this._honorAbort();
3930
4169
  }
4170
+ start() {
4171
+ let guard = (field) => this._isValidatingField(field);
4172
+ let callback = (field) => this._onFieldAdded(field);
4173
+ return up.form.trackFields(this._form, { guard }, callback);
4174
+ }
4175
+ _isValidatingField(field) {
4176
+ return field.closest('[up-validate]:not([up-validate=false])');
4177
+ }
4178
+ _onFieldAdded(field) {
4179
+ let eventType = up.form.validateOptions(field).event;
4180
+ return up.on(field, eventType, (event) => {
4181
+ up.log.putsEvent(event);
4182
+ up.error.muteUncriticalRejection(this.validate({ origin: field }));
4183
+ });
4184
+ }
3931
4185
  _honorAbort() {
3932
4186
  up.fragment.onAborted(this._form, (event) => this._onAborted(event));
3933
4187
  }
3934
4188
  _onAborted(event) {
3935
- if (this._dirtySolutions.length) {
3936
- this._dirtySolutions = [];
3937
- this._nextRenderPromise.reject(new up.Aborted(event.reason));
3938
- this._resetNextRenderPromise();
4189
+ let abortedError = new up.Aborted(event.reason);
4190
+ let solution;
4191
+ while (solution = this._dirtySolutions.shift()) {
4192
+ solution.deferred.reject(abortedError);
3939
4193
  }
3940
4194
  }
3941
- _resetNextRenderPromise() {
3942
- this._nextRenderPromise = u.newDeferred();
3943
- }
3944
- watchContainer(fieldOrForm) {
3945
- let { event } = this._originOptions(fieldOrForm);
3946
- let guard = () => up.fragment.isAlive(fieldOrForm);
3947
- let callback = () => up.error.muteUncriticalRejection(this.validate({ origin: fieldOrForm }));
3948
- up.on(fieldOrForm, event, { guard }, callback);
3949
- }
3950
4195
  validate(options = {}) {
3951
- let solutions = this._getSolutions(options);
3952
- this._dirtySolutions.push(...solutions);
4196
+ let newSolutions = this._getSolutions(options);
4197
+ this._dirtySolutions.push(...newSolutions);
3953
4198
  this._scheduleNextRender();
3954
- return this._nextRenderPromise;
4199
+ return newSolutions[0]?.deferred;
3955
4200
  }
3956
4201
  _getSolutions(options) {
3957
4202
  let solutions = this._getTargetSelectorSolutions(options)
3958
4203
  || this._getFieldSolutions(options)
3959
4204
  || this._getElementSolutions(options.origin);
4205
+ let deferred = u.newDeferred();
3960
4206
  for (let solution of solutions) {
3961
- solution.renderOptions = this._originOptions(solution.origin, options);
4207
+ let renderOptions = up.form.validateOptions(solution.origin, options);
4208
+ solution.batch = u.pluckKey(renderOptions, 'batch');
4209
+ solution.renderOptions = renderOptions;
4210
+ solution.destination = `${renderOptions.method} ${renderOptions.url}`;
3962
4211
  solution.target = up.fragment.resolveOrigin(solution.target, solution);
4212
+ solution.deferred = deferred;
3963
4213
  }
3964
4214
  return solutions;
3965
4215
  }
@@ -4011,9 +4261,6 @@ up.FormValidator = class FormValidator {
4011
4261
  return this._getTargetSelectorSolutions({ target, origin: field });
4012
4262
  }
4013
4263
  }
4014
- _originOptions(element, overrideOptions) {
4015
- return up.form.watchOptions(element, overrideOptions, { defaults: { event: 'change' } });
4016
- }
4017
4264
  _scheduleNextRender() {
4018
4265
  let solutionDelays = this._dirtySolutions.map((solution) => solution.renderOptions.delay);
4019
4266
  let shortestDelay = Math.min(...solutionDelays) || 0;
@@ -4033,33 +4280,53 @@ up.FormValidator = class FormValidator {
4033
4280
  return;
4034
4281
  if (this._nextRenderTimer)
4035
4282
  return;
4036
- let options = this._mergeRenderOptions(this._dirtySolutions);
4037
- this._dirtySolutions = [];
4283
+ let solutionsBatch = this._selectDirtySolutionsBatch();
4284
+ let renderOptions = this._mergeRenderOptions(solutionsBatch);
4038
4285
  this._rendering = true;
4039
- let renderingPromise = this._nextRenderPromise;
4040
- this._resetNextRenderPromise();
4041
4286
  try {
4042
- renderingPromise.resolve(up.render(options));
4043
- await renderingPromise;
4287
+ let renderPromise = up.render(renderOptions);
4288
+ for (let solution of solutionsBatch) {
4289
+ solution.deferred.resolve(renderPromise);
4290
+ }
4291
+ await renderPromise;
4044
4292
  }
4045
4293
  finally {
4046
4294
  this._rendering = false;
4047
4295
  this._renderDirtySolutions();
4048
4296
  }
4049
4297
  }
4298
+ _selectDirtySolutionsBatch() {
4299
+ let batch = [];
4300
+ let i = 0;
4301
+ while (i < this._dirtySolutions.length) {
4302
+ let solution = this._dirtySolutions[i];
4303
+ if (batch.length === 0 || this._canBatchSolutions(batch[0], solution)) {
4304
+ batch.push(solution);
4305
+ this._dirtySolutions.splice(i, 1);
4306
+ }
4307
+ else {
4308
+ i++;
4309
+ }
4310
+ }
4311
+ return batch;
4312
+ }
4313
+ _canBatchSolutions(s1, s2) {
4314
+ return s1.destination === s2.destination && s1.batch && s2.batch;
4315
+ }
4050
4316
  _mergeRenderOptions(dirtySolutions) {
4051
4317
  let dirtyOrigins = u.map(dirtySolutions, 'origin');
4052
4318
  let dirtyFields = u.flatMap(dirtyOrigins, up.form.fields);
4053
4319
  let dirtyNames = u.uniq(u.map(dirtyFields, 'name'));
4054
4320
  let dirtyRenderOptionsList = u.map(dirtySolutions, 'renderOptions');
4055
- let options = u.mergeDefined(...dirtyRenderOptionsList, up.form.destinationOptions(this._form));
4321
+ let formDestinationOptions = up.form.destinationOptions(this._form);
4322
+ let options = u.mergeDefined(formDestinationOptions, ...dirtyRenderOptionsList);
4056
4323
  options.target = u.map(dirtySolutions, 'target').join(', ');
4057
4324
  options.origin = this._form;
4058
4325
  options.focus ??= 'keep';
4059
4326
  options.failOptions = false;
4060
4327
  options.defaultMaybe = true;
4061
- options.params = up.Params.merge(options.params, ...u.map(dirtyRenderOptionsList, 'params'));
4062
- options.headers = u.merge(options.headers, ...u.map(dirtyRenderOptionsList, 'headers'));
4328
+ options.params = up.Params.merge(formDestinationOptions.params, ...u.map(dirtyRenderOptionsList, 'params'));
4329
+ options.headers = u.merge(formDestinationOptions.headers, ...u.map(dirtyRenderOptionsList, 'headers'));
4063
4330
  this._addValidateHeader(options.headers, dirtyNames);
4064
4331
  options.feedback = u.some(dirtyRenderOptionsList, 'feedback');
4065
4332
  options.data = undefined;
@@ -4087,27 +4354,29 @@ up.FormValidator = class FormValidator {
4087
4354
  value = ':unknown';
4088
4355
  headers[key] = value;
4089
4356
  }
4090
- static forElement(element) {
4091
- let form = up.form.get(element);
4092
- return form.upFormValidator ||= new this(form);
4093
- }
4094
4357
  };
4095
4358
 
4096
4359
 
4097
4360
  /***/ }),
4098
- /* 42 */
4361
+ /* 45 */
4099
4362
  /***/ (() => {
4100
4363
 
4101
4364
  up.FocusCapsule = class FocusCapsule {
4102
- constructor(element, target, cursorProps) {
4365
+ constructor(element, target) {
4103
4366
  this._element = element;
4104
4367
  this._target = target;
4105
- this._cursorProps = cursorProps;
4368
+ this._cursorProps = up.viewport.copyCursorProps(this._element);
4106
4369
  }
4107
4370
  wasLost() {
4108
- return document.activeElement !== this._element;
4371
+ return document.activeElement !== this._element && !this._voided;
4372
+ }
4373
+ autoVoid() {
4374
+ up.on('focusin', { once: true }, () => this._voided = true);
4109
4375
  }
4110
4376
  restore(layer, focusOptions) {
4377
+ if (!this.wasLost()) {
4378
+ return false;
4379
+ }
4111
4380
  let rediscoveredElement = up.fragment.get(this._target, { layer });
4112
4381
  if (rediscoveredElement) {
4113
4382
  up.viewport.copyCursorProps(this._cursorProps, rediscoveredElement);
@@ -4122,14 +4391,13 @@ up.FocusCapsule = class FocusCapsule {
4122
4391
  let target = up.fragment.tryToTarget(focusedElement);
4123
4392
  if (!target)
4124
4393
  return;
4125
- const cursorProps = up.viewport.copyCursorProps(focusedElement);
4126
- return new this(focusedElement, target, cursorProps);
4394
+ return new this(focusedElement, target);
4127
4395
  }
4128
4396
  };
4129
4397
 
4130
4398
 
4131
4399
  /***/ }),
4132
- /* 43 */
4400
+ /* 46 */
4133
4401
  /***/ (() => {
4134
4402
 
4135
4403
  const u = up.util;
@@ -4172,7 +4440,7 @@ up.FragmentProcessor = class FragmentProcessor extends up.Record {
4172
4440
  return this.processPrimitive(opt);
4173
4441
  }
4174
4442
  processArray(array) {
4175
- return u.find(array, opt => this.tryProcess(opt));
4443
+ return u.find(array, (opt) => this.tryProcess(opt));
4176
4444
  }
4177
4445
  resolveCondition(condition) {
4178
4446
  if (condition === 'main') {
@@ -4194,7 +4462,7 @@ up.FragmentProcessor = class FragmentProcessor extends up.Record {
4194
4462
 
4195
4463
 
4196
4464
  /***/ }),
4197
- /* 44 */
4465
+ /* 47 */
4198
4466
  /***/ (() => {
4199
4467
 
4200
4468
  const u = up.util;
@@ -4243,7 +4511,7 @@ up.FragmentFinder = class FragmentFinder {
4243
4511
 
4244
4512
 
4245
4513
  /***/ }),
4246
- /* 45 */
4514
+ /* 48 */
4247
4515
  /***/ (() => {
4248
4516
 
4249
4517
  const u = up.util;
@@ -4253,6 +4521,7 @@ up.FragmentFocus = class FragmentFocus extends up.FragmentProcessor {
4253
4521
  keys() {
4254
4522
  return super.keys().concat([
4255
4523
  'hash',
4524
+ 'focusVisible',
4256
4525
  'focusCapsule',
4257
4526
  'inputDevice',
4258
4527
  ]);
@@ -4296,9 +4565,7 @@ up.FragmentFocus = class FragmentFocus extends up.FragmentProcessor {
4296
4565
  return this._focusElement(match);
4297
4566
  }
4298
4567
  _restoreLostFocus() {
4299
- if (this._wasFocusLost()) {
4300
- return this.focusCapsule?.restore(this.layer, PREVENT_SCROLL_OPTIONS);
4301
- }
4568
+ return this.focusCapsule?.restore(this.layer, PREVENT_SCROLL_OPTIONS);
4302
4569
  }
4303
4570
  _restorePreviousFocusForLocation() {
4304
4571
  return up.viewport.restoreFocus({ layer: this.layer });
@@ -4311,7 +4578,12 @@ up.FragmentFocus = class FragmentFocus extends up.FragmentProcessor {
4311
4578
  }
4312
4579
  _focusElement(element) {
4313
4580
  if (element) {
4314
- up.focus(element, { force: true, ...PREVENT_SCROLL_OPTIONS, inputDevice: this.inputDevice });
4581
+ up.focus(element, {
4582
+ force: true,
4583
+ ...PREVENT_SCROLL_OPTIONS,
4584
+ inputDevice: this.inputDevice,
4585
+ focusVisible: this.focusVisible,
4586
+ });
4315
4587
  return true;
4316
4588
  }
4317
4589
  }
@@ -4328,7 +4600,7 @@ up.FragmentFocus = class FragmentFocus extends up.FragmentProcessor {
4328
4600
 
4329
4601
 
4330
4602
  /***/ }),
4331
- /* 46 */
4603
+ /* 49 */
4332
4604
  /***/ (() => {
4333
4605
 
4334
4606
  const e = up.element;
@@ -4414,6 +4686,11 @@ up.FragmentPolling = class FragmentPolling {
4414
4686
  if (this._state !== 'started') {
4415
4687
  return;
4416
4688
  }
4689
+ if (!up.fragment.isAlive(this._fragment)) {
4690
+ this._stop();
4691
+ up.puts('[up-poll]', 'Stopped polling a detached fragment');
4692
+ return;
4693
+ }
4417
4694
  if (!this._isFragmentVisible()) {
4418
4695
  up.puts('[up-poll]', 'Will not poll hidden fragment');
4419
4696
  return;
@@ -4483,7 +4760,7 @@ up.FragmentPolling = class FragmentPolling {
4483
4760
 
4484
4761
 
4485
4762
  /***/ }),
4486
- /* 47 */
4763
+ /* 50 */
4487
4764
  /***/ (() => {
4488
4765
 
4489
4766
  const u = up.util;
@@ -4500,8 +4777,10 @@ up.FragmentScrolling = class FragmentScrolling extends up.FragmentProcessor {
4500
4777
  }
4501
4778
  processPrimitive(opt) {
4502
4779
  switch (opt) {
4503
- case 'reset':
4504
- return this._reset();
4780
+ case 'top':
4781
+ return this._scrollTo(0);
4782
+ case 'bottom':
4783
+ return this._scrollTo(99999999);
4505
4784
  case 'layer':
4506
4785
  return this._revealLayer();
4507
4786
  case 'main':
@@ -4536,9 +4815,8 @@ up.FragmentScrolling = class FragmentScrolling extends up.FragmentProcessor {
4536
4815
  _revealLayer() {
4537
4816
  return this._revealElement(this.layer.getBoxElement());
4538
4817
  }
4539
- _reset() {
4540
- up.viewport.resetScroll({ ...this.attributes(), around: this.fragment });
4541
- return true;
4818
+ _scrollTo(position) {
4819
+ return up.viewport.scrollTo(position, { ...this.attributes(), around: this.fragment });
4542
4820
  }
4543
4821
  _restore() {
4544
4822
  return up.viewport.restoreScroll({ ...this.attributes(), around: this.fragment });
@@ -4547,7 +4825,7 @@ up.FragmentScrolling = class FragmentScrolling extends up.FragmentProcessor {
4547
4825
 
4548
4826
 
4549
4827
  /***/ }),
4550
- /* 48 */
4828
+ /* 51 */
4551
4829
  /***/ (() => {
4552
4830
 
4553
4831
  const e = up.element;
@@ -4783,7 +5061,7 @@ up.Layer = class Layer extends up.Record {
4783
5061
  up.history.push(location);
4784
5062
  }
4785
5063
  if (!this.opening) {
4786
- this.emit('up:layer:location:changed', { location });
5064
+ this.emit('up:layer:location:changed', { location, log: false });
4787
5065
  }
4788
5066
  }
4789
5067
  }
@@ -4813,7 +5091,7 @@ up.Layer = class Layer extends up.Record {
4813
5091
 
4814
5092
 
4815
5093
  /***/ }),
4816
- /* 49 */
5094
+ /* 52 */
4817
5095
  /***/ (() => {
4818
5096
 
4819
5097
  var _a;
@@ -4913,7 +5191,7 @@ up.Layer.Overlay = (_a = class Overlay extends up.Layer {
4913
5191
  }
4914
5192
  if (this._supportsDismissMethod('outside')) {
4915
5193
  if (this.viewportElement) {
4916
- up.on(this.viewportElement, 'up:click', event => {
5194
+ up.on(this.viewportElement, 'up:click', (event) => {
4917
5195
  if (event.target === this.viewportElement) {
4918
5196
  this._onOutsideClicked(event, true);
4919
5197
  }
@@ -4929,17 +5207,17 @@ up.Layer.Overlay = (_a = class Overlay extends up.Layer {
4929
5207
  }
4930
5208
  }
4931
5209
  if (this._supportsDismissMethod('key')) {
4932
- this.unbindEscapePressed = up.event.onEscape(event => this.onEscapePressed(event));
5210
+ this.unbindEscapePressed = up.event.onEscape((event) => this.onEscapePressed(event));
4933
5211
  }
4934
- this.registerClickCloser('up-accept', (value, closeOptions) => {
5212
+ this.registerAttrCloser('up-accept', (value, closeOptions) => {
4935
5213
  this.accept(value, closeOptions);
4936
5214
  });
4937
- this.registerClickCloser('up-dismiss', (value, closeOptions) => {
5215
+ this.registerAttrCloser('up-dismiss', (value, closeOptions) => {
4938
5216
  this.dismiss(value, closeOptions);
4939
5217
  });
4940
5218
  up.migrate.registerLayerCloser?.(this);
4941
- this._registerEventCloser(this.acceptEvent, this.accept);
4942
- this._registerEventCloser(this.dismissEvent, this.dismiss);
5219
+ this._registerExternalEventCloser(this.acceptEvent, this.accept);
5220
+ this._registerExternalEventCloser(this.dismissEvent, this.dismiss);
4943
5221
  this.on('up:click', 'label[for]', (event, label) => this._onLabelClicked(event, label));
4944
5222
  }
4945
5223
  _onLabelClicked(event, label) {
@@ -4974,26 +5252,38 @@ up.Layer.Overlay = (_a = class Overlay extends up.Layer {
4974
5252
  }
4975
5253
  }
4976
5254
  }
4977
- registerClickCloser(attribute, closeFn) {
4978
- let selector = `[${attribute}]`;
4979
- this.on('up:click', selector, function (event) {
5255
+ registerAttrCloser(attribute, closeFn) {
5256
+ this._registerClickCloser(attribute, closeFn);
5257
+ this._registerSubmitCloser(attribute, closeFn);
5258
+ }
5259
+ _registerClickCloser(attribute, closeFn) {
5260
+ this.on('up:click', `[${attribute}]:not(form)`, (event, link) => {
5261
+ up.event.halt(event, { log: true });
5262
+ const value = e.jsonAttr(link, attribute);
5263
+ this._onAttrCloserActivated(link, value, closeFn);
5264
+ });
5265
+ }
5266
+ _registerSubmitCloser(attribute, closeFn) {
5267
+ this.on('submit', `[${attribute}]`, (event, form) => {
4980
5268
  up.event.halt(event, { log: true });
4981
- const origin = event.target.closest(selector);
4982
- const value = e.jsonAttr(origin, attribute);
4983
- const closeOptions = { origin };
4984
- const parser = new up.OptionsParser(origin, closeOptions);
4985
- parser.booleanOrString('animation');
4986
- parser.string('easing');
4987
- parser.number('duration');
4988
- parser.string('confirm');
4989
- up.error.muteUncriticalSync(() => closeFn(value, closeOptions));
5269
+ const value = up.Params.fromForm(form);
5270
+ this._onAttrCloserActivated(form, value, closeFn);
4990
5271
  });
4991
5272
  }
4992
- _registerEventCloser(eventTypes, closeFn) {
5273
+ _onAttrCloserActivated(origin, value, closeFn) {
5274
+ const closeOptions = { origin };
5275
+ const parser = new up.OptionsParser(origin, closeOptions);
5276
+ parser.booleanOrString('animation');
5277
+ parser.string('easing');
5278
+ parser.number('duration');
5279
+ parser.string('confirm');
5280
+ up.error.muteUncriticalSync(() => closeFn(value, closeOptions));
5281
+ }
5282
+ _registerExternalEventCloser(eventTypes, closeFn) {
4993
5283
  if (!eventTypes) {
4994
5284
  return;
4995
5285
  }
4996
- return this.on(eventTypes, event => {
5286
+ return this.on(eventTypes, (event) => {
4997
5287
  event.preventDefault();
4998
5288
  up.error.muteUncriticalSync(() => closeFn.call(this, event, { response: event.response }));
4999
5289
  });
@@ -5096,11 +5386,12 @@ up.Layer.Overlay = (_a = class Overlay extends up.Layer {
5096
5386
  'closeEasing',
5097
5387
  'trapFocus',
5098
5388
  ],
5389
+ _a.UNSET_VISUALS = u.spanObject(_a.VISUAL_KEYS, undefined),
5099
5390
  _a);
5100
5391
 
5101
5392
 
5102
5393
  /***/ }),
5103
- /* 50 */
5394
+ /* 53 */
5104
5395
  /***/ (() => {
5105
5396
 
5106
5397
  up.Layer.OverlayWithTether = class OverlayWithTether extends up.Layer.Overlay {
@@ -5139,7 +5430,7 @@ up.Layer.OverlayWithTether = class OverlayWithTether extends up.Layer.Overlay {
5139
5430
 
5140
5431
 
5141
5432
  /***/ }),
5142
- /* 51 */
5433
+ /* 54 */
5143
5434
  /***/ (() => {
5144
5435
 
5145
5436
  up.Layer.OverlayWithViewport = class OverlayWithViewport extends up.Layer.Overlay {
@@ -5168,7 +5459,7 @@ up.Layer.OverlayWithViewport = class OverlayWithViewport extends up.Layer.Overla
5168
5459
 
5169
5460
 
5170
5461
  /***/ }),
5171
- /* 52 */
5462
+ /* 55 */
5172
5463
  /***/ (() => {
5173
5464
 
5174
5465
  var _a;
@@ -5214,7 +5505,7 @@ up.Layer.Root = (_a = class Root extends up.Layer {
5214
5505
 
5215
5506
 
5216
5507
  /***/ }),
5217
- /* 53 */
5508
+ /* 56 */
5218
5509
  /***/ (() => {
5219
5510
 
5220
5511
  var _a;
@@ -5225,7 +5516,7 @@ up.Layer.Modal = (_a = class Modal extends up.Layer.OverlayWithViewport {
5225
5516
 
5226
5517
 
5227
5518
  /***/ }),
5228
- /* 54 */
5519
+ /* 57 */
5229
5520
  /***/ (() => {
5230
5521
 
5231
5522
  var _a;
@@ -5236,7 +5527,7 @@ up.Layer.Popup = (_a = class Popup extends up.Layer.OverlayWithTether {
5236
5527
 
5237
5528
 
5238
5529
  /***/ }),
5239
- /* 55 */
5530
+ /* 58 */
5240
5531
  /***/ (() => {
5241
5532
 
5242
5533
  var _a;
@@ -5247,7 +5538,7 @@ up.Layer.Drawer = (_a = class Drawer extends up.Layer.OverlayWithViewport {
5247
5538
 
5248
5539
 
5249
5540
  /***/ }),
5250
- /* 56 */
5541
+ /* 59 */
5251
5542
  /***/ (() => {
5252
5543
 
5253
5544
  var _a;
@@ -5258,7 +5549,7 @@ up.Layer.Cover = (_a = class Cover extends up.Layer.OverlayWithViewport {
5258
5549
 
5259
5550
 
5260
5551
  /***/ }),
5261
- /* 57 */
5552
+ /* 60 */
5262
5553
  /***/ (() => {
5263
5554
 
5264
5555
  var _a;
@@ -5274,7 +5565,7 @@ up.LayerLookup = (_a = class LayerLookup {
5274
5565
  this._values = u.getSimpleTokens(options.layer);
5275
5566
  }
5276
5567
  all() {
5277
- let results = u.flatMap(this._values, value => this._resolveValue(value));
5568
+ let results = u.flatMap(this._values, (value) => this._resolveValue(value));
5278
5569
  results = u.compact(results);
5279
5570
  results = u.uniq(results);
5280
5571
  return results;
@@ -5289,7 +5580,7 @@ up.LayerLookup = (_a = class LayerLookup {
5289
5580
  }
5290
5581
  _forElement(element) {
5291
5582
  element = e.get(element);
5292
- return u.find(this._stack.reversed(), layer => layer.contains(element));
5583
+ return u.find(this._stack.reversed(), (layer) => layer.contains(element));
5293
5584
  }
5294
5585
  _forIndex(value) {
5295
5586
  return this._stack.at(value);
@@ -5371,7 +5662,7 @@ up.LayerLookup = (_a = class LayerLookup {
5371
5662
 
5372
5663
 
5373
5664
  /***/ }),
5374
- /* 58 */
5665
+ /* 61 */
5375
5666
  /***/ (() => {
5376
5667
 
5377
5668
  const u = up.util;
@@ -5485,7 +5776,7 @@ up.LayerStack = class LayerStack {
5485
5776
 
5486
5777
 
5487
5778
  /***/ }),
5488
- /* 59 */
5779
+ /* 62 */
5489
5780
  /***/ (() => {
5490
5781
 
5491
5782
  const u = up.util;
@@ -5519,7 +5810,7 @@ up.LinkCurrentURLs = class LinkCurrentURLs {
5519
5810
 
5520
5811
 
5521
5812
  /***/ }),
5522
- /* 60 */
5813
+ /* 63 */
5523
5814
  /***/ (() => {
5524
5815
 
5525
5816
  const u = up.util;
@@ -5560,13 +5851,15 @@ up.LinkFollowIntent = class LinkFollowIntent {
5560
5851
  }
5561
5852
  _runCallback(event) {
5562
5853
  up.log.putsEvent(event);
5854
+ if (!up.fragment.isAlive(this._link))
5855
+ return;
5563
5856
  this._callback({ onRequestKnown: (request) => this._lastRequest = request });
5564
5857
  }
5565
5858
  };
5566
5859
 
5567
5860
 
5568
5861
  /***/ }),
5569
- /* 61 */
5862
+ /* 64 */
5570
5863
  /***/ (() => {
5571
5864
 
5572
5865
  const u = up.util;
@@ -5608,7 +5901,7 @@ up.MotionController = class MotionController {
5608
5901
  }
5609
5902
  _expandFinishRequest(elements) {
5610
5903
  if (elements) {
5611
- return u.flatMap(elements, el => e.list(el.closest(this._selector), el.querySelectorAll(this._selector)));
5904
+ return u.flatMap(elements, (el) => e.list(el.closest(this._selector), el.querySelectorAll(this._selector)));
5612
5905
  }
5613
5906
  else {
5614
5907
  return document.querySelectorAll(this._selector);
@@ -5662,10 +5955,9 @@ up.MotionController = class MotionController {
5662
5955
 
5663
5956
 
5664
5957
  /***/ }),
5665
- /* 62 */
5958
+ /* 65 */
5666
5959
  /***/ (() => {
5667
5960
 
5668
- const u = up.util;
5669
5961
  const e = up.element;
5670
5962
  up.NonceableCallback = class NonceableCallback {
5671
5963
  constructor(script, nonce) {
@@ -5719,37 +6011,11 @@ up.NonceableCallback = class NonceableCallback {
5719
6011
  }
5720
6012
  }
5721
6013
  }
5722
- _allowedBy(allowedNonces) {
5723
- return this.nonce && u.contains(allowedNonces, this.nonce);
5724
- }
5725
- static adoptNonces(element, allowedNonces) {
5726
- if (!allowedNonces?.length) {
5727
- return;
5728
- }
5729
- const getPageNonce = u.memoize(up.protocol.cspNonce);
5730
- u.each(up.script.config.nonceableAttributes, (attribute) => {
5731
- let matches = e.subtree(element, `[${attribute}^="nonce-"]`);
5732
- u.each(matches, (match) => {
5733
- let attributeValue = match.getAttribute(attribute);
5734
- let callback = this.fromString(attributeValue);
5735
- let warn = (message, ...args) => up.log.warn('up.render()', `Cannot use callback [${attribute}="${attributeValue}"]: ${message}`, ...args);
5736
- if (!callback._allowedBy(allowedNonces)) {
5737
- return warn("Callback's CSP nonce (%o) does not match response header (%o)", callback.nonce, allowedNonces);
5738
- }
5739
- let pageNonce = getPageNonce();
5740
- if (!pageNonce) {
5741
- return warn("Current page's CSP nonce is unknown");
5742
- }
5743
- callback.nonce = pageNonce;
5744
- match.setAttribute(attribute, callback.toString());
5745
- });
5746
- });
5747
- }
5748
6014
  };
5749
6015
 
5750
6016
 
5751
6017
  /***/ }),
5752
- /* 63 */
6018
+ /* 66 */
5753
6019
  /***/ (() => {
5754
6020
 
5755
6021
  const e = up.element;
@@ -5771,7 +6037,7 @@ up.OverlayFocus = class OverlayFocus {
5771
6037
  'aria-modal': this._trapFocus.toString()
5772
6038
  });
5773
6039
  if (this._trapFocus) {
5774
- this._untrapFocus = up.on('focusin', event => this._onFocus(event));
6040
+ this._untrapFocus = up.on('focusin', (event) => this._onFocus(event));
5775
6041
  this._focusTrapBefore = e.affix(this._focusElement, 'beforebegin', 'up-focus-trap[tabindex=0]');
5776
6042
  this._focusTrapAfter = e.affix(this._focusElement, 'afterend', 'up-focus-trap[tabindex=0]');
5777
6043
  }
@@ -5822,7 +6088,7 @@ up.OverlayFocus = class OverlayFocus {
5822
6088
 
5823
6089
 
5824
6090
  /***/ }),
5825
- /* 64 */
6091
+ /* 67 */
5826
6092
  /***/ (() => {
5827
6093
 
5828
6094
  const u = up.util;
@@ -5959,7 +6225,7 @@ up.Params = class Params {
5959
6225
  this.entries = u.reject(this.entries, this._matchEntryFn(name));
5960
6226
  }
5961
6227
  _matchEntryFn(name) {
5962
- return entry => entry.name === name;
6228
+ return (entry) => entry.name === name;
5963
6229
  }
5964
6230
  get(name) {
5965
6231
  if (this._isArrayKey(name)) {
@@ -6056,7 +6322,7 @@ up.Params = class Params {
6056
6322
 
6057
6323
 
6058
6324
  /***/ }),
6059
- /* 65 */
6325
+ /* 68 */
6060
6326
  /***/ (() => {
6061
6327
 
6062
6328
  const u = up.util;
@@ -6127,7 +6393,7 @@ up.Preview = class Preview {
6127
6393
  }
6128
6394
  disable(...args) {
6129
6395
  let [element] = this._parseMutatorArgs(args, 'val');
6130
- this.undo(up.form.disable(element));
6396
+ this.undo(up.form.disableTemp(element));
6131
6397
  }
6132
6398
  insert(...args) {
6133
6399
  let [reference, position = 'beforeend', tempValue] = this._parseMutatorArgs(args, 'val', u.isAdjacentPosition, 'val');
@@ -6190,7 +6456,7 @@ up.Preview = class Preview {
6190
6456
 
6191
6457
 
6192
6458
  /***/ }),
6193
- /* 66 */
6459
+ /* 69 */
6194
6460
  /***/ (() => {
6195
6461
 
6196
6462
  const e = up.element;
@@ -6240,7 +6506,7 @@ up.ProgressBar = class ProgressBar {
6240
6506
 
6241
6507
 
6242
6508
  /***/ }),
6243
- /* 67 */
6509
+ /* 70 */
6244
6510
  /***/ (() => {
6245
6511
 
6246
6512
  const u = up.util;
@@ -6336,7 +6602,7 @@ up.RenderOptions = (function () {
6336
6602
  return u.merge(preprocessedOptions.defaults, lateDefaults, preprocessedOptions);
6337
6603
  }
6338
6604
  function assertContentGiven(options) {
6339
- if (!u.some(CONTENT_KEYS, contentKey => u.isGiven(options[contentKey]))) {
6605
+ if (!u.some(CONTENT_KEYS, (contentKey) => u.isGiven(options[contentKey]))) {
6340
6606
  if (options.defaultToEmptyContent) {
6341
6607
  options.content = '';
6342
6608
  }
@@ -6386,7 +6652,7 @@ up.RenderOptions = (function () {
6386
6652
 
6387
6653
 
6388
6654
  /***/ }),
6389
- /* 68 */
6655
+ /* 71 */
6390
6656
  /***/ (() => {
6391
6657
 
6392
6658
  up.RenderResult = class RenderResult extends up.Record {
@@ -6434,7 +6700,7 @@ up.RenderResult = class RenderResult extends up.Record {
6434
6700
 
6435
6701
 
6436
6702
  /***/ }),
6437
- /* 69 */
6703
+ /* 72 */
6438
6704
  /***/ (() => {
6439
6705
 
6440
6706
  var _a;
@@ -6461,6 +6727,8 @@ up.Request = (_a = class Request extends up.Record {
6461
6727
  'failMode',
6462
6728
  'failContext',
6463
6729
  'origin',
6730
+ 'originLayer',
6731
+ 'originMode',
6464
6732
  'builtAt',
6465
6733
  'wrapMethod',
6466
6734
  'contentType',
@@ -6473,30 +6741,31 @@ up.Request = (_a = class Request extends up.Record {
6473
6741
  ];
6474
6742
  }
6475
6743
  defaults() {
6744
+ let config = up.network.config;
6476
6745
  return {
6477
6746
  state: 'new',
6478
6747
  abortable: true,
6479
6748
  headers: {},
6480
- timeout: up.network.config.timeout,
6749
+ timeout: config.timeout,
6481
6750
  builtAt: new Date(),
6482
6751
  previews: [],
6752
+ wrapMethod: config.wrapMethod,
6483
6753
  };
6484
6754
  }
6485
6755
  constructor(options) {
6486
6756
  super(options);
6487
6757
  this.params = new up.Params(this.params);
6488
- if (this.wrapMethod == null) {
6489
- this.wrapMethod = up.network.config.wrapMethod;
6490
- }
6491
6758
  this._normalize();
6492
6759
  if ((this.target || this.layer || this.origin) && !options.basic) {
6493
6760
  const layerLookupOptions = { origin: this.origin };
6494
6761
  this.layer = up.layer.get(this.layer, layerLookupOptions);
6495
- this.failLayer = up.layer.get(this.failLayer, layerLookupOptions);
6496
6762
  this.context ||= this.layer.context || {};
6497
- this.failContext ||= this.failLayer?.context || {};
6498
6763
  this.mode ||= this.layer.mode;
6764
+ this.failLayer = up.layer.get(this.failLayer, layerLookupOptions);
6765
+ this.failContext ||= this.failLayer?.context || {};
6499
6766
  this.failMode ||= this.failLayer?.mode;
6767
+ this.originLayer ||= up.layer.get(this.origin) || up.layer.current;
6768
+ this.originMode ||= this.originLayer?.mode;
6500
6769
  }
6501
6770
  this.bindLayer = options.bindLayer || this.layer;
6502
6771
  this._fragments = options.fragments;
@@ -6543,8 +6812,9 @@ up.Request = (_a = class Request extends up.Record {
6543
6812
  u.task(() => {
6544
6813
  this.layer = undefined;
6545
6814
  this.failLayer = undefined;
6546
- this._bindLayer = undefined;
6815
+ this.bindLayer = undefined;
6547
6816
  this.origin = undefined;
6817
+ this.originLayer = undefined;
6548
6818
  this._fragments = undefined;
6549
6819
  this._bindFragments = undefined;
6550
6820
  });
@@ -6698,6 +6968,7 @@ up.Request = (_a = class Request extends up.Record {
6698
6968
  status: this.xhr.status,
6699
6969
  title: up.protocol.titleFromXHR(this.xhr),
6700
6970
  target: up.protocol.targetFromXHR(this.xhr),
6971
+ openLayer: up.protocol.openLayerFromXHR(this.xhr),
6701
6972
  acceptLayer: up.protocol.acceptLayerFromXHR(this.xhr),
6702
6973
  dismissLayer: up.protocol.dismissLayerFromXHR(this.xhr),
6703
6974
  eventPlans: up.protocol.eventPlansFromXHR(this.xhr),
@@ -6751,7 +7022,7 @@ up.Request = (_a = class Request extends up.Record {
6751
7022
  return this.headers[name];
6752
7023
  }
6753
7024
  _setAutoHeaders() {
6754
- for (let key of ['target', 'failTarget', 'mode', 'failMode', 'context', 'failContext']) {
7025
+ for (let key of ['target', 'failTarget', 'mode', 'failMode', 'context', 'failContext', 'originMode']) {
6755
7026
  this._setPropertyHeader(key);
6756
7027
  }
6757
7028
  let csrfHeader, csrfToken;
@@ -6806,13 +7077,13 @@ up.Request = (_a = class Request extends up.Record {
6806
7077
  }
6807
7078
  },
6808
7079
  (() => {
6809
- u.delegatePromise(_a.prototype, '_deferred');
7080
+ u.delegatePromise(_a.prototype, function () { return this._deferred; });
6810
7081
  })(),
6811
7082
  _a);
6812
7083
 
6813
7084
 
6814
7085
  /***/ }),
6815
- /* 70 */
7086
+ /* 73 */
6816
7087
  /***/ (() => {
6817
7088
 
6818
7089
  const u = up.util;
@@ -6954,14 +7225,14 @@ up.Request.Cache = class Cache {
6954
7225
  _isUsable(request) {
6955
7226
  return request.age < up.network.config.cacheEvictAge;
6956
7227
  }
6957
- get _size() {
7228
+ get currentSize() {
6958
7229
  return this._requests.length;
6959
7230
  }
6960
7231
  get _capacity() {
6961
7232
  return up.network.config.cacheSize;
6962
7233
  }
6963
7234
  _limitSize() {
6964
- for (let i = 0; i < (this._size - this._capacity); i++) {
7235
+ for (let i = 0; i < (this.currentSize - this._capacity); i++) {
6965
7236
  this._delete(this._requests[0]);
6966
7237
  }
6967
7238
  }
@@ -6977,7 +7248,7 @@ up.Request.Cache = class Cache {
6977
7248
 
6978
7249
 
6979
7250
  /***/ }),
6980
- /* 71 */
7251
+ /* 74 */
6981
7252
  /***/ (() => {
6982
7253
 
6983
7254
  const u = up.util;
@@ -6995,7 +7266,7 @@ up.Request.Queue = class Queue {
6995
7266
  }
6996
7267
  asap(request) {
6997
7268
  request.runQueuedCallbacks();
6998
- u.always(request, responseOrError => this._onRequestSettled(request, responseOrError));
7269
+ u.always(request, (responseOrError) => this._onRequestSettled(request, responseOrError));
6999
7270
  this._scheduleSlowTimer(request);
7000
7271
  this._queueRequest(request);
7001
7272
  queueMicrotask(() => this._poke());
@@ -7026,7 +7297,7 @@ up.Request.Queue = class Queue {
7026
7297
  this._queuedRequests.push(request);
7027
7298
  }
7028
7299
  _pluckNextRequest() {
7029
- let request = u.find(this._queuedRequests, request => !request.background);
7300
+ let request = u.find(this._queuedRequests, (request) => !request.background);
7030
7301
  request ||= this._queuedRequests[0];
7031
7302
  return u.remove(this._queuedRequests, request);
7032
7303
  }
@@ -7088,7 +7359,7 @@ up.Request.Queue = class Queue {
7088
7359
 
7089
7360
 
7090
7361
  /***/ }),
7091
- /* 72 */
7362
+ /* 75 */
7092
7363
  /***/ (() => {
7093
7364
 
7094
7365
  const u = up.util;
@@ -7127,7 +7398,7 @@ up.Request.FormRenderer = class FormRenderer {
7127
7398
 
7128
7399
 
7129
7400
  /***/ }),
7130
- /* 73 */
7401
+ /* 76 */
7131
7402
  /***/ (() => {
7132
7403
 
7133
7404
  var _a;
@@ -7198,7 +7469,7 @@ up.Request.XHRRenderer = (_a = class XHRRenderer {
7198
7469
 
7199
7470
 
7200
7471
  /***/ }),
7201
- /* 74 */
7472
+ /* 77 */
7202
7473
  /***/ (() => {
7203
7474
 
7204
7475
  const u = up.util;
@@ -7213,6 +7484,7 @@ up.Response = class Response extends up.Record {
7213
7484
  'xhr',
7214
7485
  'target',
7215
7486
  'title',
7487
+ 'openLayer',
7216
7488
  'acceptLayer',
7217
7489
  'dismissLayer',
7218
7490
  'eventPlans',
@@ -7227,7 +7499,7 @@ up.Response = class Response extends up.Record {
7227
7499
  defaults() {
7228
7500
  return {
7229
7501
  headers: {},
7230
- loadedAt: new Date()
7502
+ loadedAt: new Date(),
7231
7503
  };
7232
7504
  }
7233
7505
  get ok() {
@@ -7246,8 +7518,9 @@ up.Response = class Response extends up.Record {
7246
7518
  get contentType() {
7247
7519
  return this.header('Content-Type');
7248
7520
  }
7249
- get cspNonces() {
7250
- return up.protocol.cspNoncesFromHeader(this.header('Content-Security-Policy') || this.header('Content-Security-Policy-Report-Only'));
7521
+ get cspInfo() {
7522
+ let policy = this.header('Content-Security-Policy') || this.header('Content-Security-Policy-Report-Only');
7523
+ return up.protocol.cspInfoFromHeader(policy);
7251
7524
  }
7252
7525
  get lastModified() {
7253
7526
  let header = this.header('Last-Modified');
@@ -7276,15 +7549,15 @@ up.Response = class Response extends up.Record {
7276
7549
 
7277
7550
 
7278
7551
  /***/ }),
7279
- /* 75 */
7552
+ /* 78 */
7280
7553
  /***/ (() => {
7281
7554
 
7282
7555
  var _a;
7283
7556
  const u = up.util;
7284
7557
  const e = up.element;
7285
- const FULL_DOCUMENT_PATTERN = /^\s*<(html|!DOCTYPE)\b/i;
7558
+ const FULL_DOCUMENT_PATTERN = /^\s*(<!--[^-]*.*?-->\s*)*<(html|!DOCTYPE)\b/i;
7286
7559
  up.ResponseDoc = (_a = class ResponseDoc {
7287
- constructor({ document, fragment, content, target, origin, data, cspNonces, match }) {
7560
+ constructor({ document, fragment, content, target, origin, data, cspInfo, match }) {
7288
7561
  if (document) {
7289
7562
  this._parseDocument(document, origin, data);
7290
7563
  }
@@ -7294,7 +7567,7 @@ up.ResponseDoc = (_a = class ResponseDoc {
7294
7567
  else {
7295
7568
  this._parseContent(content || '', origin, target, data);
7296
7569
  }
7297
- this._cspNonces = cspNonces;
7570
+ this._cspInfo = cspInfo || {};
7298
7571
  if (origin) {
7299
7572
  let originSelector = up.fragment.tryToTarget(origin);
7300
7573
  if (originSelector) {
@@ -7323,9 +7596,6 @@ up.ResponseDoc = (_a = class ResponseDoc {
7323
7596
  this._document = this._buildFauxDocument(value);
7324
7597
  }
7325
7598
  }
7326
- _parseDocumentFromHTML(html) {
7327
- return e.createBrokenDocumentFromHTML(html);
7328
- }
7329
7599
  _parseFragment(value, origin, data) {
7330
7600
  let element = e.extractSingular(up.fragment.provideNodes(value, { origin, data }));
7331
7601
  this._document = this._buildFauxDocument(element);
@@ -7363,7 +7633,14 @@ up.ResponseDoc = (_a = class ResponseDoc {
7363
7633
  return this._fromHead(up.history.findMetaTags);
7364
7634
  }
7365
7635
  get assets() {
7366
- return this._fromHead(up.script.findAssets);
7636
+ return this._fromHead((head) => {
7637
+ let assets = up.script.findAssets(head);
7638
+ return u.map(assets, (asset) => {
7639
+ this._adoptNoncesInSubtree(asset);
7640
+ let clone = this._reviveElementAsClone(asset);
7641
+ return clone;
7642
+ });
7643
+ });
7367
7644
  }
7368
7645
  get lang() {
7369
7646
  if (this._isFullDocument) {
@@ -7415,21 +7692,43 @@ up.ResponseDoc = (_a = class ResponseDoc {
7415
7692
  throw new up.CannotMatch();
7416
7693
  }
7417
7694
  }
7695
+ _disableScriptsInSubtree(element) {
7696
+ let pageNonce = up.protocol.cspNonce();
7697
+ up.script.disableSubtree(element, (script) => !this._isScriptAllowed(script, pageNonce));
7698
+ }
7699
+ _isScriptAllowed(scriptElement, pageNonce) {
7700
+ let strategy = up.fragment.config.runScripts;
7701
+ if (strategy === true && this._cspInfo.declaration?.includes("'strict-dynamic'")) {
7702
+ return pageNonce && (pageNonce === scriptElement.nonce);
7703
+ }
7704
+ else {
7705
+ return u.evalOption(strategy, scriptElement);
7706
+ }
7707
+ }
7708
+ _reviveElementAsClone(element) {
7709
+ return e.revivedClone(element);
7710
+ }
7711
+ _reviveSubtreeInPlace(element) {
7712
+ if (this._document instanceof Document) {
7713
+ for (let brokenElement of e.subtree(element, ':is(noscript, script, audio, video):not(.up-keeping, .up-keeping *)')) {
7714
+ let clone = this._reviveElementAsClone(brokenElement);
7715
+ brokenElement.replaceWith(clone);
7716
+ }
7717
+ }
7718
+ }
7719
+ _adoptNoncesInSubtree(element) {
7720
+ up.script.adoptNoncesInSubtree(element, this._cspInfo.nonces);
7721
+ }
7418
7722
  commitElement(element) {
7419
7723
  if (this._document.contains(element)) {
7420
- if (!up.fragment.config.runScripts) {
7421
- up.script.disableSubtree(element);
7422
- }
7724
+ this._adoptNoncesInSubtree(element);
7725
+ this._disableScriptsInSubtree(element);
7423
7726
  element.remove();
7424
7727
  return true;
7425
7728
  }
7426
7729
  }
7427
7730
  finalizeElement(element) {
7428
- up.NonceableCallback.adoptNonces(element, this._cspNonces);
7429
- if (this._document instanceof Document) {
7430
- let brokenElements = e.subtree(element, ':is(noscript,script,audio,video):not(.up-keeping, .up-keeping *)');
7431
- u.each(brokenElements, e.fixParserDamage);
7432
- }
7731
+ this._reviveSubtreeInPlace(element);
7433
7732
  }
7434
7733
  },
7435
7734
  (() => {
@@ -7441,7 +7740,7 @@ up.ResponseDoc = (_a = class ResponseDoc {
7441
7740
 
7442
7741
 
7443
7742
  /***/ }),
7444
- /* 76 */
7743
+ /* 79 */
7445
7744
  /***/ (() => {
7446
7745
 
7447
7746
  const e = up.element;
@@ -7531,7 +7830,7 @@ up.RevealMotion = class RevealMotion {
7531
7830
 
7532
7831
 
7533
7832
  /***/ }),
7534
- /* 77 */
7833
+ /* 80 */
7535
7834
  /***/ (() => {
7536
7835
 
7537
7836
  const u = up.util;
@@ -7553,7 +7852,7 @@ up.Selector = class Selector {
7553
7852
  this._layers = up.layer.getAll(options);
7554
7853
  if (!this._layers.length)
7555
7854
  throw new up.CannotMatch(["Unknown layer: %o", options.layer]);
7556
- this._filters.push(match => u.some(this._layers, layer => layer.contains(match)));
7855
+ this._filters.push((match) => u.some(this._layers, (layer) => layer.contains(match)));
7557
7856
  expandTargetLayer = this._layers[0];
7558
7857
  }
7559
7858
  this._selectors = up.fragment.expandTargets(selector, { ...options, layer: expandTargetLayer });
@@ -7588,7 +7887,7 @@ up.Selector = class Selector {
7588
7887
  });
7589
7888
  }
7590
7889
  _passesFilter(element) {
7591
- return element && u.every(this._filters, filter => filter(element));
7890
+ return element && u.every(this._filters, (filter) => filter(element));
7592
7891
  }
7593
7892
  _filterOne(element) {
7594
7893
  return u.presence(element, this._passesFilter.bind(this));
@@ -7600,7 +7899,7 @@ up.Selector = class Selector {
7600
7899
 
7601
7900
 
7602
7901
  /***/ }),
7603
- /* 78 */
7902
+ /* 81 */
7604
7903
  /***/ (() => {
7605
7904
 
7606
7905
  const u = up.util;
@@ -7720,7 +8019,7 @@ up.Tether = class Tether {
7720
8019
 
7721
8020
 
7722
8021
  /***/ }),
7723
- /* 79 */
8022
+ /* 82 */
7724
8023
  /***/ (() => {
7725
8024
 
7726
8025
  const u = up.util;
@@ -7793,7 +8092,7 @@ up.URLPattern = class URLPattern {
7793
8092
 
7794
8093
 
7795
8094
  /***/ }),
7796
- /* 80 */
8095
+ /* 83 */
7797
8096
  /***/ (() => {
7798
8097
 
7799
8098
  up.framework = (function () {
@@ -7882,7 +8181,7 @@ up.boot = up.framework.boot;
7882
8181
 
7883
8182
 
7884
8183
  /***/ }),
7885
- /* 81 */
8184
+ /* 84 */
7886
8185
  /***/ (() => {
7887
8186
 
7888
8187
  up.event = (function () {
@@ -7934,9 +8233,8 @@ up.event = (function () {
7934
8233
  event.preventDefault();
7935
8234
  }
7936
8235
  const keyModifiers = ['metaKey', 'shiftKey', 'ctrlKey', 'altKey'];
7937
- function isUnmodified(event) {
7938
- return (u.isUndefined(event.button) || (event.button === 0)) &&
7939
- !u.some(keyModifiers, modifier => event[modifier]);
8236
+ function isModified(event) {
8237
+ return (event.button > 0) || u.some(keyModifiers, (modifier) => event[modifier]);
7940
8238
  }
7941
8239
  function isSyntheticClick(event) {
7942
8240
  return u.isMissing(event.clientX);
@@ -7957,7 +8255,7 @@ up.event = (function () {
7957
8255
  return newEvent;
7958
8256
  }
7959
8257
  function executeEmitAttr(event, element) {
7960
- if (!isUnmodified(event)) {
8258
+ if (isModified(event)) {
7961
8259
  return;
7962
8260
  }
7963
8261
  const eventType = e.attr(element, 'up-emit');
@@ -7986,7 +8284,7 @@ up.event = (function () {
7986
8284
  assertEmitted,
7987
8285
  onEscape,
7988
8286
  halt,
7989
- isUnmodified,
8287
+ isModified,
7990
8288
  isSyntheticClick,
7991
8289
  fork,
7992
8290
  keyModifiers,
@@ -7999,14 +8297,14 @@ up.emit = up.event.emit;
7999
8297
 
8000
8298
 
8001
8299
  /***/ }),
8002
- /* 82 */
8300
+ /* 85 */
8003
8301
  /***/ (() => {
8004
8302
 
8005
8303
  up.protocol = (function () {
8006
8304
  const u = up.util;
8007
8305
  const e = up.element;
8008
8306
  const headerize = function (camel) {
8009
- const header = camel.replace(/(^.|[A-Z])/g, char => '-' + char.toUpperCase());
8307
+ const header = camel.replace(/(^.|[A-Z])/g, (char) => '-' + char.toUpperCase());
8010
8308
  return 'X-Up' + header;
8011
8309
  };
8012
8310
  const extractHeader = function (xhr, shortHeader, parseFn = u.identity) {
@@ -8044,6 +8342,9 @@ up.protocol = (function () {
8044
8342
  function eventPlansFromXHR(xhr) {
8045
8343
  return extractHeader(xhr, 'events', u.parseRelaxedJSON);
8046
8344
  }
8345
+ function openLayerFromXHR(xhr) {
8346
+ return extractHeader(xhr, 'openLayer', u.parseRelaxedJSON);
8347
+ }
8047
8348
  function acceptLayerFromXHR(xhr) {
8048
8349
  return extractHeader(xhr, 'acceptLayer', u.parseRelaxedJSON);
8049
8350
  }
@@ -8079,21 +8380,26 @@ up.protocol = (function () {
8079
8380
  function cspNonce() {
8080
8381
  return u.evalOption(config.cspNonce);
8081
8382
  }
8082
- function cspNoncesFromHeader(cspHeader) {
8083
- let nonces = [];
8383
+ const NONCE_PATTERN = /'nonce-([^']+)'/g;
8384
+ function findNonces(cspPart) {
8385
+ let matches = cspPart.matchAll(NONCE_PATTERN);
8386
+ return u.map(matches, '1');
8387
+ }
8388
+ function cspInfoFromHeader(cspHeader) {
8389
+ let results = {};
8084
8390
  if (cspHeader) {
8085
- let parts = cspHeader.split(/\s*;\s*/);
8086
- for (let part of parts) {
8087
- if (part.indexOf('script-src') === 0) {
8088
- let noncePattern = /'nonce-([^']+)'/g;
8089
- let match;
8090
- while (match = noncePattern.exec(part)) {
8091
- nonces.push(match[1]);
8092
- }
8391
+ let declarations = cspHeader.split(/\s*;\s*/);
8392
+ for (let declaration of declarations) {
8393
+ let directive = declaration.match(/^(script|default)-src:/)?.[1];
8394
+ if (directive) {
8395
+ results[directive] = {
8396
+ declaration: declaration,
8397
+ nonces: findNonces(declaration)
8398
+ };
8093
8399
  }
8094
8400
  }
8095
8401
  }
8096
- return nonces;
8402
+ return results.script || results.default || {};
8097
8403
  }
8098
8404
  function wrapMethod(method, params) {
8099
8405
  params.add(config.methodParam, method);
@@ -8105,6 +8411,7 @@ up.protocol = (function () {
8105
8411
  titleFromXHR,
8106
8412
  targetFromXHR,
8107
8413
  methodFromXHR,
8414
+ openLayerFromXHR,
8108
8415
  acceptLayerFromXHR,
8109
8416
  contextFromXHR,
8110
8417
  dismissLayerFromXHR,
@@ -8118,13 +8425,13 @@ up.protocol = (function () {
8118
8425
  initialRequestMethod,
8119
8426
  headerize,
8120
8427
  wrapMethod,
8121
- cspNoncesFromHeader,
8428
+ cspInfoFromHeader,
8122
8429
  };
8123
8430
  })();
8124
8431
 
8125
8432
 
8126
8433
  /***/ }),
8127
- /* 83 */
8434
+ /* 86 */
8128
8435
  /***/ (() => {
8129
8436
 
8130
8437
  up.log = (function () {
@@ -8137,24 +8444,26 @@ up.log = (function () {
8137
8444
  }
8138
8445
  const printToWarn = (...args) => printToStream('warn', ...args);
8139
8446
  const printToError = (...args) => printToStream('error', ...args);
8140
- function printToStream(stream, trace, message, ...args) {
8141
- printToStreamStyled(stream, trace, '', message, ...args);
8447
+ function printToStream(stream, prefix, message, ...args) {
8448
+ printToStreamStyled(stream, prefix, '', message, ...args);
8142
8449
  }
8143
- function printToStreamStyled(stream, trace, customStyles, message, ...args) {
8450
+ function printToStreamStyled(stream, prefix, customStyles, message, ...args) {
8144
8451
  if (message) {
8145
8452
  if (config.format) {
8146
- 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);
8453
+ 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);
8147
8454
  }
8148
8455
  else {
8149
- console[stream](`[${trace}] ${u.sprintf(message, ...args)}`);
8456
+ console[stream](`[${prefix}] ${u.sprintf(message, ...args)}`);
8150
8457
  }
8151
8458
  }
8152
8459
  }
8460
+ let lastPrintedUserEvent;
8153
8461
  function printUserEvent(event) {
8154
- if (config.enabled) {
8155
- event = event.originalEvent || event;
8462
+ if (config.enabled && lastPrintedUserEvent !== event) {
8463
+ lastPrintedUserEvent = event;
8464
+ let originalEvent = event.originalEvent || event;
8156
8465
  let color = '#5566cc';
8157
- printToStreamStyled('log', event.type, `color: white; border-color: ${color}; background-color: ${color}`, 'Interaction on %o', event.target);
8466
+ printToStreamStyled('log', originalEvent.type, `color: white; border-color: ${color}; background-color: ${color}`, 'Interaction on %o', originalEvent.target);
8158
8467
  }
8159
8468
  }
8160
8469
  function printBanner() {
@@ -8205,7 +8514,7 @@ up.warn = up.log.warn;
8205
8514
 
8206
8515
 
8207
8516
  /***/ }),
8208
- /* 84 */
8517
+ /* 87 */
8209
8518
  /***/ (() => {
8210
8519
 
8211
8520
  up.script = (function () {
@@ -8387,16 +8696,41 @@ up.script = (function () {
8387
8696
  up.event.assertEmitted('up:assets:changed', { oldAssets, newAssets, renderOptions });
8388
8697
  }
8389
8698
  }
8390
- function disableScript(scriptElement) {
8391
- scriptElement.type = 'up-disabled-script';
8699
+ function disableScriptsInSubtree(root, guard = () => true) {
8700
+ for (let script of findScripts(root)) {
8701
+ if (guard(script)) {
8702
+ script.type = 'up-disabled-script';
8703
+ }
8704
+ }
8392
8705
  }
8393
- function disableScriptsInSubtree(root) {
8394
- let selector = config.selector('scriptSelectors');
8395
- u.each(e.subtree(root, selector), disableScript);
8706
+ function findScripts(root, selectorSuffix = '') {
8707
+ let selector = config.selector('scriptSelectors') + selectorSuffix;
8708
+ return e.subtree(root, selector);
8396
8709
  }
8397
8710
  function isScript(value) {
8398
8711
  return config.matches(value, 'scriptSelectors');
8399
8712
  }
8713
+ function adoptNoncesInSubtree(root, responseNonces) {
8714
+ let pageNonce = up.protocol.cspNonce();
8715
+ if (!responseNonces?.length || !pageNonce)
8716
+ return;
8717
+ for (let script of findScripts(root, '[nonce]')) {
8718
+ if (responseNonces.includes(script.nonce)) {
8719
+ script.nonce = pageNonce;
8720
+ }
8721
+ }
8722
+ for (let attribute of config.nonceableAttributes) {
8723
+ let matches = e.subtree(root, `[${attribute}^="nonce-"]`);
8724
+ for (let match of matches) {
8725
+ let attributeValue = match.getAttribute(attribute);
8726
+ let callback = up.NonceableCallback.fromString(attributeValue);
8727
+ if (responseNonces.includes(callback.nonce)) {
8728
+ callback.nonce = pageNonce;
8729
+ match.setAttribute(attribute, callback.toString());
8730
+ }
8731
+ }
8732
+ }
8733
+ }
8400
8734
  function reset() {
8401
8735
  registeredCompilers = u.filter(registeredCompilers, 'isDefault');
8402
8736
  registeredMacros = u.filter(registeredMacros, 'isDefault');
@@ -8414,6 +8748,7 @@ up.script = (function () {
8414
8748
  findAssets,
8415
8749
  assertAssetsOK,
8416
8750
  disableSubtree: disableScriptsInSubtree,
8751
+ adoptNoncesInSubtree,
8417
8752
  isScript,
8418
8753
  };
8419
8754
  })();
@@ -8426,7 +8761,7 @@ up.attribute = up.script.attrCompiler;
8426
8761
 
8427
8762
 
8428
8763
  /***/ }),
8429
- /* 85 */
8764
+ /* 88 */
8430
8765
  /***/ (() => {
8431
8766
 
8432
8767
  up.history = (function () {
@@ -8452,59 +8787,75 @@ up.history = (function () {
8452
8787
  }));
8453
8788
  let previousLocation;
8454
8789
  let nextPreviousLocation;
8790
+ let nextTrackOptions;
8791
+ let adoptedBases = new up.FIFOCache({ capacity: 100, normalizeKey: getBase });
8792
+ function isAdopted(location) {
8793
+ return !!adoptedBases.get(location);
8794
+ }
8455
8795
  function reset() {
8456
8796
  previousLocation = undefined;
8457
8797
  nextPreviousLocation = undefined;
8458
- trackCurrentLocation();
8798
+ nextTrackOptions = undefined;
8799
+ adoptedBases.clear();
8800
+ trackCurrentLocation({ reason: null, alreadyHandled: true });
8801
+ adopt();
8459
8802
  }
8460
8803
  function currentLocation() {
8461
8804
  return u.normalizeURL(location.href);
8462
8805
  }
8463
- function trackCurrentLocation() {
8464
- const url = currentLocation();
8465
- if (nextPreviousLocation !== url) {
8806
+ function trackCurrentLocation(trackOptions) {
8807
+ let { reason, alreadyHandled } = nextTrackOptions || trackOptions;
8808
+ let location = currentLocation();
8809
+ if (nextPreviousLocation !== location) {
8466
8810
  previousLocation = nextPreviousLocation;
8467
- nextPreviousLocation = url;
8811
+ nextPreviousLocation = location;
8812
+ if (reason === 'detect') {
8813
+ reason = (getBase(location) === getBase(previousLocation)) ? 'hash' : 'pop';
8814
+ }
8815
+ let willHandle = !alreadyHandled && isAdopted(location);
8816
+ let locationChangedEvent = up.event.build('up:location:changed', {
8817
+ reason,
8818
+ location,
8819
+ previousLocation,
8820
+ alreadyHandled,
8821
+ willHandle,
8822
+ log: `New location is ${location}`
8823
+ });
8824
+ up.migrate.prepareLocationChangedEvent?.(locationChangedEvent);
8825
+ if (reason) {
8826
+ up.emit(locationChangedEvent);
8827
+ reactToChange(locationChangedEvent);
8828
+ }
8468
8829
  }
8469
8830
  }
8470
- trackCurrentLocation();
8831
+ function splitLocation(location) {
8832
+ return location?.split(/(?=#)/) || [];
8833
+ }
8834
+ function getBase(location) {
8835
+ return splitLocation(location)[0];
8836
+ }
8471
8837
  function isLocation(url, options) {
8472
8838
  return u.matchURLs(url, location.href, { hash: true, ...options });
8473
8839
  }
8474
- function replace(location, options = {}) {
8475
- location = u.normalizeURL(location);
8476
- if (manipulate('replaceState', location) && (options.event !== false)) {
8477
- emitLocationChanged({ location, reason: 'replace', log: `Replaced state for ${location}` });
8478
- }
8479
- }
8480
- function push(location) {
8481
- location = u.normalizeURL(location);
8482
- if (!isLocation(location) && manipulate('pushState', location)) {
8483
- emitLocationChanged({ location, reason: 'push', log: `Advanced to location ${location}` });
8484
- }
8840
+ function replace(location, trackOptions) {
8841
+ placeAdoptedHistoryEntry('replaceState', location, trackOptions);
8485
8842
  }
8486
- function emitLocationChanged(props) {
8487
- let event = up.event.build('up:location:changed', props);
8488
- up.migrate?.renamedProperty?.(event, 'url', 'location');
8489
- up.emit(event);
8843
+ function push(location, trackOptions) {
8844
+ placeAdoptedHistoryEntry('pushState', location, trackOptions);
8490
8845
  }
8491
- function manipulate(method, url) {
8846
+ function placeAdoptedHistoryEntry(method, location, trackOptions) {
8847
+ adopt(location);
8492
8848
  if (config.enabled) {
8493
- const state = buildState();
8494
- window.history[method](state, '', url);
8495
- trackCurrentLocation();
8496
- return true;
8849
+ nextTrackOptions = trackOptions;
8850
+ history[method](null, '', location);
8851
+ nextTrackOptions = undefined;
8497
8852
  }
8498
8853
  }
8499
- function buildState() {
8500
- return { up: {} };
8854
+ function adopt(location = currentLocation()) {
8855
+ location = u.normalizeURL(location);
8856
+ adoptedBases.set(location, true);
8501
8857
  }
8502
- function restoreStateOnPop(state) {
8503
- if (!state?.up) {
8504
- up.puts('popstate', 'Ignoring a history state not owned by Unpoly');
8505
- return;
8506
- }
8507
- let location = currentLocation();
8858
+ function restoreLocation(location) {
8508
8859
  up.error.muteUncriticalRejection(up.render({
8509
8860
  guardEvent: up.event.build('up:location:restore', { location, log: `Restoring location ${location}` }),
8510
8861
  url: location,
@@ -8522,28 +8873,23 @@ up.history = (function () {
8522
8873
  focus: ['restore', 'auto'],
8523
8874
  }));
8524
8875
  }
8525
- function onPop(event) {
8526
- trackCurrentLocation();
8527
- let location = currentLocation();
8528
- emitLocationChanged({ location, reason: 'pop', log: `Navigated to history entry ${location}` });
8529
- up.viewport.saveFocus({ location: previousLocation });
8530
- up.viewport.saveScroll({ location: previousLocation });
8531
- restoreStateOnPop(event.state);
8532
- }
8533
- function register() {
8534
- window.addEventListener('popstate', onPop);
8535
- if (up.protocol.initialRequestMethod() === 'GET') {
8536
- replace(currentLocation(), { event: false });
8876
+ function reactToChange(event) {
8877
+ if (event.alreadyHandled) {
8878
+ return;
8537
8879
  }
8538
- }
8539
- up.on('up:framework:boot', function () {
8540
- if ('jasmine' in window) {
8541
- register();
8880
+ if (!event.willHandle) {
8881
+ up.puts('up.history', 'Ignoring history entry owned by foreign script');
8882
+ return;
8542
8883
  }
8543
- else {
8544
- setTimeout(register, 100);
8884
+ if (event.reason === 'pop') {
8885
+ up.viewport.saveFocus({ location: event.previousLocation });
8886
+ up.viewport.saveScroll({ location: event.previousLocation });
8887
+ restoreLocation(event.location);
8545
8888
  }
8546
- });
8889
+ else if (event.reason === 'hash') {
8890
+ up.viewport.revealHash(event.hash, { strong: true });
8891
+ }
8892
+ }
8547
8893
  function findMetaTags(head = document.head) {
8548
8894
  return head.querySelectorAll(config.selector('metaTagSelectors'));
8549
8895
  }
@@ -8565,6 +8911,62 @@ up.history = (function () {
8565
8911
  function updateLang(newLang) {
8566
8912
  e.setAttrPresence(e.root, 'lang', newLang, !!newLang);
8567
8913
  }
8914
+ function patchHistoryAPI() {
8915
+ const originalPushState = history.pushState;
8916
+ history.pushState = function (...args) {
8917
+ originalPushState.apply(this, args);
8918
+ trackCurrentLocation({ reason: 'push', alreadyHandled: true });
8919
+ };
8920
+ const originalReplaceState = history.replaceState;
8921
+ history.replaceState = function (...args) {
8922
+ originalReplaceState.apply(this, args);
8923
+ trackCurrentLocation({ reason: 'replace', alreadyHandled: true });
8924
+ };
8925
+ }
8926
+ function adoptInitialHistoryEntry() {
8927
+ if (up.protocol.initialRequestMethod() === 'GET') {
8928
+ adopt();
8929
+ }
8930
+ }
8931
+ up.on('up:framework:boot', function () {
8932
+ trackCurrentLocation({ reason: null, alreadyHandled: true });
8933
+ patchHistoryAPI();
8934
+ adoptInitialHistoryEntry();
8935
+ });
8936
+ up.on('DOMContentLoaded', function () {
8937
+ up.viewport.revealHash({ strong: true });
8938
+ u.task(up.viewport.revealHash);
8939
+ });
8940
+ up.on(window, 'hashchange, popstate', () => {
8941
+ trackCurrentLocation({ reason: 'detect', alreadyHandled: false });
8942
+ });
8943
+ function onJumpLinkClicked(event, link) {
8944
+ if (event.defaultPrevented)
8945
+ return;
8946
+ if (up.event.isModified(event))
8947
+ return;
8948
+ let [currentBase, currentHash] = splitLocation(up.layer.current.location);
8949
+ let [linkBase, linkHash] = splitLocation(u.normalizeURL(link));
8950
+ let verbatimHREF = link.getAttribute('href');
8951
+ let isJumpLink = (currentBase === linkBase) || verbatimHREF.startsWith('#');
8952
+ if (!isJumpLink)
8953
+ return;
8954
+ let behavior = link.getAttribute('up-scroll-behavior') ?? 'auto';
8955
+ let layer = up.layer.get(link);
8956
+ let revealFn = up.viewport.revealHashFn(linkHash, { layer, behavior });
8957
+ if (revealFn) {
8958
+ up.event.halt(event);
8959
+ up.log.putsEvent(event);
8960
+ if (linkHash !== currentHash && layer.showsLiveHistory()) {
8961
+ let newHREF = currentBase + linkHash;
8962
+ push(newHREF, { reason: 'hash', alreadyHandled: true });
8963
+ }
8964
+ revealFn();
8965
+ }
8966
+ else {
8967
+ }
8968
+ }
8969
+ up.on('up:click', 'a[href*="#"]', onJumpLinkClicked);
8568
8970
  up.macro('[up-back]', function (link) {
8569
8971
  if (previousLocation) {
8570
8972
  e.setMissingAttrs(link, {
@@ -8592,10 +8994,10 @@ up.history = (function () {
8592
8994
 
8593
8995
 
8594
8996
  /***/ }),
8595
- /* 86 */
8997
+ /* 89 */
8596
8998
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
8597
8999
 
8598
- __webpack_require__(87);
9000
+ __webpack_require__(90);
8599
9001
  const u = up.util;
8600
9002
  const e = up.element;
8601
9003
  up.fragment = (function () {
@@ -8640,6 +9042,7 @@ up.fragment = (function () {
8640
9042
  saveScroll: true,
8641
9043
  saveFocus: true,
8642
9044
  focus: 'keep',
9045
+ focusVisible: 'auto',
8643
9046
  abort: 'target',
8644
9047
  failOptions: true,
8645
9048
  feedback: true,
@@ -8654,7 +9057,7 @@ up.fragment = (function () {
8654
9057
  peel: true,
8655
9058
  },
8656
9059
  match: 'region',
8657
- runScripts: true,
9060
+ runScripts: false,
8658
9061
  autoHistoryTargets: [':main'],
8659
9062
  autoFocus: ['hash', 'autofocus', 'main-if-main', 'keep', 'target-if-lost'],
8660
9063
  autoScroll: ['hash', 'layer-if-main'],
@@ -8696,6 +9099,9 @@ up.fragment = (function () {
8696
9099
  return render({ ...options, navigate: true });
8697
9100
  });
8698
9101
  function emitFragmentInserted(element) {
9102
+ if (element.upInserted)
9103
+ return;
9104
+ element.upInserted = true;
8699
9105
  return up.emit(element, 'up:fragment:inserted', {
8700
9106
  log: ['Inserted fragment %o', element],
8701
9107
  });
@@ -8703,8 +9109,9 @@ up.fragment = (function () {
8703
9109
  function emitFragmentKeep(keepPlan) {
8704
9110
  let { oldElement, newElement: newFragment, newData, renderOptions } = keepPlan;
8705
9111
  const log = ['Keeping fragment %o', oldElement];
8706
- const callback = e.callbackAttr(oldElement, 'up-on-keep', { exposedKeys: ['newFragment', 'newData'] });
8707
- return up.emit(oldElement, 'up:fragment:keep', { newFragment, newData, renderOptions, log, callback });
9112
+ const callback = e.callbackAttr(keepPlan.oldElement, 'up-on-keep', { exposedKeys: ['newFragment', 'newData'] });
9113
+ const event = up.event.build('up:fragment:keep', { newFragment, newData, renderOptions });
9114
+ return up.emit(oldElement, event, { log, callback });
8708
9115
  }
8709
9116
  function emitFragmentDestroyed(fragment, options) {
8710
9117
  const log = options.log ?? ['Destroyed fragment %o', fragment];
@@ -8781,7 +9188,7 @@ up.fragment = (function () {
8781
9188
  }
8782
9189
  function markFragmentAsDestroying(element) {
8783
9190
  element.classList.add('up-destroying');
8784
- element.setAttribute('aria-hidden', 'true');
9191
+ element.setAttribute('inert', '');
8785
9192
  }
8786
9193
  function reload(...args) {
8787
9194
  const options = parseTargetAndOptions(args);
@@ -8838,8 +9245,8 @@ up.fragment = (function () {
8838
9245
  function toTarget(element, options) {
8839
9246
  return u.presence(element, u.isString) || tryToTarget(element, options) || cannotTarget(element);
8840
9247
  }
8841
- function isTargetable(element) {
8842
- return !!tryToTarget(element);
9248
+ function isTargetable(element, options) {
9249
+ return !!tryToTarget(element, options);
8843
9250
  }
8844
9251
  function untargetableMessage(element) {
8845
9252
  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.`;
@@ -9059,7 +9466,7 @@ up.fragment = (function () {
9059
9466
  if (steps.length < 2)
9060
9467
  return steps;
9061
9468
  let compressed = u.uniqBy(steps, 'oldElement');
9062
- compressed = u.reject(compressed, step => isContainedByRivalStep(compressed, step));
9469
+ compressed = u.reject(compressed, (step) => isContainedByRivalStep(compressed, step));
9063
9470
  return compressed;
9064
9471
  }
9065
9472
  function abort(...args) {
@@ -9156,6 +9563,11 @@ up.fragment = (function () {
9156
9563
  return () => up.destroy(tempElement);
9157
9564
  }
9158
9565
  }
9566
+ function trackSelector(...args) {
9567
+ let parsedArgs = u.args(args, 'val', 'options', 'callback');
9568
+ let tracker = new up.SelectorTracker(...parsedArgs);
9569
+ return tracker.start();
9570
+ }
9159
9571
  up.on('up:framework:boot', function () {
9160
9572
  const { documentElement } = document;
9161
9573
  documentElement.setAttribute('up-source', normalizeSource(location.href));
@@ -9208,6 +9620,7 @@ up.fragment = (function () {
9208
9620
  insertTemp,
9209
9621
  provideNodes,
9210
9622
  cloneTemplate,
9623
+ trackSelector,
9211
9624
  };
9212
9625
  })();
9213
9626
  up.reload = up.fragment.reload;
@@ -9220,7 +9633,7 @@ u.delegate(up, ['context'], () => up.layer.current);
9220
9633
 
9221
9634
 
9222
9635
  /***/ }),
9223
- /* 87 */
9636
+ /* 90 */
9224
9637
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
9225
9638
 
9226
9639
  "use strict";
@@ -9229,10 +9642,10 @@ __webpack_require__.r(__webpack_exports__);
9229
9642
 
9230
9643
 
9231
9644
  /***/ }),
9232
- /* 88 */
9645
+ /* 91 */
9233
9646
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
9234
9647
 
9235
- __webpack_require__(89);
9648
+ __webpack_require__(92);
9236
9649
  up.viewport = (function () {
9237
9650
  const u = up.util;
9238
9651
  const e = up.element;
@@ -9294,10 +9707,25 @@ up.viewport = (function () {
9294
9707
  doFocus(element, options);
9295
9708
  return element === document.activeElement;
9296
9709
  }
9297
- function revealHash(hash = location.hash, options) {
9298
- let match = firstHashTarget(hash, options);
9710
+ function revealHash(...args) {
9711
+ return revealHashFn(...args)?.();
9712
+ }
9713
+ function revealHashFn(hash = location.hash, { strong, layer, origin, behavior = 'instant' } = {}) {
9714
+ if (!hash)
9715
+ return;
9716
+ let match = firstHashTarget(hash, { layer, origin });
9299
9717
  if (match) {
9300
- return reveal(match, { top: true });
9718
+ return () => {
9719
+ let doReveal = () => reveal(match, { top: true, behavior });
9720
+ if (strong)
9721
+ u.task(doReveal);
9722
+ return doReveal();
9723
+ };
9724
+ }
9725
+ else if (hash === '#top') {
9726
+ return () => {
9727
+ return scrollTo(0, { behavior });
9728
+ };
9301
9729
  }
9302
9730
  }
9303
9731
  function allSelector() {
@@ -9369,7 +9797,7 @@ up.viewport = (function () {
9369
9797
  const { location } = options.layer;
9370
9798
  const locationScrollTops = options.layer.lastScrollTops.get(location);
9371
9799
  if (locationScrollTops) {
9372
- setScrollTops(viewports, locationScrollTops);
9800
+ setScrollPositions(viewports, locationScrollTops, 0);
9373
9801
  up.puts('up.viewport.restoreScroll()', 'Restored scroll positions to %o', locationScrollTops);
9374
9802
  return true;
9375
9803
  }
@@ -9415,14 +9843,16 @@ up.viewport = (function () {
9415
9843
  }
9416
9844
  return [viewports, options];
9417
9845
  }
9418
- function resetScroll(...args) {
9419
- const [viewports, _options] = parseOptions(args);
9420
- setScrollTops(viewports, {});
9846
+ function scrollTo(position, ...args) {
9847
+ const [viewports, options] = parseOptions(args);
9848
+ setScrollPositions(viewports, {}, position, options.behavior);
9849
+ return true;
9421
9850
  }
9422
- function setScrollTops(viewports, tops) {
9851
+ function setScrollPositions(viewports, tops, defaultTop, behavior = 'instant') {
9423
9852
  for (let viewport of viewports) {
9424
9853
  const key = scrollTopKey(viewport);
9425
- viewport.scrollTop = tops[key] || 0;
9854
+ const top = tops[key] || defaultTop;
9855
+ viewport.scrollTo({ top, behavior });
9426
9856
  }
9427
9857
  }
9428
9858
  function absolutize(element, options = {}) {
@@ -9463,7 +9893,8 @@ up.viewport = (function () {
9463
9893
  };
9464
9894
  }
9465
9895
  function firstHashTarget(hash, options = {}) {
9466
- if (hash = pureHash(hash)) {
9896
+ hash = pureHash(hash);
9897
+ if (hash) {
9467
9898
  const selector = [
9468
9899
  e.idSelector(hash),
9469
9900
  'a' + e.attrSelector('name', hash)
@@ -9491,22 +9922,10 @@ up.viewport = (function () {
9491
9922
  }
9492
9923
  return to;
9493
9924
  }
9494
- document.addEventListener('DOMContentLoaded', function () {
9495
- revealHash();
9496
- u.task(revealHash);
9497
- });
9498
- up.on(window, 'hashchange', () => revealHash());
9499
- up.on('up:click', 'a[href^="#"]', function (event, link) {
9500
- if (link.hash !== location.hash)
9501
- return;
9502
- if (up.link.isFollowable(link))
9503
- return;
9504
- if (revealHash(link.hash))
9505
- up.event.halt(event);
9506
- });
9507
9925
  return {
9508
9926
  reveal,
9509
9927
  revealHash,
9928
+ revealHashFn,
9510
9929
  firstHashTarget,
9511
9930
  config,
9512
9931
  get: closest,
@@ -9519,7 +9938,7 @@ up.viewport = (function () {
9519
9938
  rootScrollbarWidth,
9520
9939
  saveScroll,
9521
9940
  restoreScroll,
9522
- resetScroll,
9941
+ scrollTo,
9523
9942
  saveFocus,
9524
9943
  restoreFocus,
9525
9944
  absolutize,
@@ -9536,7 +9955,7 @@ up.reveal = up.viewport.reveal;
9536
9955
 
9537
9956
 
9538
9957
  /***/ }),
9539
- /* 89 */
9958
+ /* 92 */
9540
9959
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
9541
9960
 
9542
9961
  "use strict";
@@ -9545,27 +9964,22 @@ __webpack_require__.r(__webpack_exports__);
9545
9964
 
9546
9965
 
9547
9966
  /***/ }),
9548
- /* 90 */
9967
+ /* 93 */
9549
9968
  /***/ (() => {
9550
9969
 
9551
9970
  up.motion = (function () {
9552
9971
  const u = up.util;
9553
9972
  const e = up.element;
9554
- let namedAnimations = {};
9555
- let namedTransitions = {};
9556
9973
  const motionController = new up.MotionController('motion');
9557
9974
  const config = new up.Config(() => ({
9558
9975
  duration: 175,
9559
9976
  easing: 'ease',
9560
9977
  enabled: !matchMedia('(prefers-reduced-motion: reduce)').matches
9561
9978
  }));
9562
- function pickDefault(registry) {
9563
- return u.pickBy(registry, 'isDefault');
9564
- }
9979
+ let namedAnimations = new up.Registry('animation', findAnimationFn);
9980
+ let namedTransitions = new up.Registry('transition', findTransitionFn);
9565
9981
  function reset() {
9566
9982
  motionController.reset();
9567
- namedAnimations = pickDefault(namedAnimations);
9568
- namedTransitions = pickDefault(namedTransitions);
9569
9983
  }
9570
9984
  function isEnabled() {
9571
9985
  return config.enabled;
@@ -9605,9 +10019,6 @@ up.motion = (function () {
9605
10019
  options.easing ??= config.easing;
9606
10020
  options.duration ??= config.duration;
9607
10021
  }
9608
- function findNamedAnimation(name) {
9609
- return namedAnimations[name] || up.fail("Unknown animation %o", name);
9610
- }
9611
10022
  function finish(element) {
9612
10023
  return motionController.finish(element);
9613
10024
  }
@@ -9658,27 +10069,21 @@ up.motion = (function () {
9658
10069
  return Promise.resolve();
9659
10070
  }
9660
10071
  }
9661
- function findTransitionFn(object) {
9662
- if (isNone(object)) {
10072
+ function findTransitionFn(value) {
10073
+ if (isNone(value)) {
9663
10074
  return undefined;
9664
10075
  }
9665
- else if (u.isFunction(object)) {
9666
- return object;
10076
+ else if (u.isFunction(value)) {
10077
+ return value;
9667
10078
  }
9668
- else if (u.isArray(object)) {
9669
- return composeTransitionFn(...object);
10079
+ else if (u.isArray(value)) {
10080
+ return composeTransitionFn(...value);
9670
10081
  }
9671
- else if (u.isString(object)) {
9672
- let namedTransition;
9673
- if (object.indexOf('/') >= 0) {
9674
- return composeTransitionFn(...object.split('/'));
9675
- }
9676
- else if (namedTransition = namedTransitions[object]) {
9677
- return findTransitionFn(namedTransition);
9678
- }
10082
+ else if (u.isString(value) && value.includes('/')) {
10083
+ return composeTransitionFn(...value.split('/'));
9679
10084
  }
9680
10085
  else {
9681
- up.fail("Unknown transition %o", object);
10086
+ return namedTransitions.get(value);
9682
10087
  }
9683
10088
  }
9684
10089
  function composeTransitionFn(oldAnimation, newAnimation) {
@@ -9691,21 +10096,18 @@ up.motion = (function () {
9691
10096
  ]);
9692
10097
  }
9693
10098
  }
9694
- function findAnimationFn(object) {
9695
- if (isNone(object)) {
10099
+ function findAnimationFn(value) {
10100
+ if (isNone(value)) {
9696
10101
  return undefined;
9697
10102
  }
9698
- else if (u.isFunction(object)) {
9699
- return object;
9700
- }
9701
- else if (u.isString(object)) {
9702
- return findNamedAnimation(object);
10103
+ else if (u.isFunction(value)) {
10104
+ return value;
9703
10105
  }
9704
- else if (u.isOptions(object)) {
9705
- return (element, options) => animateNow(element, object, options);
10106
+ else if (u.isOptions(value)) {
10107
+ return (element, options) => animateNow(element, value, options);
9706
10108
  }
9707
10109
  else {
9708
- up.fail('Unknown animation %o', object);
10110
+ return namedAnimations.get(value);
9709
10111
  }
9710
10112
  }
9711
10113
  const swapElementsDirectly = up.mockable(function (oldElement, newElement) {
@@ -9720,16 +10122,6 @@ up.motion = (function () {
9720
10122
  parser.number('duration');
9721
10123
  return options;
9722
10124
  }
9723
- function registerTransition(name, transition) {
9724
- const fn = findTransitionFn(transition);
9725
- fn.isDefault = up.framework.evaling;
9726
- namedTransitions[name] = fn;
9727
- }
9728
- function registerAnimation(name, animation) {
9729
- const fn = findAnimationFn(animation);
9730
- fn.isDefault = up.framework.evaling;
9731
- namedAnimations[name] = fn;
9732
- }
9733
10125
  up.on('up:framework:boot', function () {
9734
10126
  if (!isEnabled()) {
9735
10127
  up.puts('up.motion', 'Animations are disabled');
@@ -9739,7 +10131,7 @@ up.motion = (function () {
9739
10131
  return !animationOrTransition || animationOrTransition === 'none';
9740
10132
  }
9741
10133
  function registerOpacityAnimation(name, from, to) {
9742
- registerAnimation(name, function (element, options) {
10134
+ namedAnimations.put(name, function (element, options) {
9743
10135
  element.style.opacity = 0;
9744
10136
  e.setStyle(element, { opacity: from });
9745
10137
  return animateNow(element, { opacity: to }, options);
@@ -9760,12 +10152,12 @@ up.motion = (function () {
9760
10152
  function registerMoveAnimations(direction, boxToTransform) {
9761
10153
  const animationToName = `move-to-${direction}`;
9762
10154
  const animationFromName = `move-from-${direction}`;
9763
- registerAnimation(animationToName, function (element, options) {
10155
+ namedAnimations.put(animationToName, function (element, options) {
9764
10156
  const box = untranslatedBox(element);
9765
10157
  const transform = boxToTransform(box);
9766
10158
  return animateNow(element, transform, options);
9767
10159
  });
9768
- registerAnimation(animationFromName, function (element, options) {
10160
+ namedAnimations.put(animationFromName, function (element, options) {
9769
10161
  const box = untranslatedBox(element);
9770
10162
  const transform = boxToTransform(box);
9771
10163
  e.setStyle(element, transform);
@@ -9788,19 +10180,19 @@ up.motion = (function () {
9788
10180
  const travelDistance = up.viewport.rootWidth() - box.left;
9789
10181
  return translateCSS(travelDistance, 0);
9790
10182
  });
9791
- registerTransition('cross-fade', ['fade-out', 'fade-in']);
9792
- registerTransition('move-left', ['move-to-left', 'move-from-right']);
9793
- registerTransition('move-right', ['move-to-right', 'move-from-left']);
9794
- registerTransition('move-up', ['move-to-top', 'move-from-bottom']);
9795
- registerTransition('move-down', ['move-to-bottom', 'move-from-top']);
10183
+ namedTransitions.put('cross-fade', ['fade-out', 'fade-in']);
10184
+ namedTransitions.put('move-left', ['move-to-left', 'move-from-right']);
10185
+ namedTransitions.put('move-right', ['move-to-right', 'move-from-left']);
10186
+ namedTransitions.put('move-up', ['move-to-top', 'move-from-bottom']);
10187
+ namedTransitions.put('move-down', ['move-to-bottom', 'move-from-top']);
9796
10188
  up.on('up:framework:reset', reset);
9797
10189
  return {
9798
10190
  morph,
9799
10191
  animate,
9800
10192
  finish,
9801
10193
  finishCount() { return motionController.finishCount; },
9802
- transition: registerTransition,
9803
- animation: registerAnimation,
10194
+ transition: namedTransitions.put,
10195
+ animation: namedAnimations.put,
9804
10196
  config,
9805
10197
  isEnabled,
9806
10198
  isNone,
@@ -9816,10 +10208,10 @@ up.animate = up.motion.animate;
9816
10208
 
9817
10209
 
9818
10210
  /***/ }),
9819
- /* 91 */
10211
+ /* 94 */
9820
10212
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
9821
10213
 
9822
- __webpack_require__(92);
10214
+ __webpack_require__(95);
9823
10215
  const u = up.util;
9824
10216
  up.network = (function () {
9825
10217
  const config = new up.Config(() => ({
@@ -9831,7 +10223,7 @@ up.network = (function () {
9831
10223
  lateDelay: 400,
9832
10224
  fail(response) { return (response.status < 200 || response.status > 299) && response.status !== 304; },
9833
10225
  autoCache(request) { return request.isSafe(); },
9834
- expireCache(request, _response) { return !request.isSafe(); },
10226
+ expireCache(request) { return !request.isSafe(); },
9835
10227
  evictCache: false,
9836
10228
  progressBar: true,
9837
10229
  timeout: 90000,
@@ -9858,6 +10250,8 @@ up.network = (function () {
9858
10250
  return options;
9859
10251
  }
9860
10252
  function processRequest(request) {
10253
+ cache.expire(request.expireCache ?? u.evalOption(config.expireCache, request) ?? false);
10254
+ cache.evict(request.evictCache ?? u.evalOption(config.evictCache, request) ?? false);
9861
10255
  useCachedRequest(request) || queueRequest(request);
9862
10256
  }
9863
10257
  function useCachedRequest(newRequest) {
@@ -9883,14 +10277,8 @@ up.network = (function () {
9883
10277
  request.onLoading = () => cache.reindex(request);
9884
10278
  }
9885
10279
  u.always(request, function (responseOrError) {
9886
- let expireCache = responseOrError.expireCache ?? request.expireCache ?? u.evalOption(config.expireCache, request, responseOrError);
9887
- if (expireCache) {
9888
- cache.expire(expireCache, { except: request });
9889
- }
9890
- let evictCache = responseOrError.evictCache ?? request.evictCache ?? u.evalOption(config.evictCache, request, responseOrError);
9891
- if (evictCache) {
9892
- cache.evict(evictCache, { except: request });
9893
- }
10280
+ cache.expire(responseOrError.expireCache ?? false, { except: request });
10281
+ cache.evict(responseOrError.evictCache ?? false, { except: request });
9894
10282
  let hasCacheEntry = cache.get(request);
9895
10283
  let isResponse = responseOrError instanceof up.Response;
9896
10284
  let isNetworkError = !isResponse;
@@ -9959,7 +10347,7 @@ up.cache = up.network.cache;
9959
10347
 
9960
10348
 
9961
10349
  /***/ }),
9962
- /* 92 */
10350
+ /* 95 */
9963
10351
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
9964
10352
 
9965
10353
  "use strict";
@@ -9968,10 +10356,10 @@ __webpack_require__.r(__webpack_exports__);
9968
10356
 
9969
10357
 
9970
10358
  /***/ }),
9971
- /* 93 */
10359
+ /* 96 */
9972
10360
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
9973
10361
 
9974
- __webpack_require__(94);
10362
+ __webpack_require__(97);
9975
10363
  const u = up.util;
9976
10364
  const e = up.element;
9977
10365
  up.layer = (function () {
@@ -10146,7 +10534,7 @@ up.layer = (function () {
10146
10534
  });
10147
10535
  }
10148
10536
  function anySelector() {
10149
- return u.map(LAYER_CLASSES, Class => Class.selector()).join();
10537
+ return u.map(LAYER_CLASSES, (Class) => Class.selector()).join();
10150
10538
  }
10151
10539
  function optionToString(option) {
10152
10540
  if (u.isString(option)) {
@@ -10216,7 +10604,7 @@ up.layer = (function () {
10216
10604
 
10217
10605
 
10218
10606
  /***/ }),
10219
- /* 94 */
10607
+ /* 97 */
10220
10608
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
10221
10609
 
10222
10610
  "use strict";
@@ -10225,14 +10613,16 @@ __webpack_require__.r(__webpack_exports__);
10225
10613
 
10226
10614
 
10227
10615
  /***/ }),
10228
- /* 95 */
10616
+ /* 98 */
10229
10617
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
10230
10618
 
10231
- __webpack_require__(96);
10619
+ __webpack_require__(99);
10232
10620
  up.link = (function () {
10233
10621
  const u = up.util;
10234
10622
  const e = up.element;
10623
+ let lastTouchstartTarget = null;
10235
10624
  let lastMousedownTarget = null;
10625
+ let lastInstantTarget = null;
10236
10626
  const ATTRS_WITH_LOCAL_HTML = '[up-content], [up-fragment], [up-document]';
10237
10627
  const ATTRS_SUGGESTING_FOLLOW = `${ATTRS_WITH_LOCAL_HTML}, [up-target], [up-layer], [up-transition], [up-preload]`;
10238
10628
  const DEFAULT_INTERACTIVE_ELEMENT = 'a[href], button';
@@ -10262,7 +10652,9 @@ up.link = (function () {
10262
10652
  }
10263
10653
  }
10264
10654
  function reset() {
10655
+ lastTouchstartTarget = null;
10265
10656
  lastMousedownTarget = null;
10657
+ lastInstantTarget = null;
10266
10658
  }
10267
10659
  const follow = up.mockable(function (link, options, parserOptions) {
10268
10660
  return up.render(followOptions(link, options, parserOptions));
@@ -10284,6 +10676,7 @@ up.link = (function () {
10284
10676
  parser.string('contentType');
10285
10677
  parser.booleanOrNumber('lateDelay');
10286
10678
  parser.number('timeout');
10679
+ parser.booleanOrString('fail');
10287
10680
  return options;
10288
10681
  }
10289
10682
  function followOptions(link, options, parserOptions) {
@@ -10292,7 +10685,6 @@ up.link = (function () {
10292
10685
  const parser = new up.OptionsParser(link, options, { fail: true, ...parserOptions });
10293
10686
  parser.include(parseRequestOptions);
10294
10687
  options.origin ||= link;
10295
- parser.boolean('fail');
10296
10688
  parser.boolean('navigate', { default: true });
10297
10689
  parser.string('confirm', { attr: ['up-confirm', 'data-confirm'] });
10298
10690
  parser.string('target');
@@ -10326,9 +10718,12 @@ up.link = (function () {
10326
10718
  parser.string('dismissEvent');
10327
10719
  parser.string('acceptLocation');
10328
10720
  parser.string('dismissLocation');
10329
- parser.booleanOrString('history');
10721
+ parser.booleanOrString('closeAnimation');
10722
+ parser.string('closeEasing');
10723
+ parser.number('closeDuration');
10330
10724
  parser.include(up.status.statusOptions);
10331
10725
  parser.booleanOrString('focus');
10726
+ parser.booleanOrString('focusVisible');
10332
10727
  parser.boolean('saveScroll');
10333
10728
  parser.boolean('saveFocus');
10334
10729
  parser.booleanOrString('scroll');
@@ -10358,9 +10753,9 @@ up.link = (function () {
10358
10753
  abortable: false,
10359
10754
  background: true,
10360
10755
  cache: true,
10756
+ ...options,
10361
10757
  ...up.RenderOptions.NO_INPUT_INTERFERENCE,
10362
10758
  ...up.RenderOptions.NO_PREVIEWS,
10363
- ...options,
10364
10759
  guardEvent,
10365
10760
  preload: true,
10366
10761
  });
@@ -10419,27 +10814,37 @@ up.link = (function () {
10419
10814
  }
10420
10815
  function convertClicks(layer) {
10421
10816
  layer.on('click', function (event, element) {
10422
- if (!up.event.isUnmodified(event)) {
10817
+ if (up.event.isModified(event)) {
10423
10818
  return;
10424
10819
  }
10425
- if (isInstant(element) && lastMousedownTarget) {
10820
+ if (isInstant(element) && lastInstantTarget === element) {
10426
10821
  up.event.halt(event);
10427
10822
  }
10428
10823
  else if (up.event.inputDevice === 'key' || up.event.isSyntheticClick(event) || (layer.wasHitByMouseEvent(event) && !didUserDragAway(event))) {
10429
10824
  forkEventAsUpClick(event);
10430
10825
  }
10431
- return lastMousedownTarget = null;
10826
+ lastMousedownTarget = null;
10827
+ lastInstantTarget = null;
10828
+ });
10829
+ layer.on('touchstart', { passive: true }, function (event, element) {
10830
+ lastTouchstartTarget = element;
10432
10831
  });
10433
10832
  layer.on('mousedown', function (event, element) {
10434
- if (!up.event.isUnmodified(event)) {
10833
+ if (up.event.isModified(event)) {
10435
10834
  return;
10436
10835
  }
10437
- lastMousedownTarget = event.target;
10438
- if (isInstant(element)) {
10836
+ lastMousedownTarget = element;
10837
+ if (isInstant(element) && !isLongPressPossible(event)) {
10838
+ lastInstantTarget = element;
10439
10839
  forkEventAsUpClick(event);
10440
10840
  }
10841
+ lastTouchstartTarget = null;
10441
10842
  });
10442
10843
  }
10844
+ function isLongPressPossible(mousedownEvent) {
10845
+ let mousedownTarget = mousedownEvent.target;
10846
+ return (lastTouchstartTarget === mousedownTarget) && mousedownTarget.closest('[href]');
10847
+ }
10443
10848
  function didUserDragAway(clickEvent) {
10444
10849
  return lastMousedownTarget && (lastMousedownTarget !== clickEvent.target);
10445
10850
  }
@@ -10535,7 +10940,7 @@ up.deferred = { load: up.link.loadDeferred };
10535
10940
 
10536
10941
 
10537
10942
  /***/ }),
10538
- /* 96 */
10943
+ /* 99 */
10539
10944
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
10540
10945
 
10541
10946
  "use strict";
@@ -10544,7 +10949,7 @@ __webpack_require__.r(__webpack_exports__);
10544
10949
 
10545
10950
 
10546
10951
  /***/ }),
10547
- /* 97 */
10952
+ /* 100 */
10548
10953
  /***/ (() => {
10549
10954
 
10550
10955
  up.form = (function () {
@@ -10557,12 +10962,14 @@ up.form = (function () {
10557
10962
  noSubmitSelectors: ['[up-submit=false]', '[target]', e.crossOriginSelector('action')],
10558
10963
  submitButtonSelectors: ['input[type=submit]', 'input[type=image]', 'button[type=submit]', 'button:not([type])'],
10559
10964
  genericButtonSelectors: ['input[type=button]', 'button[type=button]'],
10965
+ validateBatch: true,
10560
10966
  watchInputEvents: ['input', 'change'],
10561
10967
  watchInputDelay: 0,
10562
10968
  watchChangeEvents: ['change'],
10969
+ watchableEvents: ['input', 'change'],
10563
10970
  }));
10564
10971
  function fieldSelector(suffix = '') {
10565
- return config.fieldSelectors.map(field => field + suffix).join();
10972
+ return config.fieldSelectors.map((field) => field + suffix).join();
10566
10973
  }
10567
10974
  function isField(element) {
10568
10975
  return element.matches(fieldSelector());
@@ -10573,11 +10980,17 @@ up.form = (function () {
10573
10980
  if (root.matches('form[id]')) {
10574
10981
  const outsideFieldSelector = fieldSelector(e.attrSelector('form', root.getAttribute('id')));
10575
10982
  const outsideFields = up.fragment.all(outsideFieldSelector, { layer: root });
10576
- fields.push(...outsideFields);
10577
- fields = u.uniq(fields);
10983
+ fields = u.uniq([...fields, ...outsideFields]);
10578
10984
  }
10579
10985
  return fields;
10580
10986
  }
10987
+ function findFieldsAndButtons(container) {
10988
+ return [
10989
+ ...findFields(container),
10990
+ ...findSubmitButtons(container),
10991
+ ...findGenericButtons(container),
10992
+ ];
10993
+ }
10581
10994
  function findSubmitButtons(root) {
10582
10995
  return e.subtree(root, submitButtonSelector());
10583
10996
  }
@@ -10612,8 +11025,10 @@ up.form = (function () {
10612
11025
  }
10613
11026
  function watchOptions(field, options, parserOptions = {}) {
10614
11027
  options = u.options(options);
10615
- let parser = new up.OptionsParser(field, options, { ...parserOptions, closest: true, attrPrefix: 'up-watch-' });
10616
- parser.include(up.status.statusOptions);
11028
+ parserOptions.closest ??= true;
11029
+ parserOptions.attrPrefix ??= 'up-watch-';
11030
+ let parser = new up.OptionsParser(field, options, parserOptions);
11031
+ parser.include(up.status.statusOptions, parserOptions);
10617
11032
  parser.string('event');
10618
11033
  parser.number('delay');
10619
11034
  let config = up.form.config;
@@ -10627,15 +11042,20 @@ up.form = (function () {
10627
11042
  options.origin ||= field;
10628
11043
  return options;
10629
11044
  }
10630
- function disableContainer(container) {
10631
- let controls = [
10632
- ...findFields(container),
10633
- ...findSubmitButtons(container),
10634
- ...findGenericButtons(container),
10635
- ];
10636
- return u.sequence(u.map(controls, disableControl));
11045
+ function validateOptions(field, options, parserOptions = {}) {
11046
+ options = u.options(options);
11047
+ let parser = new up.OptionsParser(field, options, { ...parserOptions, closest: true, attrPrefix: 'up-validate-' });
11048
+ parser.string('url');
11049
+ parser.string('method', { normalize: u.normalizeMethod });
11050
+ parser.boolean('batch', { default: config.validateBatch });
11051
+ parser.include(watchOptions, { defaults: { event: 'change' } });
11052
+ return options;
11053
+ }
11054
+ function disableContainerTemp(container) {
11055
+ let controls = findFieldsAndButtons(container);
11056
+ return u.sequence(u.map(controls, disableControlTemp));
10637
11057
  }
10638
- function disableControl(control) {
11058
+ function disableControlTemp(control) {
10639
11059
  if (control.disabled)
10640
11060
  return;
10641
11061
  let focusFallback;
@@ -10650,7 +11070,7 @@ up.form = (function () {
10650
11070
  return () => { control.disabled = false; };
10651
11071
  }
10652
11072
  function getDisableContainers(disable, origin) {
10653
- let originScope = () => getScope(origin);
11073
+ let originScope = () => getRegion(origin);
10654
11074
  if (disable === true) {
10655
11075
  return [originScope()];
10656
11076
  }
@@ -10675,6 +11095,11 @@ up.form = (function () {
10675
11095
  }
10676
11096
  };
10677
11097
  }
11098
+ function setContainerDisabled(container, disabled) {
11099
+ for (let control of findFieldsAndButtons(container)) {
11100
+ control.disabled = disabled;
11101
+ }
11102
+ }
10678
11103
  function destinationOptions(form, options, parserOptions) {
10679
11104
  options = u.options(options);
10680
11105
  form = getForm(form);
@@ -10706,8 +11131,7 @@ up.form = (function () {
10706
11131
  root = up.element.get(root);
10707
11132
  callback ||= watchCallbackFromElement(root) || up.fail('No callback given for up.watch()');
10708
11133
  const watcher = new up.FieldWatcher(root, options, callback);
10709
- watcher.start();
10710
- return () => watcher.stop();
11134
+ return watcher.start();
10711
11135
  }
10712
11136
  function watchCallbackFromElement(element) {
10713
11137
  let rawCallback = element.getAttribute('up-watch');
@@ -10717,7 +11141,7 @@ up.form = (function () {
10717
11141
  }
10718
11142
  function autosubmit(target, options = {}) {
10719
11143
  const onChange = (_diff, renderOptions) => submit(target, renderOptions);
10720
- return watch(target, { ...options, batch: true }, onChange);
11144
+ return watch(target, { logPrefix: 'up.autosubmit()', ...options, batch: true }, onChange);
10721
11145
  }
10722
11146
  function getGroupSelectors() {
10723
11147
  return up.migrate.migratedFormGroupSelectors?.() || config.groupSelectors;
@@ -10745,7 +11169,8 @@ up.form = (function () {
10745
11169
  }
10746
11170
  function validate(...args) {
10747
11171
  let options = parseValidateArgs(...args);
10748
- let validator = up.FormValidator.forElement(options.origin);
11172
+ let form = getForm(options.origin);
11173
+ let validator = getFormValidator(form);
10749
11174
  return validator.validate(options);
10750
11175
  }
10751
11176
  function parseValidateArgs(originOrTarget, ...args) {
@@ -10758,88 +11183,20 @@ up.form = (function () {
10758
11183
  }
10759
11184
  return options;
10760
11185
  }
10761
- function switcherValues(field) {
10762
- let value;
10763
- let meta;
10764
- if (field.matches('input[type=checkbox]')) {
10765
- if (field.checked) {
10766
- value = field.value;
10767
- meta = ':checked';
10768
- }
10769
- else {
10770
- meta = ':unchecked';
10771
- }
10772
- }
10773
- else if (field.matches('input[type=radio]')) {
10774
- const form = getScope(field);
10775
- const groupName = field.getAttribute('name');
10776
- const checkedButton = form.querySelector(`input[type=radio]${e.attrSelector('name', groupName)}:checked`);
10777
- if (checkedButton) {
10778
- meta = ':checked';
10779
- value = checkedButton.value;
10780
- }
10781
- else {
10782
- meta = ':unchecked';
10783
- }
10784
- }
10785
- else {
10786
- value = field.value;
10787
- }
10788
- const values = [];
10789
- if (u.isPresent(value)) {
10790
- values.push(value);
10791
- values.push(':present');
10792
- }
10793
- else {
10794
- values.push(':blank');
10795
- }
10796
- if (u.isPresent(meta)) {
10797
- values.push(meta);
10798
- }
10799
- return values;
10800
- }
10801
- function switchTargets(switcher, options = {}) {
10802
- const targetSelector = options.target || options.target || switcher.getAttribute('up-switch');
10803
- const form = getScope(switcher);
10804
- targetSelector || up.fail("No switch target given for %o", switcher);
10805
- const fieldValues = switcherValues(switcher);
10806
- for (let target of up.fragment.all(form, targetSelector)) {
10807
- switchTarget(target, fieldValues);
10808
- }
10809
- }
10810
- const switchTarget = up.mockable(function (target, fieldValues) {
10811
- let show;
10812
- fieldValues ||= switcherValues(findSwitcherForTarget(target));
10813
- let hideValues = target.getAttribute('up-hide-for');
10814
- if (hideValues) {
10815
- hideValues = parseSwitchTokens(hideValues);
10816
- show = u.intersect(fieldValues, hideValues).length === 0;
10817
- }
10818
- else {
10819
- let showValues = target.getAttribute('up-show-for');
10820
- showValues = showValues ? parseSwitchTokens(showValues) : [':present', ':checked'];
10821
- show = u.intersect(fieldValues, showValues).length > 0;
10822
- }
10823
- e.toggle(target, show);
10824
- target.classList.add('up-switched');
10825
- });
10826
- function parseSwitchTokens(str) {
10827
- return u.getSimpleTokens(str, { json: true });
10828
- }
10829
- function findSwitcherForTarget(target) {
10830
- const form = getScope(target);
10831
- const switchers = form.querySelectorAll('[up-switch]');
10832
- const switcher = u.find(switchers, function (switcher) {
10833
- const targetSelector = switcher.getAttribute('up-switch');
10834
- return target.matches(targetSelector);
10835
- });
10836
- return switcher || up.fail('Could not find [up-switch] field for %o', target);
10837
- }
10838
11186
  function getForm(elementOrSelector, options = {}) {
10839
11187
  const element = up.fragment.get(elementOrSelector, options);
10840
11188
  return element.form || element.closest('form');
10841
11189
  }
10842
- function getScope(origin, options) {
11190
+ function getFormValidator(form) {
11191
+ return form.upFormValidator ||= setupFormValidator(form);
11192
+ }
11193
+ function setupFormValidator(form) {
11194
+ const validator = new up.FormValidator(form);
11195
+ const stop = validator.start();
11196
+ up.destructor(form, stop);
11197
+ return validator;
11198
+ }
11199
+ function getRegion(origin, options) {
10843
11200
  if (origin) {
10844
11201
  return getForm(origin, options) || up.layer.get(origin).element;
10845
11202
  }
@@ -10847,6 +11204,19 @@ up.form = (function () {
10847
11204
  return up.layer.current.element;
10848
11205
  }
10849
11206
  }
11207
+ function trackFields(...args) {
11208
+ let [root, { guard }, callback] = u.args(args, 'val', 'options', 'callback');
11209
+ let filter = function (fields) {
11210
+ let scope = getRegion(root);
11211
+ return u.filter(fields, function (field) {
11212
+ return (root === scope || root.contains(field))
11213
+ && (getForm(field) === scope)
11214
+ && (!guard || guard(field));
11215
+ });
11216
+ };
11217
+ const live = true;
11218
+ return up.fragment.trackSelector(fieldSelector(), { filter, live }, callback);
11219
+ }
10850
11220
  function focusedField() {
10851
11221
  return u.presence(document.activeElement, isField);
10852
11222
  }
@@ -10861,49 +11231,39 @@ up.form = (function () {
10861
11231
  up.event.halt(event, { log: true });
10862
11232
  up.error.muteUncriticalRejection(submit(form, { submitButton }));
10863
11233
  });
10864
- up.compiler(validatingFieldSelector, function (fieldOrForm) {
10865
- let validator = up.FormValidator.forElement(fieldOrForm);
10866
- validator.watchContainer(fieldOrForm);
11234
+ up.compiler('form', function (form) {
11235
+ getFormValidator(form);
10867
11236
  });
10868
- function validatingFieldSelector() {
10869
- let includes = config.fieldSelectors.map((selector) => `${selector}[up-validate], [up-validate] ${selector}`);
10870
- let excludes = ['[up-validate=false]'];
10871
- return e.unionSelector(includes, excludes);
10872
- }
10873
11237
  up.compiler('[up-switch]', (switcher) => {
10874
- switchTargets(switcher);
10875
- });
10876
- up.on('change', '[up-switch]', (_event, switcher) => {
10877
- switchTargets(switcher);
10878
- });
10879
- up.compiler('[up-show-for]:not(.up-switched), [up-hide-for]:not(.up-switched)', (element) => {
10880
- switchTarget(element);
11238
+ return new up.Switcher(switcher).start();
10881
11239
  });
10882
11240
  up.attribute('up-watch', (formOrField) => watch(formOrField));
10883
- up.attribute('up-autosubmit', (formOrField) => autosubmit(formOrField));
11241
+ up.attribute('up-autosubmit', (formOrField) => autosubmit(formOrField, { logPrefix: '[up-autosubmit]' }));
10884
11242
  return {
10885
11243
  config,
10886
11244
  submit,
10887
11245
  submitOptions,
10888
11246
  destinationOptions,
10889
11247
  watchOptions,
11248
+ validateOptions,
10890
11249
  isSubmittable,
10891
11250
  watch,
10892
11251
  validate,
10893
11252
  autosubmit,
10894
11253
  fieldSelector,
10895
11254
  fields: findFields,
11255
+ trackFields,
10896
11256
  isField,
10897
11257
  submitButtons: findSubmitButtons,
10898
11258
  focusedField,
10899
- switchTarget,
10900
- disable: disableContainer,
11259
+ disableTemp: disableContainerTemp,
11260
+ setDisabled: setContainerDisabled,
10901
11261
  getDisablePreviewFn,
10902
11262
  group: findGroup,
10903
11263
  groupSolution: findGroupSolution,
10904
11264
  groupSelectors: getGroupSelectors,
10905
11265
  get: getForm,
10906
- getScope,
11266
+ getRegion,
10907
11267
  };
10908
11268
  })();
10909
11269
  up.submit = up.form.submit;
@@ -10913,13 +11273,12 @@ up.validate = up.form.validate;
10913
11273
 
10914
11274
 
10915
11275
  /***/ }),
10916
- /* 98 */
11276
+ /* 101 */
10917
11277
  /***/ (() => {
10918
11278
 
10919
11279
  up.status = (function () {
10920
11280
  const u = up.util;
10921
11281
  const e = up.element;
10922
- let namedPreviewFns = {};
10923
11282
  const config = new up.Config(() => ({
10924
11283
  currentClasses: ['up-current'],
10925
11284
  activeClasses: ['up-active'],
@@ -10927,9 +11286,9 @@ up.status = (function () {
10927
11286
  navSelectors: ['[up-nav]', 'nav'],
10928
11287
  noNavSelectors: ['[up-nav=false]'],
10929
11288
  }));
11289
+ let namedPreviewFns = new up.Registry('preview');
10930
11290
  function reset() {
10931
11291
  up.layer.root.feedbackLocation = null;
10932
- namedPreviewFns = u.pickBy(namedPreviewFns, 'isDefault');
10933
11292
  }
10934
11293
  const SELECTOR_LINK = 'a, [up-href]';
10935
11294
  function linkCurrentURLs(link) {
@@ -10960,7 +11319,7 @@ up.status = (function () {
10960
11319
  let focusCapsule = up.FocusCapsule.preserve(bindLayer);
10961
11320
  let applyPreviews = () => doRunPreviews(request, renderOptions);
10962
11321
  let revertPreviews = bindLayer.asCurrent(applyPreviews);
10963
- up.on('focusin', { once: true }, () => focusCapsule = null);
11322
+ focusCapsule?.autoVoid();
10964
11323
  return () => {
10965
11324
  bindLayer.asCurrent(revertPreviews);
10966
11325
  focusCapsule?.restore(bindLayer, { preventScroll: true });
@@ -11005,7 +11364,7 @@ up.status = (function () {
11005
11364
  }
11006
11365
  function resolvePreviewString(str) {
11007
11366
  return u.map(u.parseScalarJSONPairs(str), ([name, parsedOptions]) => {
11008
- let previewFn = namedPreviewFns[name] || up.fail('Unknown preview "%s"', name);
11367
+ let previewFn = namedPreviewFns.get(name);
11009
11368
  return function (preview, runOptions) {
11010
11369
  up.puts('[up-preview]', 'Showing preview %o', name);
11011
11370
  return previewFn(preview, parsedOptions || runOptions);
@@ -11016,10 +11375,6 @@ up.status = (function () {
11016
11375
  activeElements ||= u.wrapList(origin);
11017
11376
  return activeElements.map(findActivatableArea);
11018
11377
  }
11019
- function registerPreview(name, previewFn) {
11020
- previewFn.isDefault = up.framework.evaling;
11021
- namedPreviewFns[name] = previewFn;
11022
- }
11023
11378
  function getFeedbackClassesPreviewFn(feedbackOption, fragments) {
11024
11379
  if (!feedbackOption)
11025
11380
  return;
@@ -11064,7 +11419,7 @@ up.status = (function () {
11064
11419
  up.on('up:framework:reset', reset);
11065
11420
  return {
11066
11421
  config,
11067
- preview: registerPreview,
11422
+ preview: namedPreviewFns.put,
11068
11423
  resolvePreviewFns,
11069
11424
  runPreviews,
11070
11425
  statusOptions,
@@ -11074,7 +11429,7 @@ up.preview = up.status.preview;
11074
11429
 
11075
11430
 
11076
11431
  /***/ }),
11077
- /* 99 */
11432
+ /* 102 */
11078
11433
  /***/ (() => {
11079
11434
 
11080
11435
  up.radio = (function () {
@@ -11168,7 +11523,7 @@ up.radio = (function () {
11168
11523
 
11169
11524
 
11170
11525
  /***/ }),
11171
- /* 100 */
11526
+ /* 103 */
11172
11527
  /***/ (() => {
11173
11528
 
11174
11529
  (function () {
@@ -11318,15 +11673,18 @@ __webpack_require__(83);
11318
11673
  __webpack_require__(84);
11319
11674
  __webpack_require__(85);
11320
11675
  __webpack_require__(86);
11676
+ __webpack_require__(87);
11321
11677
  __webpack_require__(88);
11322
- __webpack_require__(90);
11678
+ __webpack_require__(89);
11323
11679
  __webpack_require__(91);
11324
11680
  __webpack_require__(93);
11325
- __webpack_require__(95);
11326
- __webpack_require__(97);
11681
+ __webpack_require__(94);
11682
+ __webpack_require__(96);
11327
11683
  __webpack_require__(98);
11328
- __webpack_require__(99);
11329
11684
  __webpack_require__(100);
11685
+ __webpack_require__(101);
11686
+ __webpack_require__(102);
11687
+ __webpack_require__(103);
11330
11688
  up.framework.onEvaled();
11331
11689
 
11332
11690
  })();