unpoly-rails 3.9.5 → 3.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,7 +5,7 @@
5
5
  /***/ (() => {
6
6
 
7
7
  window.up = {
8
- version: '3.9.5'
8
+ version: '3.10.0'
9
9
  };
10
10
 
11
11
 
@@ -202,6 +202,9 @@ up.util = (function () {
202
202
  function isElement(object) {
203
203
  return object instanceof Element;
204
204
  }
205
+ function isTextNode(object) {
206
+ return object instanceof Text;
207
+ }
205
208
  function isRegExp(object) {
206
209
  return object instanceof RegExp;
207
210
  }
@@ -211,8 +214,8 @@ up.util = (function () {
211
214
  function isJQuery(object) {
212
215
  return up.browser.canJQuery() && object instanceof jQuery;
213
216
  }
214
- function isElementish(object) {
215
- return !!(object && (object.addEventListener || object[0]?.addEventListener));
217
+ function isElementLike(object) {
218
+ return !!(object && (object.addEventListener || (isJQuery(object) && object[0]?.addEventListener)));
216
219
  }
217
220
  function isPromise(object) {
218
221
  return isObject(object) && isFunction(object.then);
@@ -240,6 +243,9 @@ up.util = (function () {
240
243
  function isArguments(value) {
241
244
  return Object.prototype.toString.call(value) === '[object Arguments]';
242
245
  }
246
+ function isAdjacentPosition(value) {
247
+ return /^(before|after)/.test(value);
248
+ }
243
249
  function wrapList(value) {
244
250
  if (isList(value)) {
245
251
  return value;
@@ -297,10 +303,9 @@ up.util = (function () {
297
303
  }
298
304
  }
299
305
  function parseArgIntoOptions(args, argKey) {
300
- let options = extractOptions(args);
301
- if (isDefined(args[0])) {
302
- options = copy(options);
303
- options[argKey] = args[0];
306
+ let [positionalArg, options] = parseArgs(args, 'val', 'options');
307
+ if (isDefined(positionalArg)) {
308
+ options[argKey] = positionalArg;
304
309
  }
305
310
  return options;
306
311
  }
@@ -468,7 +473,9 @@ up.util = (function () {
468
473
  return value;
469
474
  }
470
475
  function renameKey(object, oldKey, newKey) {
471
- return object[newKey] = pluckKey(object, oldKey);
476
+ if (oldKey in object) {
477
+ object[newKey] = pluckKey(object, oldKey);
478
+ }
472
479
  }
473
480
  function extractLastArg(args, tester) {
474
481
  if (tester(last(args))) {
@@ -554,26 +561,34 @@ up.util = (function () {
554
561
  function isEqualList(a, b) {
555
562
  return (a.length === b.length) && every(a, (elem, index) => isEqual(elem, b[index]));
556
563
  }
557
- const PARSE_TOKEN_PATTERNS = {
558
- 'space/or': /\s+(?:or\s+)?/,
559
- 'or': /\s+or\s+/,
560
- 'comma': /\s*,\s*/
561
- };
562
- function parseTokens(value, options = {}) {
563
- if (isString(value)) {
564
- value = value.trim();
565
- if (options.json && /^\[.*]$/.test(value)) {
566
- return JSON.parse(value);
567
- }
568
- else {
569
- let separator = options.separator || 'space/or';
570
- let pattern = PARSE_TOKEN_PATTERNS[separator];
571
- return value.split(pattern);
572
- }
564
+ function getSimpleTokens(value, { json = false, separator = /[,\s]/ } = {}) {
565
+ if (!isString(value)) {
566
+ return wrapList(value);
567
+ }
568
+ else if (json && /^\[.*]$/.test(value)) {
569
+ return parseRelaxedJSON(value);
573
570
  }
574
571
  else {
572
+ return splitSimpleTokenString(value, separator);
573
+ }
574
+ }
575
+ function splitSimpleTokenString(value, separator) {
576
+ let parts = up.migrate.splitAtOr?.(value) || value.split(separator);
577
+ return parts.map((s) => s.trim()).filter(identity);
578
+ }
579
+ function getComplexTokens(value) {
580
+ if (!isString(value)) {
575
581
  return wrapList(value);
576
582
  }
583
+ else {
584
+ let { maskedTokens, restore } = complexTokenOutlines(value);
585
+ return maskedTokens.map((token) => restore(token));
586
+ }
587
+ }
588
+ function complexTokenOutlines(string) {
589
+ let { masked, restore } = expressionOutline(string);
590
+ let maskedTokens = splitSimpleTokenString(masked, ',');
591
+ return { maskedTokens, restore };
577
592
  }
578
593
  function wrapValue(constructor, ...args) {
579
594
  return (args[0] instanceof constructor) ? args[0] : new constructor(...args);
@@ -585,18 +600,13 @@ up.util = (function () {
585
600
  function reverse(list) {
586
601
  return copy(list).reverse();
587
602
  }
588
- function replaceValue(value, matchValue, replacementValue) {
589
- if (value === matchValue) {
590
- return replacementValue;
591
- }
592
- else {
593
- return value;
594
- }
595
- }
596
- function renameKeys(object, renameKeyFn) {
603
+ function withRenamedKeys(object, renameKeyFn) {
597
604
  const renamed = {};
598
605
  for (let key in object) {
599
- renamed[renameKeyFn(key)] = object[key];
606
+ let transformed = renameKeyFn(key);
607
+ if (isGiven(transformed)) {
608
+ renamed[transformed] = object[key];
609
+ }
600
610
  }
601
611
  return renamed;
602
612
  }
@@ -627,6 +637,9 @@ up.util = (function () {
627
637
  });
628
638
  }
629
639
  }
640
+ function delegatePromise(object, promiseProp) {
641
+ return defineDelegates(object, ['then', 'catch', 'finally'], function () { return this[promiseProp]; });
642
+ }
630
643
  function stringifyArg(arg, placeholder = '%o') {
631
644
  let string;
632
645
  const maxLength = 200;
@@ -736,6 +749,122 @@ up.util = (function () {
736
749
  Object.assign(variant, changes);
737
750
  return variant;
738
751
  }
752
+ function parseArgs(args, ...specs) {
753
+ let results = [];
754
+ while (specs.length) {
755
+ let lastSpec = specs.pop();
756
+ if (lastSpec === 'options') {
757
+ results.unshift(extractOptions(args));
758
+ }
759
+ else if (lastSpec === 'callback') {
760
+ results.unshift(extractCallback(args));
761
+ }
762
+ else if (lastSpec === 'val') {
763
+ results.unshift(args.pop());
764
+ }
765
+ else if (isFunction(lastSpec)) {
766
+ let value = lastSpec(last(args)) ? args.pop() : undefined;
767
+ results.unshift(value);
768
+ }
769
+ }
770
+ return results;
771
+ }
772
+ function scanFunctions(...values) {
773
+ return values.flat().filter(isFunction);
774
+ }
775
+ function cleaner() {
776
+ let fns = [];
777
+ let track = function (values, transform) {
778
+ values = scanFunctions(...values).map(transform);
779
+ fns.push(...scanFunctions(...values));
780
+ };
781
+ let api = function (...values) {
782
+ track(values, identity);
783
+ };
784
+ api.guard = function (...values) {
785
+ track(values, up.error.guardFn);
786
+ };
787
+ api.clean = function (...args) {
788
+ let { length } = fns;
789
+ for (let i = length - 1; i >= 0; i--)
790
+ fns[i](...args);
791
+ fns = [];
792
+ };
793
+ return api;
794
+ }
795
+ function maskPattern(str, patterns, { keepDelimiters = false } = {}) {
796
+ let maskCount = 0;
797
+ let maskPattern = /§(\d+)/g;
798
+ let matches = [];
799
+ let replaceLayers = 0;
800
+ let replace = (replacePattern) => {
801
+ let didReplace = false;
802
+ str = str.replaceAll(replacePattern, function (match) {
803
+ didReplace = true;
804
+ let glyph = '§' + (maskCount++);
805
+ let mask;
806
+ let masked;
807
+ if (keepDelimiters) {
808
+ let startDelimiter = match[0];
809
+ let endDelimiter = match.slice(-1);
810
+ masked = match.slice(1, -1);
811
+ mask = startDelimiter + glyph + endDelimiter;
812
+ }
813
+ else {
814
+ masked = match;
815
+ mask = glyph;
816
+ }
817
+ matches.push(masked);
818
+ return mask;
819
+ });
820
+ if (didReplace)
821
+ replaceLayers++;
822
+ };
823
+ [maskPattern, ...patterns].forEach(replace);
824
+ let restore = (s, transform = identity) => {
825
+ for (let i = 0; i < replaceLayers; i++) {
826
+ s = s.replace(maskPattern, (match, placeholderIndex) => transform(matches[placeholderIndex]));
827
+ }
828
+ return s;
829
+ };
830
+ return { masked: str, restore };
831
+ }
832
+ const QUOTED_STRING_PATTERN = /'(?:\\\\|\\'|[^'])*'|"(?:\\\\|\\"|[^"])*"/g;
833
+ const NESTED_GROUP_PATTERN = /{(?:[^{}]|{[^{}]*})*}|\((?:[^\(\)]|\([^\(\)]*\))*\)|\[(?:[^\[\]]|\[[^\[\]]*\])*\]/g;
834
+ function expressionOutline(str) {
835
+ return maskPattern(str, [QUOTED_STRING_PATTERN, NESTED_GROUP_PATTERN], { keepDelimiters: true });
836
+ }
837
+ function ensureDoubleQuotes(str) {
838
+ if (str[0] === '"')
839
+ return str;
840
+ str = str.slice(1, -1);
841
+ let transformed = str.replace(/(\\\\)|(\\')|(\\")|(")/g, function (_match, escapedBackslash, escapedSingleQuote, _doubleQuote) {
842
+ return escapedBackslash
843
+ || (escapedSingleQuote && "'")
844
+ || '\\"';
845
+ });
846
+ return '"' + transformed + '"';
847
+ }
848
+ function parseString(value) {
849
+ return JSON.parse(ensureDoubleQuotes(value));
850
+ }
851
+ function parseRelaxedJSON(str) {
852
+ let { masked, restore } = maskPattern(str, [QUOTED_STRING_PATTERN]);
853
+ masked = masked.replace(/([a-z_$][\w$]*:)/gi, (unquotedProperty) => ('"' + unquotedProperty.slice(0, -1) + '":'));
854
+ masked = masked.replace(/,\s*([}\]])/g, '$1');
855
+ masked = restore(masked, ensureDoubleQuotes);
856
+ return JSON.parse(masked);
857
+ }
858
+ function parseScalarJSONPairs(str) {
859
+ let { maskedTokens, restore } = complexTokenOutlines(str);
860
+ return maskedTokens.map((maskedToken) => {
861
+ let [_match, string, json] = maskedToken.match(/([^{]+)({[^}]*})?/);
862
+ return [
863
+ restore(string.trim()),
864
+ json && parseRelaxedJSON(restore(json))
865
+ ];
866
+ });
867
+ }
739
868
  return {
740
869
  parseURL,
741
870
  normalizeURL,
@@ -779,14 +908,16 @@ up.util = (function () {
779
908
  isBoolean,
780
909
  isNumber,
781
910
  isElement,
911
+ isTextNode,
782
912
  isJQuery,
783
- isElementish,
913
+ isElementLike,
784
914
  isPromise,
785
915
  isOptions,
786
916
  isArray,
787
917
  isFormData,
788
918
  isList,
789
919
  isRegExp,
920
+ isAdjacentPosition,
790
921
  timer: scheduleTimer,
791
922
  contains,
792
923
  containsAll,
@@ -817,21 +948,30 @@ up.util = (function () {
817
948
  isCrossOrigin,
818
949
  task: queueTask,
819
950
  isEqual,
820
- parseTokens,
951
+ getSimpleTokens,
952
+ getComplexTokens,
821
953
  wrapList,
822
954
  wrapValue,
823
955
  uid,
824
956
  upperCaseFirst,
825
957
  lowerCaseFirst,
826
958
  delegate: defineDelegates,
959
+ delegatePromise,
827
960
  reverse,
828
961
  camelToKebabCase,
829
- replaceValue,
830
962
  sprintf,
831
- renameKeys,
963
+ withRenamedKeys,
832
964
  memoizeMethod,
833
965
  safeStringifyJSON,
834
966
  variant,
967
+ cleaner,
968
+ scanFunctions,
969
+ args: parseArgs,
970
+ parseRelaxedJSON,
971
+ parseScalarJSONPairs,
972
+ maskPattern,
973
+ expressionOutline,
974
+ parseString,
835
975
  };
836
976
  })();
837
977
 
@@ -863,17 +1003,12 @@ up.error = (function () {
863
1003
  throw value;
864
1004
  }
865
1005
  }
866
- function report(error) {
867
- console.error('Uncaught %o', error);
868
- let event = new ErrorEvent('error', { error, message: 'Uncaught ' + error });
869
- window.dispatchEvent(event);
870
- }
871
- function guard(fn) {
1006
+ function guard(fn, ...args) {
872
1007
  try {
873
- return fn();
1008
+ return fn(...args);
874
1009
  }
875
1010
  catch (error) {
876
- report(error);
1011
+ reportError(error);
877
1012
  }
878
1013
  }
879
1014
  function guardFn(fn) {
@@ -905,7 +1040,6 @@ up.migrate = {
905
1040
  /***/ (() => {
906
1041
 
907
1042
  up.browser = (function () {
908
- const u = up.util;
909
1043
  function submitForm(form) {
910
1044
  form.submit();
911
1045
  }
@@ -915,7 +1049,6 @@ up.browser = (function () {
915
1049
  function canJQuery() {
916
1050
  return !!window.jQuery;
917
1051
  }
918
- const canHasSelector = u.memoize(() => CSS.supports('selector(:has(*))'));
919
1052
  function popCookie(name) {
920
1053
  let value = document.cookie.match(new RegExp(name + "=(\\w+)"))?.[1];
921
1054
  if (value) {
@@ -936,7 +1069,6 @@ up.browser = (function () {
936
1069
  canJQuery,
937
1070
  assertConfirmed,
938
1071
  popCookie,
939
- canHasSelector,
940
1072
  };
941
1073
  })();
942
1074
 
@@ -949,18 +1081,23 @@ __webpack_require__(8);
949
1081
  up.element = (function () {
950
1082
  const u = up.util;
951
1083
  function first(...args) {
952
- const selector = args.pop();
953
- const root = args[0] || document;
1084
+ let [root = document, selector] = u.args(args, 'val', 'val');
954
1085
  return root.querySelector(selector);
955
1086
  }
956
1087
  function subtree(root, selector) {
957
1088
  const results = [];
958
- if (root.matches(selector)) {
1089
+ if (elementLikeMatches(root, selector)) {
959
1090
  results.push(root);
960
1091
  }
961
1092
  results.push(...root.querySelectorAll(selector));
962
1093
  return results;
963
1094
  }
1095
+ function subtreeFirst(root, selector) {
1096
+ return elementLikeMatches(root, selector) ? root : root.querySelector(selector);
1097
+ }
1098
+ function elementLikeMatches(elementLike, selector) {
1099
+ return u.isElement(elementLike) && elementLike.matches(selector);
1100
+ }
964
1101
  function contains(root, selectorOrElement) {
965
1102
  const element = getOne(selectorOrElement);
966
1103
  return Node.prototype.contains.call(root, element);
@@ -1001,24 +1138,38 @@ up.element = (function () {
1001
1138
  }
1002
1139
  }
1003
1140
  function hide(element) {
1004
- element.setAttribute('hidden', '');
1141
+ setVisible(element, false);
1005
1142
  }
1006
1143
  function show(element) {
1007
- element.removeAttribute('hidden');
1008
- if (element.style.display === 'none') {
1009
- element.style.display = '';
1010
- }
1144
+ setVisible(element, true);
1011
1145
  }
1012
- function toggle(element, newVisible) {
1013
- if (newVisible == null) {
1014
- newVisible = !isVisible(element);
1015
- }
1016
- (newVisible ? show : hide)(element);
1146
+ function showTemp(element) {
1147
+ return setVisibleTemp(element, true);
1017
1148
  }
1018
- function toggleAttr(element, attr, value, newPresent) {
1019
- if (newPresent == null) {
1020
- newPresent = !element.hasAttribute(attr);
1149
+ function hideTemp(element) {
1150
+ return setVisibleTemp(element, false);
1151
+ }
1152
+ function setVisibleTemp(element, newVisible) {
1153
+ if (newVisible === isVisible(element))
1154
+ return u.noop;
1155
+ setVisible(element, newVisible);
1156
+ return () => setVisible(element, !newVisible);
1157
+ }
1158
+ function setVisible(element, newVisible) {
1159
+ if (newVisible) {
1160
+ element.removeAttribute('hidden');
1161
+ if (element.style.display === 'none') {
1162
+ element.style.display = '';
1163
+ }
1164
+ }
1165
+ else {
1166
+ element.setAttribute('hidden', '');
1021
1167
  }
1168
+ }
1169
+ function toggle(element, newVisible = !isVisible(element)) {
1170
+ setVisible(element, newVisible);
1171
+ }
1172
+ function setAttrPresence(element, attr, value, newPresent) {
1022
1173
  if (newPresent) {
1023
1174
  return element.setAttribute(attr, value);
1024
1175
  }
@@ -1037,11 +1188,9 @@ up.element = (function () {
1037
1188
  }
1038
1189
  }
1039
1190
  }
1040
- function setTemporaryAttrs(element, attrs) {
1041
- const oldAttrs = {};
1042
- for (let key of Object.keys(attrs)) {
1043
- oldAttrs[key] = element.getAttribute(key);
1044
- }
1191
+ function setAttrsTemp(element, attrs) {
1192
+ let keys = Object.keys(attrs);
1193
+ let oldAttrs = pickAttrs(element, keys);
1045
1194
  setAttrs(element, attrs);
1046
1195
  return () => setAttrs(element, oldAttrs);
1047
1196
  }
@@ -1049,8 +1198,8 @@ up.element = (function () {
1049
1198
  const selector = "meta" + attrSelector('name', name);
1050
1199
  return first(selector)?.getAttribute('content');
1051
1200
  }
1052
- function insertBefore(existingElement, newElement) {
1053
- existingElement.insertAdjacentElement('beforebegin', newElement);
1201
+ function insertBefore(existingNode, newNode) {
1202
+ existingNode.parentNode.insertBefore(newNode, existingNode);
1054
1203
  }
1055
1204
  function createFromSelector(selector, attrs = {}) {
1056
1205
  let { includePath } = parseSelector(selector);
@@ -1058,7 +1207,7 @@ up.element = (function () {
1058
1207
  let depthElement;
1059
1208
  let previousElement;
1060
1209
  for (let includeSegment of includePath) {
1061
- let { tagName, id, classNames, attributes } = includeSegment;
1210
+ let { tagName } = includeSegment;
1062
1211
  if (!tagName || tagName === '*') {
1063
1212
  tagName = 'div';
1064
1213
  }
@@ -1066,25 +1215,14 @@ up.element = (function () {
1066
1215
  if (!rootElement) {
1067
1216
  rootElement = depthElement;
1068
1217
  }
1069
- if (id) {
1070
- depthElement.id = id;
1071
- }
1072
- for (let className of classNames) {
1073
- depthElement.classList.add(className);
1074
- }
1075
- for (let attributeName in attributes) {
1076
- let attributeValue = attributes[attributeName];
1077
- depthElement.setAttribute(attributeName, attributeValue || '');
1078
- }
1218
+ makeVariation(depthElement, includeSegment);
1079
1219
  previousElement?.appendChild(depthElement);
1080
1220
  previousElement = depthElement;
1081
1221
  }
1082
1222
  for (let key in attrs) {
1083
1223
  let value = attrs[key];
1084
1224
  if (key === 'class') {
1085
- for (let klass of u.wrapList(value)) {
1086
- rootElement.classList.add(klass);
1087
- }
1225
+ addClasses(rootElement, u.wrapList(value));
1088
1226
  }
1089
1227
  else if (key === 'style') {
1090
1228
  setInlineStyle(rootElement, value);
@@ -1093,7 +1231,12 @@ up.element = (function () {
1093
1231
  rootElement.textContent = value;
1094
1232
  }
1095
1233
  else if (key === 'content') {
1096
- rootElement.innerHTML = value;
1234
+ if (u.isString(value)) {
1235
+ rootElement.innerHTML = value;
1236
+ }
1237
+ else {
1238
+ rootElement.append(...u.wrapList(value));
1239
+ }
1097
1240
  }
1098
1241
  else {
1099
1242
  rootElement.setAttribute(key, value);
@@ -1101,14 +1244,24 @@ up.element = (function () {
1101
1244
  }
1102
1245
  return rootElement;
1103
1246
  }
1104
- function parseSelector(selector) {
1247
+ function makeVariation(element, { id, classNames, attributes }) {
1248
+ if (id) {
1249
+ element.id = id;
1250
+ }
1251
+ for (let [name, value] of Object.entries(attributes)) {
1252
+ element.setAttribute(name, value);
1253
+ }
1254
+ addClasses(element, classNames);
1255
+ }
1256
+ function parseSelector(rawSelector) {
1105
1257
  let excludeRaw;
1106
- const includeRaw = selector.replace(/:not\([^)]+\)/, function (match) {
1107
- excludeRaw = match;
1258
+ const { masked: selectorOutline, restore: restoreSelectorLiterals, } = u.expressionOutline(rawSelector);
1259
+ const includeWithoutAttrs = selectorOutline.replace(/:not\([^)]*\)/, function (match) {
1260
+ excludeRaw = restoreSelectorLiterals(match);
1108
1261
  return '';
1109
1262
  });
1110
- const [includeSelectorWithoutAttrValues, attrValues] = removeAttrSelectorValues(includeRaw);
1111
- const includeSegments = includeSelectorWithoutAttrValues.split(/[ >]+/);
1263
+ let includeRaw = restoreSelectorLiterals(includeWithoutAttrs);
1264
+ const includeSegments = includeWithoutAttrs.split(/[ >]+/);
1112
1265
  let includePath = includeSegments.map(function (depthSelector) {
1113
1266
  let parsed = {
1114
1267
  tagName: null,
@@ -1128,14 +1281,15 @@ up.element = (function () {
1128
1281
  parsed.classNames.push(className);
1129
1282
  return '';
1130
1283
  });
1131
- if (attrValues.length) {
1132
- depthSelector = replaceAttrSelectors(depthSelector, function ({ name }) {
1133
- parsed.attributes[name] = attrValues.shift();
1134
- return '';
1135
- });
1136
- }
1284
+ depthSelector = depthSelector.replace(/\[[^\]]*]/g, function (attr) {
1285
+ attr = restoreSelectorLiterals(attr);
1286
+ let [_raw, name, _operator, quote, value] = attr.match(/\[([\w-]+)(?:([~|^$*]?=)(["'])?([^\3\]]*?)\3)?]/);
1287
+ quote ||= '"';
1288
+ parsed.attributes[name] = value ? u.parseString(quote + value + quote) : '';
1289
+ return '';
1290
+ });
1137
1291
  if (depthSelector) {
1138
- up.fail('Cannot parse selector: ' + selector);
1292
+ up.fail('Cannot parse selector: ' + rawSelector);
1139
1293
  }
1140
1294
  return parsed;
1141
1295
  });
@@ -1145,33 +1299,8 @@ up.element = (function () {
1145
1299
  excludeRaw,
1146
1300
  };
1147
1301
  }
1148
- const ATTR_SELECTOR_PATTERN = /\[([\w-]+)(?:([~|^$*]?=)(["'])?([^\3\]]*?)\3)?]/g;
1149
- function replaceAttrSelectors(string, replacement) {
1150
- return string.replace(ATTR_SELECTOR_PATTERN, function (_match, name, operator, quote, value) {
1151
- if (value) {
1152
- value = value.replace(/\\([\\"'])/, '$1');
1153
- }
1154
- return replacement({ name, operator, quote, value });
1155
- });
1156
- }
1157
- function removeAttrSelectorValues(selector) {
1158
- let values = [];
1159
- selector = replaceAttrSelectors(selector, function ({ name, value }) {
1160
- values.push(value);
1161
- return `[${name}]`;
1162
- });
1163
- return [selector, values];
1164
- }
1165
- function affix(parent, ...args) {
1166
- let position, selector;
1167
- const attributes = u.extractOptions(args);
1168
- if (args.length === 2) {
1169
- [position, selector] = args;
1170
- }
1171
- else {
1172
- position = 'beforeend';
1173
- selector = args[0];
1174
- }
1302
+ function affix(...args) {
1303
+ let [parent, position = 'beforeend', selector, attributes] = u.args(args, 'val', u.isAdjacentPosition, 'val', 'options');
1175
1304
  const element = createFromSelector(selector, attributes);
1176
1305
  parent.insertAdjacentElement(position, element);
1177
1306
  return element;
@@ -1210,14 +1339,22 @@ up.element = (function () {
1210
1339
  scriptish.replaceWith(clone);
1211
1340
  }
1212
1341
  function createFromHTML(html) {
1342
+ return extractSingular(createNodesFromHTML(html));
1343
+ }
1344
+ function extractSingular(nodes) {
1345
+ if (nodes.length === 1 && u.isElementLike(nodes[0])) {
1346
+ return nodes[0];
1347
+ }
1348
+ else {
1349
+ up.fail('Expected a single element, but got %d elements', nodes.length);
1350
+ }
1351
+ }
1352
+ function createNodesFromHTML(html) {
1353
+ html = html.trim();
1213
1354
  const range = document.createRange();
1214
1355
  range.setStart(document.body, 0);
1215
- const fragment = range.createContextualFragment(html.trim());
1216
- let elements = fragment.childNodes;
1217
- if (elements.length !== 1) {
1218
- throw new Error('HTML must have a single root element');
1219
- }
1220
- return elements[0];
1356
+ const fragment = range.createContextualFragment(html);
1357
+ return fragment.childNodes;
1221
1358
  }
1222
1359
  function getRoot() {
1223
1360
  return document.documentElement;
@@ -1226,7 +1363,7 @@ up.element = (function () {
1226
1363
  element.offsetHeight;
1227
1364
  }
1228
1365
  function concludeCSSTransition(element) {
1229
- const undo = setTemporaryStyle(element, { transition: 'none' });
1366
+ const undo = setStyleTemp(element, { transition: 'none' });
1230
1367
  paint(element);
1231
1368
  return undo;
1232
1369
  }
@@ -1259,19 +1396,28 @@ up.element = (function () {
1259
1396
  }
1260
1397
  function unwrap(wrapper) {
1261
1398
  preservingFocus(function () {
1262
- const parent = wrapper.parentNode;
1263
- const wrappedNodes = u.toArray(wrapper.childNodes);
1264
- u.each(wrappedNodes, wrappedNode => parent.insertBefore(wrappedNode, wrapper));
1265
- parent.removeChild(wrapper);
1399
+ let childNodes = [...wrapper.childNodes];
1400
+ for (let child of childNodes)
1401
+ insertBefore(wrapper, child);
1402
+ wrapper.remove();
1266
1403
  });
1267
1404
  }
1268
- function wrapChildren(element) {
1269
- let childNode;
1405
+ function wrapNodes(nodeOrNodes) {
1270
1406
  const wrapper = document.createElement('up-wrapper');
1271
- while ((childNode = element.firstChild)) {
1272
- wrapper.appendChild(childNode);
1407
+ wrapper.append(...u.wrapList(nodeOrNodes));
1408
+ return wrapper;
1409
+ }
1410
+ function wrapIfRequired(nodes) {
1411
+ if (nodes.length === 1 && u.isElement(nodes[0])) {
1412
+ return nodes[0];
1413
+ }
1414
+ else {
1415
+ return wrapNodes(nodes);
1273
1416
  }
1274
- element.appendChild(wrapper);
1417
+ }
1418
+ function wrapChildren(element) {
1419
+ const wrapper = wrapNodes(element.childNodes);
1420
+ element.append(wrapper);
1275
1421
  return wrapper;
1276
1422
  }
1277
1423
  function preservingFocus(fn) {
@@ -1285,76 +1431,90 @@ up.element = (function () {
1285
1431
  }
1286
1432
  }
1287
1433
  }
1434
+ function parseAttr(element, attribute, ...parsers) {
1435
+ if (!element.hasAttribute?.(attribute))
1436
+ return undefined;
1437
+ let rawValue = element.getAttribute(attribute);
1438
+ for (let parser of parsers) {
1439
+ let parserResult = parser(rawValue, attribute, element);
1440
+ if (u.isDefined(parserResult))
1441
+ return parserResult;
1442
+ }
1443
+ }
1288
1444
  function stringAttr(element, attribute) {
1289
- let value = element.getAttribute(attribute);
1290
- return u.replaceValue(value, null, undefined);
1445
+ return parseAttr(element, attribute, tryParseString);
1291
1446
  }
1292
- function booleanAttr(element, attribute, pass) {
1293
- if (!element.hasAttribute(attribute))
1294
- return;
1295
- const value = stringAttr(element, attribute);
1447
+ let tryParseString = u.identity;
1448
+ function booleanAttr(element, attribute) {
1449
+ return parseAttr(element, attribute, tryParseBoolean);
1450
+ }
1451
+ function tryParseBoolean(value, attribute) {
1296
1452
  switch (value) {
1297
1453
  case 'false': {
1298
1454
  return false;
1299
1455
  }
1300
1456
  case 'true':
1301
1457
  case '':
1302
- case attribute: {
1303
- return true;
1304
- }
1305
- default: {
1306
- if (pass) {
1307
- return value;
1308
- }
1309
- else {
1458
+ case attribute:
1459
+ {
1310
1460
  return true;
1311
1461
  }
1312
- }
1313
1462
  }
1314
1463
  }
1315
- function booleanOrStringAttr(element, attribute, trueValue = true) {
1316
- let value = booleanAttr(element, attribute, true);
1317
- return value === true ? trueValue : value;
1464
+ function booleanOrStringAttr(element, attribute) {
1465
+ return parseAttr(element, attribute, tryParseBoolean, tryParseString);
1466
+ }
1467
+ function booleanOrNumberAttr(element, attribute) {
1468
+ return parseAttr(element, attribute, tryParseBoolean, tryParseNumber);
1318
1469
  }
1319
1470
  function numberAttr(element, attribute) {
1320
- let value = element.getAttribute(attribute);
1321
- if (value) {
1322
- value = value.replace(/_/g, '');
1323
- if (value.match(/^-?[\d.]+$/)) {
1324
- return parseFloat(value);
1325
- }
1471
+ return parseAttr(element, attribute, tryParseNumber);
1472
+ }
1473
+ function tryParseNumber(value) {
1474
+ value = value.replaceAll('_', '');
1475
+ if (value.match(/^-?[\d.]+$/)) {
1476
+ return parseFloat(value);
1326
1477
  }
1327
1478
  }
1328
1479
  function jsonAttr(element, attribute) {
1329
- let json = element.getAttribute?.(attribute)?.trim();
1330
- if (json) {
1331
- return JSON.parse(json);
1332
- }
1333
- }
1334
- function callbackAttr(link, attr, { exposedKeys = [], mainKey = 'event' } = {}) {
1335
- let code = link.getAttribute(attr);
1336
- if (code) {
1337
- const callback = up.NonceableCallback.fromString(code).toFunction(mainKey, ...exposedKeys);
1338
- return function (event) {
1339
- const exposedValues = Object.values(u.pick(event, exposedKeys));
1340
- return callback.call(link, event, ...exposedValues);
1341
- };
1480
+ return parseAttr(element, attribute, tryParseJSON);
1481
+ }
1482
+ function tryParseJSON(value) {
1483
+ if (value?.trim()) {
1484
+ return u.parseRelaxedJSON(value);
1342
1485
  }
1343
1486
  }
1344
- function closestAttr(element, attr, parseFn = stringAttr) {
1487
+ function callbackAttr(link, attr, callbackOptions) {
1488
+ return parseAttr(link, attr, (value) => tryParseCallback(value, link, callbackOptions));
1489
+ }
1490
+ function tryParseCallback(code, link, { exposedKeys = [], mainKey = 'event' } = {}) {
1491
+ const callback = up.NonceableCallback.fromString(code).toFunction(mainKey, ...exposedKeys);
1492
+ return function (event) {
1493
+ const exposedValues = Object.values(u.pick(event, exposedKeys));
1494
+ return callback.call(link, event, ...exposedValues);
1495
+ };
1496
+ }
1497
+ function closestAttr(element, attr, readAttrFn = stringAttr) {
1345
1498
  let match = element.closest('[' + attr + ']');
1346
1499
  if (match) {
1347
- return parseFn(match, attr);
1500
+ return readAttrFn(match, attr);
1348
1501
  }
1349
1502
  }
1350
- function setTemporaryStyle(element, newStyles) {
1351
- const oldStyles = inlineStyle(element, Object.keys(newStyles));
1352
- setInlineStyle(element, newStyles);
1353
- return () => setInlineStyle(element, oldStyles);
1503
+ function addClasses(element, classes) {
1504
+ for (let klass of classes)
1505
+ element.classList.add(klass);
1506
+ }
1507
+ function addClassTemp(element, klass) {
1508
+ return setClassStateTemp(element, klass, true);
1509
+ }
1510
+ function removeClassTemp(element, klass) {
1511
+ return setClassStateTemp(element, klass, false);
1354
1512
  }
1355
- function addTemporaryClass(element, klass) {
1356
- element.classList.add(klass);
1357
- return () => element.classList.remove(klass);
1513
+ function setClassStateTemp(element, klass, targetState) {
1514
+ if (element.classList.contains(klass) === targetState)
1515
+ return u.noop;
1516
+ element.classList.toggle(klass, targetState);
1517
+ return () => element.classList.toggle(klass, !targetState);
1358
1518
  }
1359
1519
  function computedStyle(element, props) {
1360
1520
  const style = window.getComputedStyle(element);
@@ -1394,16 +1554,24 @@ up.element = (function () {
1394
1554
  }
1395
1555
  }
1396
1556
  }
1557
+ function setStyleTemp(element, newStyles) {
1558
+ const oldStyles = inlineStyle(element, Object.keys(newStyles));
1559
+ setInlineStyle(element, newStyles);
1560
+ return () => setInlineStyle(element, oldStyles);
1561
+ }
1397
1562
  function isVisible(element) {
1398
1563
  return !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length);
1399
1564
  }
1400
1565
  function isUpPrefixed(string) {
1401
1566
  return /^up-/.test(string);
1402
1567
  }
1403
- function upAttrs(element) {
1404
- let attrNames = u.filter(element.getAttributeNames(), isUpPrefixed);
1568
+ function pickAttrs(element, attrNames) {
1405
1569
  return u.mapObject(attrNames, (name) => [name, element.getAttribute(name)]);
1406
1570
  }
1571
+ function upAttrs(element) {
1572
+ let attrNames = element.getAttributeNames().filter(isUpPrefixed);
1573
+ return pickAttrs(element, attrNames);
1574
+ }
1407
1575
  function upClasses(element) {
1408
1576
  return u.filter(element.classList.values(), isUpPrefixed);
1409
1577
  }
@@ -1430,8 +1598,29 @@ up.element = (function () {
1430
1598
  selector += `:not(${excludes.join()})`;
1431
1599
  return selector;
1432
1600
  }
1601
+ function matchSelectorMap(selectorMap, element) {
1602
+ let matches = [];
1603
+ if (selectorMap) {
1604
+ for (let [selector, value] of Object.entries(selectorMap)) {
1605
+ if (u.isDefined(value) && element.matches(selector)) {
1606
+ matches.push(value);
1607
+ }
1608
+ }
1609
+ }
1610
+ return matches;
1611
+ }
1612
+ function documentPosition(element) {
1613
+ let nextSibling = element.nextElementSibling;
1614
+ if (nextSibling) {
1615
+ return [nextSibling, 'beforebegin'];
1616
+ }
1617
+ else {
1618
+ return [element.parentElement, 'beforeend'];
1619
+ }
1620
+ }
1433
1621
  return {
1434
1622
  subtree,
1623
+ subtreeFirst,
1435
1624
  contains,
1436
1625
  closestAttr,
1437
1626
  ancestor,
@@ -1440,12 +1629,14 @@ up.element = (function () {
1440
1629
  list: getList,
1441
1630
  toggle,
1442
1631
  hide,
1632
+ hideTemp,
1443
1633
  show,
1634
+ showTemp,
1444
1635
  metaContent,
1445
1636
  insertBefore,
1446
1637
  createFromSelector,
1447
1638
  setAttrs,
1448
- setTemporaryAttrs,
1639
+ setAttrsTemp,
1449
1640
  affix,
1450
1641
  idSelector,
1451
1642
  classSelector,
@@ -1454,7 +1645,9 @@ up.element = (function () {
1454
1645
  tagName: elementTagName,
1455
1646
  createBrokenDocumentFromHTML,
1456
1647
  fixParserDamage,
1648
+ createNodesFromHTML,
1457
1649
  createFromHTML,
1650
+ extractSingular,
1458
1651
  get root() { return getRoot(); },
1459
1652
  paint,
1460
1653
  concludeCSSTransition,
@@ -1464,13 +1657,15 @@ up.element = (function () {
1464
1657
  setMissingAttr,
1465
1658
  unwrap,
1466
1659
  wrapChildren,
1660
+ wrapIfRequired,
1467
1661
  attr: stringAttr,
1468
1662
  booleanAttr,
1469
1663
  numberAttr,
1470
1664
  jsonAttr,
1471
1665
  callbackAttr,
1472
1666
  booleanOrStringAttr,
1473
- setTemporaryStyle,
1667
+ booleanOrNumberAttr,
1668
+ setStyleTemp,
1474
1669
  style: computedStyle,
1475
1670
  styleNumber: computedStyleNumber,
1476
1671
  inlineStyle,
@@ -1478,14 +1673,19 @@ up.element = (function () {
1478
1673
  isVisible,
1479
1674
  upAttrs,
1480
1675
  upClasses,
1481
- toggleAttr,
1482
- addTemporaryClass,
1676
+ setAttrPresence,
1677
+ addClasses,
1678
+ addClassTemp,
1679
+ removeClassTemp,
1483
1680
  cleanJQuery,
1484
1681
  parseSelector,
1485
1682
  isEmpty,
1486
1683
  crossOriginSelector,
1487
1684
  isIntersectingWindow,
1488
1685
  unionSelector,
1686
+ matchSelectorMap,
1687
+ elementLikeMatches,
1688
+ documentPosition,
1489
1689
  };
1490
1690
  })();
1491
1691
 
@@ -1682,6 +1882,9 @@ up.OptionsParser = class OptionsParser {
1682
1882
  booleanOrString(key, keyOptions) {
1683
1883
  this.parse(e.booleanOrStringAttr, key, keyOptions);
1684
1884
  }
1885
+ booleanOrNumber(key, keyOptions) {
1886
+ this.parse(e.booleanOrNumberAttr, key, keyOptions);
1887
+ }
1685
1888
  json(key, keyOptions) {
1686
1889
  this.parse(e.jsonAttr, key, keyOptions);
1687
1890
  }
@@ -1801,16 +2004,17 @@ up.Rect = class Rect extends up.Record {
1801
2004
  /***/ (() => {
1802
2005
 
1803
2006
  const e = up.element;
2007
+ const u = up.util;
1804
2008
  const SHIFT_CLASS = 'up-scrollbar-away';
1805
2009
  up.BodyShifter = class BodyShifter {
1806
2010
  constructor() {
1807
2011
  this._anchoredElements = new Set();
1808
2012
  this._stack = 0;
1809
- this._cleaners = [];
2013
+ this._cleaner = u.cleaner();
1810
2014
  }
1811
2015
  lowerStack() {
1812
2016
  if (--this._stack === 0)
1813
- this._unshiftNow();
2017
+ this._cleaner.clean();
1814
2018
  }
1815
2019
  raiseStack() {
1816
2020
  if (++this._stack === 1)
@@ -1826,7 +2030,7 @@ up.BodyShifter = class BodyShifter {
1826
2030
  }
1827
2031
  _shiftNow() {
1828
2032
  this._rootScrollbarWidth = up.viewport.rootScrollbarWidth();
1829
- this._cleaners.push(e.setTemporaryStyle(e.root, {
2033
+ this._cleaner(e.setStyleTemp(e.root, {
1830
2034
  '--up-scrollbar-width': this._rootScrollbarWidth + 'px'
1831
2035
  }));
1832
2036
  this._shiftElement(document.body, 'padding-right');
@@ -1838,13 +2042,7 @@ up.BodyShifter = class BodyShifter {
1838
2042
  if (!this._isShifted())
1839
2043
  return;
1840
2044
  let originalValue = e.style(element, styleProp);
1841
- this._cleaners.push(e.setTemporaryStyle(element, { ['--up-original-' + styleProp]: originalValue }), e.addTemporaryClass(element, SHIFT_CLASS));
1842
- }
1843
- _unshiftNow() {
1844
- let cleaner;
1845
- while (cleaner = this._cleaners.pop()) {
1846
- cleaner();
1847
- }
2045
+ this._cleaner(e.setStyleTemp(element, { ['--up-original-' + styleProp]: originalValue }), e.addClassTemp(element, SHIFT_CLASS));
1848
2046
  }
1849
2047
  };
1850
2048
 
@@ -1861,9 +2059,6 @@ up.Change = class Change {
1861
2059
  execute() {
1862
2060
  throw new up.NotImplemented();
1863
2061
  }
1864
- onFinished(renderResult) {
1865
- return this.options.onFinished?.(renderResult);
1866
- }
1867
2062
  improveHistoryValue(existingValue, newValue) {
1868
2063
  if ((existingValue === false) || u.isString(existingValue)) {
1869
2064
  return existingValue;
@@ -1894,30 +2089,30 @@ up.Change.Addition = class Addition extends up.Change {
1894
2089
  }
1895
2090
  handleLayerChangeRequests() {
1896
2091
  if (this.layer.isOverlay()) {
1897
- this.tryAcceptLayerFromServer();
2092
+ this._tryAcceptLayerFromServer();
1898
2093
  this.abortWhenLayerClosed();
1899
- this.layer.tryAcceptForLocation(this.responseOption());
2094
+ this.layer.tryAcceptForLocation(this._responseOptions());
1900
2095
  this.abortWhenLayerClosed();
1901
- this.tryDismissLayerFromServer();
2096
+ this._tryDismissLayerFromServer();
1902
2097
  this.abortWhenLayerClosed();
1903
- this.layer.tryDismissForLocation(this.responseOption());
2098
+ this.layer.tryDismissForLocation(this._responseOptions());
1904
2099
  this.abortWhenLayerClosed();
1905
2100
  }
1906
2101
  this.layer.asCurrent(() => {
1907
2102
  for (let eventPlan of this._eventPlans) {
1908
- up.emit({ ...eventPlan, ...this.responseOption() });
2103
+ up.emit({ ...eventPlan, ...this._responseOptions() });
1909
2104
  this.abortWhenLayerClosed();
1910
2105
  }
1911
2106
  });
1912
2107
  }
1913
- tryAcceptLayerFromServer() {
2108
+ _tryAcceptLayerFromServer() {
1914
2109
  if (u.isDefined(this._acceptLayer) && this.layer.isOverlay()) {
1915
- this.layer.accept(this._acceptLayer, this.responseOption());
2110
+ this.layer.accept(this._acceptLayer, this._responseOptions());
1916
2111
  }
1917
2112
  }
1918
- tryDismissLayerFromServer() {
2113
+ _tryDismissLayerFromServer() {
1919
2114
  if (u.isDefined(this._dismissLayer) && this.layer.isOverlay()) {
1920
- this.layer.dismiss(this._dismissLayer, this.responseOption());
2115
+ this.layer.dismiss(this._dismissLayer, this._responseOptions());
1921
2116
  }
1922
2117
  }
1923
2118
  abortWhenLayerClosed(layer = this.layer) {
@@ -1925,7 +2120,7 @@ up.Change.Addition = class Addition extends up.Change {
1925
2120
  throw new up.Aborted('Layer was closed');
1926
2121
  }
1927
2122
  }
1928
- setSource({ oldElement, newElement, source }) {
2123
+ _setSource({ oldElement, newElement, source }) {
1929
2124
  if (source === 'keep') {
1930
2125
  source = (oldElement && up.fragment.source(oldElement));
1931
2126
  }
@@ -1933,18 +2128,18 @@ up.Change.Addition = class Addition extends up.Change {
1933
2128
  e.setMissingAttr(newElement, 'up-source', up.fragment.normalizeSource(source));
1934
2129
  }
1935
2130
  }
1936
- setTime({ newElement, time }) {
2131
+ _setTime({ newElement, time }) {
1937
2132
  e.setMissingAttr(newElement, 'up-time', time ? time.toUTCString() : false);
1938
2133
  }
1939
- setETag({ newElement, etag }) {
2134
+ _setETag({ newElement, etag }) {
1940
2135
  e.setMissingAttr(newElement, 'up-etag', etag || false);
1941
2136
  }
1942
2137
  setReloadAttrs(options) {
1943
- this.setSource(options);
1944
- this.setTime(options);
1945
- this.setETag(options);
2138
+ this._setSource(options);
2139
+ this._setTime(options);
2140
+ this._setETag(options);
1946
2141
  }
1947
- responseOption() {
2142
+ _responseOptions() {
1948
2143
  return { response: this._response };
1949
2144
  }
1950
2145
  executeSteps(steps, responseDoc, noneOptions) {
@@ -1969,8 +2164,10 @@ up.RenderJob = (_a = class RenderJob {
1969
2164
  }
1970
2165
  async _executePromise() {
1971
2166
  try {
1972
- this._guardRender();
2167
+ this._emitGuardEvent();
1973
2168
  this.options = up.RenderOptions.preprocess(this.options);
2169
+ up.browser.assertConfirmed(this.options);
2170
+ up.RenderOptions.assertContentGiven(this.options);
1974
2171
  let result = await this._getChange().execute();
1975
2172
  this._handleResult(result);
1976
2173
  return result;
@@ -2015,21 +2212,19 @@ up.RenderJob = (_a = class RenderJob {
2015
2212
  }
2016
2213
  }
2017
2214
  _getChange() {
2018
- if (this.options.url) {
2019
- let onRequest = (request) => this._handleAbortOption(request);
2020
- return new up.Change.FromURL({ ...this.options, onRequest });
2215
+ let handleAbort = u.memoize((request) => this._handleAbortOption(request));
2216
+ let renderOptions = { ...this.options, handleAbort };
2217
+ if (renderOptions.url) {
2218
+ return new up.Change.FromURL(renderOptions);
2021
2219
  }
2022
- else if (this.options.response) {
2023
- let onRender = () => this._handleAbortOption(null);
2024
- return new up.Change.FromResponse({ ...this.options, onRender });
2220
+ else if (renderOptions.response) {
2221
+ return new up.Change.FromResponse(renderOptions);
2025
2222
  }
2026
2223
  else {
2027
- let onRender = () => this._handleAbortOption(null);
2028
- return new up.Change.FromContent({ ...this.options, onRender });
2224
+ return new up.Change.FromContent(renderOptions);
2029
2225
  }
2030
2226
  }
2031
- _guardRender() {
2032
- up.browser.assertConfirmed(this.options);
2227
+ _emitGuardEvent() {
2033
2228
  let guardEvent = u.pluckKey(this.options, 'guardEvent');
2034
2229
  if (guardEvent) {
2035
2230
  guardEvent.renderOptions = this.options;
@@ -2037,24 +2232,23 @@ up.RenderJob = (_a = class RenderJob {
2037
2232
  throw new up.Aborted(`Rendering was prevented by ${guardEvent.type} listener`);
2038
2233
  }
2039
2234
  }
2040
- up.RenderOptions.assertContentGiven(this.options);
2041
2235
  }
2042
2236
  _handleAbortOption(request) {
2043
2237
  let { abort } = this.options;
2044
2238
  if (!abort || !up.network.isBusy())
2045
2239
  return;
2046
- let { fragments, layer, origin, newLayer } = this._getChange().getPreflightProps();
2240
+ let { bindFragments, bindLayer, origin, layer } = this._getChange().getPreflightProps();
2047
2241
  let abortOptions = {
2048
2242
  except: request,
2049
2243
  logOnce: ['up.render()', 'Change with { abort } option will abort other requests'],
2050
- newLayer,
2244
+ newLayer: (layer === 'new'),
2051
2245
  origin,
2052
2246
  };
2053
2247
  if (abort === 'target') {
2054
- up.fragment.abort(fragments, abortOptions);
2248
+ up.fragment.abort(bindFragments, { ...abortOptions });
2055
2249
  }
2056
2250
  else if (abort === 'layer') {
2057
- up.fragment.abort({ ...abortOptions, layer });
2251
+ up.fragment.abort({ ...abortOptions, layer: bindLayer });
2058
2252
  }
2059
2253
  else if (abort === 'all' || abort === true) {
2060
2254
  up.fragment.abort({ ...abortOptions, layer: 'any' });
@@ -2063,12 +2257,12 @@ up.RenderJob = (_a = class RenderJob {
2063
2257
  abort(abortOptions);
2064
2258
  }
2065
2259
  else {
2066
- up.fragment.abort(abort, { ...abortOptions, layer });
2260
+ up.fragment.abort(abort, { ...abortOptions, layer: bindLayer });
2067
2261
  }
2068
2262
  }
2069
2263
  },
2070
2264
  (() => {
2071
- u.delegate(_a.prototype, ['then', 'catch', 'finally'], function () { return this._rendered; });
2265
+ u.delegatePromise(_a.prototype, '_rendered');
2072
2266
  u.memoizeMethod(_a.prototype, {
2073
2267
  _awaitFinished: true,
2074
2268
  _getChange: true,
@@ -2081,21 +2275,14 @@ up.RenderJob = (_a = class RenderJob {
2081
2275
  /* 26 */
2082
2276
  /***/ (() => {
2083
2277
 
2084
- up.Change.Removal = class Removal extends up.Change {
2085
- };
2086
-
2087
-
2088
- /***/ }),
2089
- /* 27 */
2090
- /***/ (() => {
2091
-
2092
- up.Change.DestroyFragment = class DestroyFragment extends up.Change.Removal {
2278
+ up.Change.DestroyFragment = class DestroyFragment extends up.Change {
2093
2279
  constructor(options) {
2094
2280
  super(options);
2095
2281
  this._layer = up.layer.get(options) || up.layer.current;
2096
2282
  this._element = this.options.element;
2097
2283
  this._animation = this.options.animation;
2098
2284
  this._log = this.options.log;
2285
+ this._onFinished = this.options.onFinished;
2099
2286
  }
2100
2287
  execute() {
2101
2288
  this._parent = this._element.parentNode;
@@ -2111,12 +2298,12 @@ up.Change.DestroyFragment = class DestroyFragment extends up.Change.Removal {
2111
2298
  this._emitDestroyed();
2112
2299
  await this._animate();
2113
2300
  this._wipe();
2114
- this.onFinished();
2301
+ this._onFinished?.();
2115
2302
  }
2116
2303
  _destroyNow() {
2117
2304
  this._wipe();
2118
2305
  this._emitDestroyed();
2119
- this.onFinished();
2306
+ this._onFinished?.();
2120
2307
  }
2121
2308
  _animate() {
2122
2309
  return up.motion.animate(this._element, this._animation, this.options);
@@ -2136,7 +2323,7 @@ up.Change.DestroyFragment = class DestroyFragment extends up.Change.Removal {
2136
2323
 
2137
2324
 
2138
2325
  /***/ }),
2139
- /* 28 */
2326
+ /* 27 */
2140
2327
  /***/ (() => {
2141
2328
 
2142
2329
  let u = up.util;
@@ -2153,9 +2340,10 @@ up.Change.OpenLayer = class OpenLayer extends up.Change.Addition {
2153
2340
  context: this._buildLayer().context,
2154
2341
  origin: this.options.origin,
2155
2342
  target: this.target,
2156
- layer: this._baseLayer,
2157
- fragments: u.compact([up.fragment.get(':main', { layer: this._baseLayer })]),
2158
- newLayer: true,
2343
+ bindLayer: this._baseLayer,
2344
+ layer: 'new',
2345
+ bindFragments: u.compact([up.fragment.get(':main', { layer: this._baseLayer })]),
2346
+ fragments: [],
2159
2347
  };
2160
2348
  }
2161
2349
  execute(responseDoc, onApplicable) {
@@ -2205,7 +2393,7 @@ up.Change.OpenLayer = class OpenLayer extends up.Change.Addition {
2205
2393
  fragments: [this._content],
2206
2394
  target: this.target,
2207
2395
  });
2208
- up.hello(this.layer.element, { ...this.options, layer: this.layer });
2396
+ up.hello(this.layer.element, { ...this.options, layer: this.layer, dataRoot: this._content });
2209
2397
  this._handleScroll();
2210
2398
  this._newOverlayResult.finished = this._finish();
2211
2399
  this.layer.opening = false;
@@ -2290,7 +2478,7 @@ up.Change.OpenLayer = class OpenLayer extends up.Change.Addition {
2290
2478
 
2291
2479
 
2292
2480
  /***/ }),
2293
- /* 29 */
2481
+ /* 28 */
2294
2482
  /***/ (() => {
2295
2483
 
2296
2484
  var _a;
@@ -2306,14 +2494,16 @@ up.Change.UpdateLayer = (_a = class UpdateLayer extends up.Change.Addition {
2306
2494
  }
2307
2495
  getPreflightProps() {
2308
2496
  this._matchPreflight();
2497
+ let fragments = this._getFragments();
2309
2498
  return {
2310
2499
  layer: this.layer,
2500
+ bindLayer: this.layer,
2311
2501
  mode: this.layer.mode,
2312
2502
  context: u.merge(this.layer.context, this._context),
2313
2503
  origin: this.options.origin,
2314
2504
  target: this._bestPreflightSelector(),
2315
- fragments: this._getFragments(),
2316
- newLayer: false,
2505
+ fragments,
2506
+ bindFragments: fragments,
2317
2507
  };
2318
2508
  }
2319
2509
  _bestPreflightSelector() {
@@ -2439,7 +2629,7 @@ up.Change.UpdateLayer = (_a = class UpdateLayer extends up.Change.Addition {
2439
2629
 
2440
2630
 
2441
2631
  /***/ }),
2442
- /* 30 */
2632
+ /* 29 */
2443
2633
  /***/ (() => {
2444
2634
 
2445
2635
  const u = up.util;
@@ -2511,7 +2701,7 @@ up.Change.UpdateSteps = class UpdateSteps extends up.Change.Addition {
2511
2701
  up.script.clean(step.oldElement, { layer: step.layer });
2512
2702
  },
2513
2703
  afterDetach() {
2514
- up.element.cleanJQuery();
2704
+ e.cleanJQuery();
2515
2705
  up.fragment.emitDestroyed(step.oldElement, { parent, log: false });
2516
2706
  },
2517
2707
  scrollNew: () => {
@@ -2555,7 +2745,7 @@ up.Change.UpdateSteps = class UpdateSteps extends up.Change.Addition {
2555
2745
  }
2556
2746
  }
2557
2747
  _findKeepPlan(options) {
2558
- if (!options.useKeep) {
2748
+ if (!options.keep) {
2559
2749
  return;
2560
2750
  }
2561
2751
  const { oldElement, newElement } = options;
@@ -2570,7 +2760,7 @@ up.Change.UpdateSteps = class UpdateSteps extends up.Change.Addition {
2570
2760
  partner = up.fragment.get(newElement, partnerSelector, lookupOpts);
2571
2761
  }
2572
2762
  else {
2573
- partner = up.fragment.subtree(newElement, partnerSelector, lookupOpts)[0];
2763
+ partner = e.subtreeFirst(newElement, partnerSelector, lookupOpts);
2574
2764
  }
2575
2765
  if (partner && e.booleanAttr(partner, 'up-keep') !== false) {
2576
2766
  const plan = {
@@ -2586,7 +2776,7 @@ up.Change.UpdateSteps = class UpdateSteps extends up.Change.Addition {
2586
2776
  }
2587
2777
  _preserveKeepables(step) {
2588
2778
  const keepPlans = [];
2589
- if (step.useKeep) {
2779
+ if (step.keep) {
2590
2780
  for (let keepable of step.oldElement.querySelectorAll('[up-keep]')) {
2591
2781
  let keepPlan = this._findKeepPlan({ ...step, oldElement: keepable, descendantsOnly: true });
2592
2782
  if (keepPlan) {
@@ -2647,11 +2837,11 @@ up.Change.UpdateSteps = class UpdateSteps extends up.Change.Addition {
2647
2837
 
2648
2838
 
2649
2839
  /***/ }),
2650
- /* 31 */
2840
+ /* 30 */
2651
2841
  /***/ (() => {
2652
2842
 
2653
2843
  const u = up.util;
2654
- up.Change.CloseLayer = class CloseLayer extends up.Change.Removal {
2844
+ up.Change.CloseLayer = class CloseLayer extends up.Change {
2655
2845
  constructor(options) {
2656
2846
  super(options);
2657
2847
  this._verb = options.verb;
@@ -2723,27 +2913,26 @@ up.Change.CloseLayer = class CloseLayer extends up.Change.Removal {
2723
2913
 
2724
2914
 
2725
2915
  /***/ }),
2726
- /* 32 */
2916
+ /* 31 */
2727
2917
  /***/ (() => {
2728
2918
 
2729
2919
  var _a;
2730
2920
  const u = up.util;
2731
2921
  up.Change.FromURL = (_a = class FromURL extends up.Change {
2732
- execute() {
2733
- let _newPageReason = this._newPageReason();
2734
- if (_newPageReason) {
2735
- up.puts('up.render()', _newPageReason);
2922
+ async execute() {
2923
+ let newPageReason = this._newPageReason();
2924
+ if (newPageReason) {
2925
+ up.puts('up.render()', newPageReason);
2736
2926
  up.network.loadPage(this.options);
2737
2927
  return u.unresolvablePromise();
2738
2928
  }
2739
- this.request = up.request(this._getRequestAttrs());
2740
- this.options.onRequest?.(this.request);
2741
- up.feedback.showAroundRequest(this.request, this.options);
2742
- up.form.disableWhile(this.request, this.options);
2743
- if (this.options.preload) {
2744
- return this.request;
2745
- }
2746
- return u.always(this.request, responseOrError => this._onRequestSettled(responseOrError));
2929
+ let request = this.request = up.request(this._getRequestAttrs());
2930
+ this.options.onRequestKnown?.(request);
2931
+ if (this.options.preload)
2932
+ return request;
2933
+ this.options.handleAbort?.(request);
2934
+ request.runPreviews(this.options);
2935
+ return await u.always(request, responseOrError => this._onRequestSettled(responseOrError));
2747
2936
  }
2748
2937
  _newPageReason() {
2749
2938
  if (u.isCrossOrigin(this.options.url)) {
@@ -2759,15 +2948,15 @@ up.Change.FromURL = (_a = class FromURL extends up.Change {
2759
2948
  return {
2760
2949
  ...this.options,
2761
2950
  ...successAttrs,
2762
- ...u.renameKeys(failAttrs, up.fragment.failKey)
2951
+ ...u.withRenamedKeys(failAttrs, up.fragment.failKey),
2763
2952
  };
2764
2953
  }
2765
2954
  getPreflightProps() {
2766
2955
  return this._getRequestAttrs();
2767
2956
  }
2768
- _preflightPropsForRenderOptions(renderOptions, requestAttributesOptions) {
2769
- const preview = new up.Change.FromContent({ ...renderOptions, preview: true });
2770
- return preview.getPreflightProps(requestAttributesOptions);
2957
+ _preflightPropsForRenderOptions(renderOptions, getPreflightPropsOptions) {
2958
+ const preflightChange = new up.Change.FromContent({ ...renderOptions, preflight: true });
2959
+ return preflightChange.getPreflightProps(getPreflightPropsOptions);
2771
2960
  }
2772
2961
  _onRequestSettled(response) {
2773
2962
  if (response instanceof up.Response) {
@@ -2801,7 +2990,7 @@ up.Change.FromURL = (_a = class FromURL extends up.Change {
2801
2990
 
2802
2991
 
2803
2992
  /***/ }),
2804
- /* 33 */
2993
+ /* 32 */
2805
2994
  /***/ (() => {
2806
2995
 
2807
2996
  var _a;
@@ -2862,17 +3051,17 @@ up.Change.FromResponse = (_a = class FromResponse extends up.Change {
2862
3051
  up.puts('up.render()', 'Revalidating cached response for target "%s"', effectiveTarget);
2863
3052
  let verifyResult = await up.reload(effectiveTarget, {
2864
3053
  ...originalRenderOptions,
3054
+ ...up.RenderOptions.NO_MOTION,
3055
+ ...up.RenderOptions.NO_INPUT_INTERFERENCE,
3056
+ ...up.RenderOptions.NO_PREVIEWS,
2865
3057
  preferOldElements: renderResult.fragments,
2866
3058
  layer: renderResult.layer,
2867
3059
  onFinished: null,
2868
- scroll: false,
2869
- focus: 'keep',
2870
- transition: false,
2871
- cache: false,
2872
- confirm: false,
2873
- feedback: false,
2874
- abort: false,
2875
3060
  expiredResponse: this._response,
3061
+ preview: this._revalidatePreview(originalRenderOptions),
3062
+ abort: false,
3063
+ cache: false,
3064
+ background: true,
2876
3065
  });
2877
3066
  if (!verifyResult.none) {
2878
3067
  renderResult = verifyResult;
@@ -2880,6 +3069,14 @@ up.Change.FromResponse = (_a = class FromResponse extends up.Change {
2880
3069
  }
2881
3070
  return renderResult;
2882
3071
  }
3072
+ _revalidatePreview({ preview, revalidatePreview }) {
3073
+ if (revalidatePreview === true) {
3074
+ return preview;
3075
+ }
3076
+ else {
3077
+ return revalidatePreview;
3078
+ }
3079
+ }
2883
3080
  _loadedEventProps() {
2884
3081
  const { expiredResponse } = this.options;
2885
3082
  return {
@@ -2939,7 +3136,7 @@ up.Change.FromResponse = (_a = class FromResponse extends up.Change {
2939
3136
 
2940
3137
 
2941
3138
  /***/ }),
2942
- /* 34 */
3139
+ /* 33 */
2943
3140
  /***/ (() => {
2944
3141
 
2945
3142
  var _a;
@@ -2948,7 +3145,7 @@ up.Change.FromContent = (_a = class FromContent extends up.Change {
2948
3145
  constructor(options) {
2949
3146
  super(options);
2950
3147
  this._origin = options.origin;
2951
- this._preview = options.preview;
3148
+ this._preflight = options.preflight;
2952
3149
  this._layers = up.layer.getAll(options);
2953
3150
  }
2954
3151
  _getPlans() {
@@ -3000,10 +3197,10 @@ up.Change.FromContent = (_a = class FromContent extends up.Change {
3000
3197
  if (assets) {
3001
3198
  up.script.assertAssetsOK(assets, plan.options);
3002
3199
  }
3003
- this.options.onRender?.();
3200
+ this.options.handleAbort?.(null);
3004
3201
  }
3005
3202
  _getResponseDoc() {
3006
- if (this._preview)
3203
+ if (this._preflight)
3007
3204
  return;
3008
3205
  const docOptions = u.pick(this.options, [
3009
3206
  'target',
@@ -3013,6 +3210,7 @@ up.Change.FromContent = (_a = class FromContent extends up.Change {
3013
3210
  'html',
3014
3211
  'cspNonces',
3015
3212
  'origin',
3213
+ 'data',
3016
3214
  ]);
3017
3215
  up.migrate.handleResponseDocOptions?.(docOptions);
3018
3216
  if (this._defaultPlacement() === 'content') {
@@ -3021,7 +3219,7 @@ up.Change.FromContent = (_a = class FromContent extends up.Change {
3021
3219
  return new up.ResponseDoc(docOptions);
3022
3220
  }
3023
3221
  _improveOptionsFromResponseDoc() {
3024
- if (this._preview)
3222
+ if (this._preflight)
3025
3223
  return;
3026
3224
  let responseDoc = this._getResponseDoc();
3027
3225
  if (this.options.fragment) {
@@ -3093,17 +3291,18 @@ up.Change.FromContent = (_a = class FromContent extends up.Change {
3093
3291
 
3094
3292
 
3095
3293
  /***/ }),
3096
- /* 35 */
3294
+ /* 34 */
3097
3295
  /***/ (() => {
3098
3296
 
3099
3297
  const u = up.util;
3100
3298
  up.CompilerPass = class CompilerPass {
3101
- constructor(root, compilers, { layer, data, dataMap, meta }) {
3299
+ constructor(root, compilers, { layer, data, dataRoot, dataMap, meta }) {
3102
3300
  layer ||= up.layer.get(root) || up.layer.current;
3103
3301
  this._root = root;
3104
3302
  this._compilers = compilers;
3105
3303
  this._layer = layer;
3106
3304
  this._data = data;
3305
+ this._dataRoot = dataRoot || root;
3107
3306
  this._dataMap = dataMap;
3108
3307
  meta ||= {};
3109
3308
  meta.layer = layer;
@@ -3119,7 +3318,7 @@ up.CompilerPass = class CompilerPass {
3119
3318
  }
3120
3319
  setCompileData() {
3121
3320
  if (this._data) {
3122
- this._root.upCompileData = this._data;
3321
+ this._dataRoot.upCompileData = this._data;
3123
3322
  }
3124
3323
  if (this._dataMap) {
3125
3324
  for (let selector in this._dataMap) {
@@ -3154,10 +3353,7 @@ up.CompilerPass = class CompilerPass {
3154
3353
  compileArgs.push(data, this._meta);
3155
3354
  }
3156
3355
  const result = this._applyCompilerFunction(compiler, element, compileArgs);
3157
- let destructorOrDestructors = this._destructorPresence(result);
3158
- if (destructorOrDestructors) {
3159
- up.destructor(element, destructorOrDestructors);
3160
- }
3356
+ up.destructor(element, result);
3161
3357
  }
3162
3358
  _compileBatch(compiler, elements) {
3163
3359
  const compileArgs = [elements];
@@ -3166,18 +3362,13 @@ up.CompilerPass = class CompilerPass {
3166
3362
  compileArgs.push(dataList, this._meta);
3167
3363
  }
3168
3364
  const result = this._applyCompilerFunction(compiler, elements, compileArgs);
3169
- if (this._destructorPresence(result)) {
3365
+ if (result) {
3170
3366
  up.fail('Compilers with { batch: true } cannot return destructors');
3171
3367
  }
3172
3368
  }
3173
3369
  _applyCompilerFunction(compiler, elementOrElements, compileArgs) {
3174
3370
  return up.error.guard(() => compiler.apply(elementOrElements, compileArgs));
3175
3371
  }
3176
- _destructorPresence(result) {
3177
- if (u.isFunction(result) || (u.isArray(result) && (u.every(result, u.isFunction)))) {
3178
- return result;
3179
- }
3180
- }
3181
3372
  _select(selector) {
3182
3373
  return up.fragment.subtree(this._root, u.evalOption(selector), { layer: this._layer });
3183
3374
  }
@@ -3195,7 +3386,7 @@ up.CompilerPass = class CompilerPass {
3195
3386
 
3196
3387
 
3197
3388
  /***/ }),
3198
- /* 36 */
3389
+ /* 35 */
3199
3390
  /***/ (() => {
3200
3391
 
3201
3392
  const u = up.util;
@@ -3279,7 +3470,7 @@ up.CSSTransition = class CSSTransition {
3279
3470
  if (oldTransition['transition-property'] !== 'all') {
3280
3471
  const oldTransitionProperties = oldTransition['transition-property'].split(/\s*,\s*/);
3281
3472
  const oldTransitionFrame = e.style(this._element, oldTransitionProperties);
3282
- this._setOldTransitionTargetFrame = e.setTemporaryStyle(this._element, oldTransitionFrame);
3473
+ this._setOldTransitionTargetFrame = e.setStyleTemp(this._element, oldTransitionFrame);
3283
3474
  }
3284
3475
  this._setOldTransition = e.concludeCSSTransition(this._element);
3285
3476
  }
@@ -3300,7 +3491,7 @@ up.CSSTransition = class CSSTransition {
3300
3491
 
3301
3492
 
3302
3493
  /***/ }),
3303
- /* 37 */
3494
+ /* 36 */
3304
3495
  /***/ (() => {
3305
3496
 
3306
3497
  const u = up.util;
@@ -3311,27 +3502,19 @@ up.DestructorPass = class DestructorPass {
3311
3502
  }
3312
3503
  run() {
3313
3504
  for (let cleanable of this._selectCleanables()) {
3314
- let destructors = u.pluckKey(cleanable, 'upDestructors');
3315
- if (destructors) {
3316
- for (let destructor of destructors) {
3317
- this._applyDestructorFunction(destructor, cleanable);
3318
- }
3319
- }
3320
- cleanable.classList.remove('up-can-clean');
3505
+ let registry = u.pluckKey(cleanable, 'upDestructors');
3506
+ registry?.clean(cleanable);
3321
3507
  }
3322
3508
  }
3323
3509
  _selectCleanables() {
3324
3510
  const selectOptions = { ...this._options, destroying: true };
3325
3511
  return up.fragment.subtree(this._fragment, '.up-can-clean', selectOptions);
3326
3512
  }
3327
- _applyDestructorFunction(destructor, element) {
3328
- up.error.guard(() => destructor(element));
3329
- }
3330
3513
  };
3331
3514
 
3332
3515
 
3333
3516
  /***/ }),
3334
- /* 38 */
3517
+ /* 37 */
3335
3518
  /***/ (() => {
3336
3519
 
3337
3520
  const u = up.util;
@@ -3393,7 +3576,7 @@ up.EventEmitter = class EventEmitter extends up.Record {
3393
3576
  static fromEmitArgs(args, defaults = {}) {
3394
3577
  let options = u.extractOptions(args);
3395
3578
  options = u.merge(defaults, options);
3396
- if (u.isElementish(args[0])) {
3579
+ if (u.isElementLike(args[0])) {
3397
3580
  options.target = e.get(args.shift());
3398
3581
  }
3399
3582
  else if (args[0] instanceof up.Layer) {
@@ -3430,7 +3613,7 @@ up.EventEmitter = class EventEmitter extends up.Record {
3430
3613
 
3431
3614
 
3432
3615
  /***/ }),
3433
- /* 39 */
3616
+ /* 38 */
3434
3617
  /***/ (() => {
3435
3618
 
3436
3619
  const u = up.util;
@@ -3534,7 +3717,7 @@ up.EventListener = class EventListener extends up.Record {
3534
3717
 
3535
3718
 
3536
3719
  /***/ }),
3537
- /* 40 */
3720
+ /* 39 */
3538
3721
  /***/ (() => {
3539
3722
 
3540
3723
  const u = up.util;
@@ -3554,13 +3737,13 @@ up.EventListenerGroup = class EventListenerGroup extends up.Record {
3554
3737
  ];
3555
3738
  }
3556
3739
  bind() {
3557
- const unbindFns = [];
3740
+ const cleaner = u.cleaner();
3558
3741
  this._eachListenerAttributes(function (attrs) {
3559
3742
  const listener = new up.EventListener(attrs);
3560
3743
  listener.bind();
3561
- return unbindFns.push(listener.unbind.bind(listener));
3744
+ return cleaner(listener.unbind.bind(listener));
3562
3745
  });
3563
- return u.sequence(unbindFns);
3746
+ return cleaner.clean;
3564
3747
  }
3565
3748
  _eachListenerAttributes(fn) {
3566
3749
  for (let element of this.elements) {
@@ -3593,7 +3776,7 @@ up.EventListenerGroup = class EventListenerGroup extends up.Record {
3593
3776
  else {
3594
3777
  elements = [document];
3595
3778
  }
3596
- let eventTypes = u.parseTokens(args.shift());
3779
+ let eventTypes = u.getSimpleTokens(args.shift());
3597
3780
  let fixTypes = up.migrate.fixEventTypes;
3598
3781
  if (fixTypes) {
3599
3782
  eventTypes = fixTypes(eventTypes);
@@ -3607,7 +3790,7 @@ up.EventListenerGroup = class EventListenerGroup extends up.Record {
3607
3790
 
3608
3791
 
3609
3792
  /***/ }),
3610
- /* 41 */
3793
+ /* 40 */
3611
3794
  /***/ (() => {
3612
3795
 
3613
3796
  const u = up.util;
@@ -3618,26 +3801,24 @@ up.FieldWatcher = class FieldWatcher {
3618
3801
  this._scope = up.form.getScope(root);
3619
3802
  this._callback = callback;
3620
3803
  this._batch = options.batch;
3621
- this._abortable = options.abortable;
3622
3804
  }
3623
3805
  start() {
3624
3806
  this._scheduledValues = null;
3625
3807
  this._processedValues = this._readFieldValues();
3626
3808
  this._currentTimer = null;
3627
3809
  this._callbackRunning = false;
3628
- this._unbindFns = [];
3810
+ this._cleaner = u.cleaner();
3629
3811
  this._watchFieldsWithin(this._root);
3630
3812
  this._root.addEventListener('up:fragment:inserted', ({ target }) => {
3631
3813
  if (target !== this._root)
3632
3814
  this._watchFieldsWithin(target);
3633
3815
  });
3634
- this._unbindFns.push(up.fragment.onAborted(this._scope, () => this._abort()));
3635
- this._unbindFns.push(up.on(this._scope, 'reset', () => this._onFormReset()));
3816
+ this._cleaner(up.fragment.onAborted(this._scope, () => this._abort()));
3817
+ this._cleaner(up.on(this._scope, 'reset', () => this._onFormReset()));
3636
3818
  }
3637
3819
  stop() {
3638
3820
  this._abort();
3639
- for (let unbindFn of this._unbindFns)
3640
- unbindFn();
3821
+ this._cleaner.clean();
3641
3822
  }
3642
3823
  _fieldOptions(field) {
3643
3824
  let rootOptions = u.copy(this._options);
@@ -3650,7 +3831,7 @@ up.FieldWatcher = class FieldWatcher {
3650
3831
  }
3651
3832
  _watchField(field) {
3652
3833
  let fieldOptions = this._fieldOptions(field);
3653
- this._unbindFns.push(up.on(field, fieldOptions.event, () => this._check(fieldOptions)));
3834
+ this._cleaner(up.on(field, fieldOptions.event, () => this._check(fieldOptions)));
3654
3835
  }
3655
3836
  _abort() {
3656
3837
  this._scheduledValues = null;
@@ -3677,13 +3858,12 @@ up.FieldWatcher = class FieldWatcher {
3677
3858
  return;
3678
3859
  if (!this._scope.isConnected)
3679
3860
  return;
3680
- let fieldOptions = this._scheduledFieldOptions;
3861
+ let callbackOptions = u.omit(this._scheduledFieldOptions, ['event', 'delay']);
3681
3862
  const diff = this._changedValues(this._processedValues, this._scheduledValues);
3682
3863
  this._processedValues = this._scheduledValues;
3683
3864
  this._scheduledValues = null;
3684
3865
  this._callbackRunning = true;
3685
3866
  this._scheduledFieldOptions = null;
3686
- let callbackOptions = { ...fieldOptions, disable: false };
3687
3867
  const callbackReturnValues = [];
3688
3868
  if (this._batch) {
3689
3869
  callbackReturnValues.push(this._runCallback(diff, callbackOptions));
@@ -3696,14 +3876,13 @@ up.FieldWatcher = class FieldWatcher {
3696
3876
  }
3697
3877
  if (u.some(callbackReturnValues, u.isPromise)) {
3698
3878
  let callbackDone = Promise.allSettled(callbackReturnValues);
3699
- up.form.disableWhile(callbackDone, fieldOptions);
3700
3879
  await callbackDone;
3701
3880
  }
3702
3881
  this._callbackRunning = false;
3703
3882
  this._requestCallback();
3704
3883
  }
3705
3884
  _runCallback(...args) {
3706
- return up.error.guard(() => this._callback(...args));
3885
+ return up.error.guard(this._callback, ...args);
3707
3886
  }
3708
3887
  _changedValues(previous, next) {
3709
3888
  const changes = {};
@@ -3735,7 +3914,7 @@ up.FieldWatcher = class FieldWatcher {
3735
3914
 
3736
3915
 
3737
3916
  /***/ }),
3738
- /* 42 */
3917
+ /* 41 */
3739
3918
  /***/ (() => {
3740
3919
 
3741
3920
  const u = up.util;
@@ -3854,47 +4033,52 @@ up.FormValidator = class FormValidator {
3854
4033
  return;
3855
4034
  if (this._nextRenderTimer)
3856
4035
  return;
3857
- let dirtySolutions = this._dirtySolutions;
4036
+ let options = this._mergeRenderOptions(this._dirtySolutions);
3858
4037
  this._dirtySolutions = [];
4038
+ this._rendering = true;
4039
+ let renderingPromise = this._nextRenderPromise;
4040
+ this._resetNextRenderPromise();
4041
+ try {
4042
+ renderingPromise.resolve(up.render(options));
4043
+ await renderingPromise;
4044
+ }
4045
+ finally {
4046
+ this._rendering = false;
4047
+ this._renderDirtySolutions();
4048
+ }
4049
+ }
4050
+ _mergeRenderOptions(dirtySolutions) {
3859
4051
  let dirtyOrigins = u.map(dirtySolutions, 'origin');
3860
4052
  let dirtyFields = u.flatMap(dirtyOrigins, up.form.fields);
3861
4053
  let dirtyNames = u.uniq(u.map(dirtyFields, 'name'));
3862
- let dataMap = this._buildDataMap(dirtySolutions);
3863
4054
  let dirtyRenderOptionsList = u.map(dirtySolutions, 'renderOptions');
3864
- let options = u.mergeDefined(...dirtyRenderOptionsList, { dataMap }, up.form.destinationOptions(this._form));
4055
+ let options = u.mergeDefined(...dirtyRenderOptionsList, up.form.destinationOptions(this._form));
3865
4056
  options.target = u.map(dirtySolutions, 'target').join(', ');
3866
- options.feedback = u.some(dirtyRenderOptionsList, 'feedback');
3867
4057
  options.origin = this._form;
3868
4058
  options.focus ??= 'keep';
3869
4059
  options.failOptions = false;
3870
4060
  options.defaultMaybe = true;
3871
4061
  options.params = up.Params.merge(options.params, ...u.map(dirtyRenderOptionsList, 'params'));
3872
- options.headers = u.merge(...u.map(dirtyRenderOptionsList, 'headers'));
4062
+ options.headers = u.merge(options.headers, ...u.map(dirtyRenderOptionsList, 'headers'));
3873
4063
  this._addValidateHeader(options.headers, dirtyNames);
4064
+ options.feedback = u.some(dirtyRenderOptionsList, 'feedback');
4065
+ options.data = undefined;
4066
+ options.dataMap = u.mapObject(dirtySolutions, ({ target, element, renderOptions: { data, keepData } }) => [
4067
+ target,
4068
+ keepData ? up.data(element) : data
4069
+ ]);
4070
+ options.preview = undefined;
4071
+ options.previewMap = u.mapObject(dirtySolutions, ({ target, renderOptions: { preview } }) => [target, preview]);
4072
+ options.placeholder = undefined;
4073
+ options.placeholderMap = u.mapObject(dirtySolutions, ({ target, renderOptions: { placeholder } }) => [target, placeholder]);
4074
+ options.disable = dirtySolutions.map((solution) => up.fragment.resolveOrigin(solution.renderOptions.disable, solution));
3874
4075
  options.guardEvent = up.event.build('up:form:validate', {
3875
4076
  fields: dirtyFields,
3876
4077
  log: 'Validating form',
3877
4078
  params: options.params,
3878
4079
  form: this._form,
3879
4080
  });
3880
- this._rendering = true;
3881
- let renderingPromise = this._nextRenderPromise;
3882
- this._resetNextRenderPromise();
3883
- options.disable = false;
3884
- for (let solution of dirtySolutions) {
3885
- up.form.disableWhile(renderingPromise, {
3886
- disable: solution.renderOptions.disable,
3887
- origin: solution.origin,
3888
- });
3889
- }
3890
- try {
3891
- renderingPromise.resolve(up.render(options));
3892
- await renderingPromise;
3893
- }
3894
- finally {
3895
- this._rendering = false;
3896
- this._renderDirtySolutions();
3897
- }
4081
+ return options;
3898
4082
  }
3899
4083
  _addValidateHeader(headers, names) {
3900
4084
  let key = up.protocol.headerize('validate');
@@ -3903,20 +4087,6 @@ up.FormValidator = class FormValidator {
3903
4087
  value = ':unknown';
3904
4088
  headers[key] = value;
3905
4089
  }
3906
- _buildDataMap(solutions) {
3907
- let dataMap = {};
3908
- for (let solution of solutions) {
3909
- let data = u.pluckKey(solution.renderOptions, 'data');
3910
- let keepData = u.pluckKey(solution.renderOptions, 'keepData');
3911
- if (keepData) {
3912
- data = up.data(solution.element);
3913
- }
3914
- if (data) {
3915
- dataMap[solution.target] = data;
3916
- }
3917
- }
3918
- return dataMap;
3919
- }
3920
4090
  static forElement(element) {
3921
4091
  let form = up.form.get(element);
3922
4092
  return form.upFormValidator ||= new this(form);
@@ -3925,19 +4095,23 @@ up.FormValidator = class FormValidator {
3925
4095
 
3926
4096
 
3927
4097
  /***/ }),
3928
- /* 43 */
4098
+ /* 42 */
3929
4099
  /***/ (() => {
3930
4100
 
3931
4101
  up.FocusCapsule = class FocusCapsule {
3932
- constructor(target, cursorProps) {
4102
+ constructor(element, target, cursorProps) {
4103
+ this._element = element;
3933
4104
  this._target = target;
3934
4105
  this._cursorProps = cursorProps;
3935
4106
  }
3936
- restore(layer, options) {
4107
+ wasLost() {
4108
+ return document.activeElement !== this._element;
4109
+ }
4110
+ restore(layer, focusOptions) {
3937
4111
  let rediscoveredElement = up.fragment.get(this._target, { layer });
3938
4112
  if (rediscoveredElement) {
3939
4113
  up.viewport.copyCursorProps(this._cursorProps, rediscoveredElement);
3940
- up.focus(rediscoveredElement, options);
4114
+ up.focus(rediscoveredElement, focusOptions);
3941
4115
  return true;
3942
4116
  }
3943
4117
  }
@@ -3949,13 +4123,13 @@ up.FocusCapsule = class FocusCapsule {
3949
4123
  if (!target)
3950
4124
  return;
3951
4125
  const cursorProps = up.viewport.copyCursorProps(focusedElement);
3952
- return new this(target, cursorProps);
4126
+ return new this(focusedElement, target, cursorProps);
3953
4127
  }
3954
4128
  };
3955
4129
 
3956
4130
 
3957
4131
  /***/ }),
3958
- /* 44 */
4132
+ /* 43 */
3959
4133
  /***/ (() => {
3960
4134
 
3961
4135
  const u = up.util;
@@ -3973,14 +4147,14 @@ up.FragmentProcessor = class FragmentProcessor extends up.Record {
3973
4147
  return this.tryProcess(preprocessed);
3974
4148
  }
3975
4149
  preprocess(opt) {
3976
- return u.parseTokens(opt, { separator: 'or' });
4150
+ return u.getComplexTokens(opt);
3977
4151
  }
3978
4152
  tryProcess(opt) {
3979
4153
  if (u.isArray(opt)) {
3980
4154
  return this.processArray(opt);
3981
4155
  }
3982
4156
  if (u.isFunction(opt)) {
3983
- let result = up.error.guard(() => opt(this.fragment, this.attributes()));
4157
+ let result = up.error.guard(opt, this.fragment, this.attributes());
3984
4158
  return this.tryProcess(result);
3985
4159
  }
3986
4160
  if (u.isElement(opt)) {
@@ -4020,7 +4194,7 @@ up.FragmentProcessor = class FragmentProcessor extends up.Record {
4020
4194
 
4021
4195
 
4022
4196
  /***/ }),
4023
- /* 45 */
4197
+ /* 44 */
4024
4198
  /***/ (() => {
4025
4199
 
4026
4200
  const u = up.util;
@@ -4057,19 +4231,19 @@ up.FragmentFinder = class FragmentFinder {
4057
4231
  if (parts) {
4058
4232
  let parent = up.fragment.closest(this._origin, parts[1], this._options);
4059
4233
  if (parent) {
4060
- return up.fragment.getDumb(parent, parts[2]);
4234
+ return up.fragment.getFirstDescendant(parent, parts[2]);
4061
4235
  }
4062
4236
  }
4063
4237
  });
4064
4238
  }
4065
4239
  _findFirst() {
4066
- return up.fragment.getDumb(this._document, this._selector, this._options);
4240
+ return up.fragment.getFirstDescendant(this._document, this._selector, this._options);
4067
4241
  }
4068
4242
  };
4069
4243
 
4070
4244
 
4071
4245
  /***/ }),
4072
- /* 46 */
4246
+ /* 45 */
4073
4247
  /***/ (() => {
4074
4248
 
4075
4249
  const u = up.util;
@@ -4130,7 +4304,7 @@ up.FragmentFocus = class FragmentFocus extends up.FragmentProcessor {
4130
4304
  return up.viewport.restoreFocus({ layer: this.layer });
4131
4305
  }
4132
4306
  _autofocus() {
4133
- let autofocusElement = this.fragment && e.subtree(this.fragment, '[autofocus]')[0];
4307
+ let autofocusElement = this.fragment && e.subtreeFirst(this.fragment, '[autofocus]');
4134
4308
  if (autofocusElement) {
4135
4309
  return this._focusElement(autofocusElement);
4136
4310
  }
@@ -4148,13 +4322,13 @@ up.FragmentFocus = class FragmentFocus extends up.FragmentProcessor {
4148
4322
  }
4149
4323
  }
4150
4324
  _wasFocusLost() {
4151
- return !this.layer.hasFocus();
4325
+ return this.focusCapsule?.wasLost();
4152
4326
  }
4153
4327
  };
4154
4328
 
4155
4329
 
4156
4330
  /***/ }),
4157
- /* 47 */
4331
+ /* 46 */
4158
4332
  /***/ (() => {
4159
4333
 
4160
4334
  const e = up.element;
@@ -4223,17 +4397,17 @@ up.FragmentPolling = class FragmentPolling {
4223
4397
  (this._options.ifLayer === 'any' || this._isOnFrontLayer());
4224
4398
  }
4225
4399
  _clearReloadTimer() {
4226
- clearTimeout(this.reloadTimer);
4227
- this.reloadTimer = null;
4400
+ clearTimeout(this._reloadTimer);
4401
+ this._reloadTimer = null;
4228
4402
  }
4229
4403
  _scheduleRemainingTime() {
4230
- if (!this.reloadTimer && !this._loading) {
4404
+ if (!this._reloadTimer && !this._loading) {
4231
4405
  this._clearReloadTimer();
4232
- this.reloadTimer = setTimeout(this._onTimerReached.bind(this), this._getRemainingDelay());
4406
+ this._reloadTimer = setTimeout(this._onTimerReached.bind(this), this._getRemainingDelay());
4233
4407
  }
4234
4408
  }
4235
4409
  _onTimerReached() {
4236
- this.reloadTimer = null;
4410
+ this._reloadTimer = null;
4237
4411
  this._tryReload();
4238
4412
  }
4239
4413
  _tryReload() {
@@ -4309,7 +4483,7 @@ up.FragmentPolling = class FragmentPolling {
4309
4483
 
4310
4484
 
4311
4485
  /***/ }),
4312
- /* 48 */
4486
+ /* 47 */
4313
4487
  /***/ (() => {
4314
4488
 
4315
4489
  const u = up.util;
@@ -4373,7 +4547,7 @@ up.FragmentScrolling = class FragmentScrolling extends up.FragmentProcessor {
4373
4547
 
4374
4548
 
4375
4549
  /***/ }),
4376
- /* 49 */
4550
+ /* 48 */
4377
4551
  /***/ (() => {
4378
4552
 
4379
4553
  const e = up.element;
@@ -4639,285 +4813,294 @@ up.Layer = class Layer extends up.Record {
4639
4813
 
4640
4814
 
4641
4815
  /***/ }),
4642
- /* 50 */
4816
+ /* 49 */
4643
4817
  /***/ (() => {
4644
4818
 
4819
+ var _a;
4645
4820
  const e = up.element;
4646
4821
  const u = up.util;
4647
- up.Layer.Overlay = class Overlay extends up.Layer {
4648
- keys() {
4649
- return super.keys().concat([
4650
- 'position',
4651
- 'align',
4652
- 'size',
4653
- 'origin',
4654
- 'class',
4655
- 'backdrop',
4656
- 'openAnimation',
4657
- 'closeAnimation',
4658
- 'openDuration',
4659
- 'closeDuration',
4660
- 'openEasing',
4661
- 'closeEasing',
4662
- 'backdropOpenAnimation',
4663
- 'backdropCloseAnimation',
4664
- 'dismissable',
4665
- 'dismissLabel',
4666
- 'dismissAriaLabel',
4667
- 'trapFocus',
4668
- 'onOpened',
4669
- 'onAccept',
4670
- 'onAccepted',
4671
- 'onDismiss',
4672
- 'onDismissed',
4673
- 'acceptEvent',
4674
- 'dismissEvent',
4675
- 'acceptLocation',
4676
- 'dismissLocation',
4677
- 'opening'
4678
- ]);
4679
- }
4680
- constructor(options) {
4681
- super(options);
4682
- if (this.dismissable === true) {
4683
- this.dismissable = ['button', 'key', 'outside'];
4822
+ up.Layer.Overlay = (_a = class Overlay extends up.Layer {
4823
+ keys() {
4824
+ return [
4825
+ ...super.keys(),
4826
+ ...this.constructor.VISUAL_KEYS,
4827
+ 'onOpened',
4828
+ 'onAccept',
4829
+ 'onAccepted',
4830
+ 'onDismiss',
4831
+ 'onDismissed',
4832
+ 'acceptEvent',
4833
+ 'dismissEvent',
4834
+ 'acceptLocation',
4835
+ 'dismissLocation',
4836
+ 'opening'
4837
+ ];
4684
4838
  }
4685
- else if (this.dismissable === false) {
4686
- this.dismissable = [];
4839
+ constructor(options) {
4840
+ super(options);
4841
+ if (this.dismissable === true) {
4842
+ this.dismissable = ['button', 'key', 'outside'];
4843
+ }
4844
+ else if (this.dismissable === false) {
4845
+ this.dismissable = [];
4846
+ }
4847
+ else {
4848
+ this.dismissable = u.getSimpleTokens(this.dismissable);
4849
+ }
4850
+ if (this.acceptLocation) {
4851
+ this.acceptLocation = new up.URLPattern(this.acceptLocation);
4852
+ }
4853
+ if (this.dismissLocation) {
4854
+ this.dismissLocation = new up.URLPattern(this.dismissLocation);
4855
+ }
4687
4856
  }
4688
- else {
4689
- this.dismissable = u.parseTokens(this.dismissable);
4857
+ callback(name) {
4858
+ let fn = this[name];
4859
+ if (fn) {
4860
+ return fn.bind(this);
4861
+ }
4690
4862
  }
4691
- if (this.acceptLocation) {
4692
- this.acceptLocation = new up.URLPattern(this.acceptLocation);
4863
+ createElement(parentElement) {
4864
+ this.nesting ||= this._suggestVisualNesting();
4865
+ const elementAttrs = u.compactObject(u.pick(this, ['align', 'position', 'size', 'class', 'nesting']));
4866
+ this.element = this.affixPart(parentElement, null, elementAttrs);
4693
4867
  }
4694
- if (this.dismissLocation) {
4695
- this.dismissLocation = new up.URLPattern(this.dismissLocation);
4868
+ createBackdropElement(parentElement) {
4869
+ this.backdropElement = this.affixPart(parentElement, 'backdrop');
4696
4870
  }
4697
- }
4698
- callback(name) {
4699
- let fn = this[name];
4700
- if (fn) {
4701
- return fn.bind(this);
4871
+ createViewportElement(parentElement) {
4872
+ this.viewportElement = this.affixPart(parentElement, 'viewport', { 'up-viewport': '' });
4702
4873
  }
4703
- }
4704
- createElement(parentElement) {
4705
- this.nesting ||= this._suggestVisualNesting();
4706
- const elementAttrs = u.compactObject(u.pick(this, ['align', 'position', 'size', 'class', 'nesting']));
4707
- this.element = this.affixPart(parentElement, null, elementAttrs);
4708
- }
4709
- createBackdropElement(parentElement) {
4710
- this.backdropElement = this.affixPart(parentElement, 'backdrop');
4711
- }
4712
- createViewportElement(parentElement) {
4713
- this.viewportElement = this.affixPart(parentElement, 'viewport', { 'up-viewport': '' });
4714
- }
4715
- createBoxElement(parentElement) {
4716
- this.boxElement = this.affixPart(parentElement, 'box');
4717
- }
4718
- createContentElement(parentElement) {
4719
- this.contentElement = this.affixPart(parentElement, 'content');
4720
- }
4721
- setContent(content) {
4722
- this.contentElement.append(content);
4723
- this.onContentSet();
4724
- }
4725
- onContentSet() {
4726
- }
4727
- createDismissElement(parentElement) {
4728
- this.dismissElement = this.affixPart(parentElement, 'dismiss', {
4729
- 'up-dismiss': '":button"',
4730
- 'aria-label': this.dismissAriaLabel
4731
- });
4732
- return e.affix(this.dismissElement, 'span[aria-hidden="true"]', { text: this.dismissLabel });
4733
- }
4734
- affixPart(parentElement, part, options = {}) {
4735
- return e.affix(parentElement, this.selector(part), options);
4736
- }
4737
- static selector(part) {
4738
- return u.compact(['up', this.mode, part]).join('-');
4739
- }
4740
- _suggestVisualNesting() {
4741
- const { parent } = this;
4742
- if (this.mode === parent.mode) {
4743
- return 1 + parent._suggestVisualNesting();
4874
+ createBoxElement(parentElement) {
4875
+ this.boxElement = this.affixPart(parentElement, 'box');
4744
4876
  }
4745
- else {
4746
- return 0;
4877
+ createContentElement(parentElement) {
4878
+ this.contentElement = this.affixPart(parentElement, 'content');
4747
4879
  }
4748
- }
4749
- setupHandlers() {
4750
- super.setupHandlers();
4751
- this.overlayFocus = new up.OverlayFocus(this);
4752
- if (this._supportsDismissMethod('button')) {
4753
- this.createDismissElement(this.getBoxElement());
4754
- }
4755
- if (this._supportsDismissMethod('outside')) {
4756
- if (this.viewportElement) {
4757
- up.on(this.viewportElement, 'up:click', event => {
4758
- if (event.target === this.viewportElement) {
4759
- this._onOutsideClicked(event, true);
4760
- }
4761
- });
4880
+ setContent(content) {
4881
+ this.contentElement.append(content);
4882
+ this.onContentSet();
4883
+ }
4884
+ onContentSet() {
4885
+ }
4886
+ createDismissElement(parentElement) {
4887
+ this.dismissElement = this.affixPart(parentElement, 'dismiss', {
4888
+ 'up-dismiss': '":button"',
4889
+ 'aria-label': this.dismissARIALabel
4890
+ });
4891
+ return e.affix(this.dismissElement, 'span[aria-hidden="true"]', { text: this.dismissLabel });
4892
+ }
4893
+ affixPart(parentElement, part, options = {}) {
4894
+ return e.affix(parentElement, this.selector(part), options);
4895
+ }
4896
+ static selector(part) {
4897
+ return u.compact(['up', this.mode, part]).join('-');
4898
+ }
4899
+ _suggestVisualNesting() {
4900
+ const { parent } = this;
4901
+ if (this.mode === parent.mode) {
4902
+ return 1 + parent._suggestVisualNesting();
4762
4903
  }
4763
4904
  else {
4764
- this.unbindParentClicked = this.parent.on('up:click', (event, element) => {
4765
- if (!up.layer.isWithinForeignOverlay(element)) {
4766
- const originClicked = this.origin && this.origin.contains(element);
4767
- this._onOutsideClicked(event, originClicked);
4768
- }
4769
- });
4905
+ return 0;
4770
4906
  }
4771
4907
  }
4772
- if (this._supportsDismissMethod('key')) {
4773
- this.unbindEscapePressed = up.event.onEscape(event => this.onEscapePressed(event));
4908
+ setupHandlers() {
4909
+ super.setupHandlers();
4910
+ this.overlayFocus = new up.OverlayFocus(this);
4911
+ if (this._supportsDismissMethod('button')) {
4912
+ this.createDismissElement(this.getBoxElement());
4913
+ }
4914
+ if (this._supportsDismissMethod('outside')) {
4915
+ if (this.viewportElement) {
4916
+ up.on(this.viewportElement, 'up:click', event => {
4917
+ if (event.target === this.viewportElement) {
4918
+ this._onOutsideClicked(event, true);
4919
+ }
4920
+ });
4921
+ }
4922
+ else {
4923
+ this.unbindParentClicked = this.parent.on('up:click', (event, element) => {
4924
+ if (!up.layer.isWithinForeignOverlay(element)) {
4925
+ const originClicked = this.origin && this.origin.contains(element);
4926
+ this._onOutsideClicked(event, originClicked);
4927
+ }
4928
+ });
4929
+ }
4930
+ }
4931
+ if (this._supportsDismissMethod('key')) {
4932
+ this.unbindEscapePressed = up.event.onEscape(event => this.onEscapePressed(event));
4933
+ }
4934
+ this.registerClickCloser('up-accept', (value, closeOptions) => {
4935
+ this.accept(value, closeOptions);
4936
+ });
4937
+ this.registerClickCloser('up-dismiss', (value, closeOptions) => {
4938
+ this.dismiss(value, closeOptions);
4939
+ });
4940
+ up.migrate.registerLayerCloser?.(this);
4941
+ this._registerEventCloser(this.acceptEvent, this.accept);
4942
+ this._registerEventCloser(this.dismissEvent, this.dismiss);
4943
+ this.on('up:click', 'label[for]', (event, label) => this._onLabelClicked(event, label));
4944
+ }
4945
+ _onLabelClicked(event, label) {
4946
+ let id = label.getAttribute('for');
4947
+ let fieldSelector = up.form.fieldSelector(e.idSelector(id));
4948
+ let fieldsAnywhere = up.fragment.all(fieldSelector, { layer: 'any' });
4949
+ let fieldsInLayer = up.fragment.all(fieldSelector, { layer: this });
4950
+ if (fieldsAnywhere.length > 1 && fieldsInLayer[0] !== fieldsAnywhere[0]) {
4951
+ event.preventDefault();
4952
+ const field = fieldsInLayer[0];
4953
+ field.focus();
4954
+ if (field.matches('input[type=checkbox], input[type=radio]')) {
4955
+ field.click();
4956
+ }
4957
+ }
4774
4958
  }
4775
- this.registerClickCloser('up-accept', (value, closeOptions) => {
4776
- this.accept(value, closeOptions);
4777
- });
4778
- this.registerClickCloser('up-dismiss', (value, closeOptions) => {
4779
- this.dismiss(value, closeOptions);
4780
- });
4781
- up.migrate.registerLayerCloser?.(this);
4782
- this._registerEventCloser(this.acceptEvent, this.accept);
4783
- this._registerEventCloser(this.dismissEvent, this.dismiss);
4784
- this.on('up:click', 'label[for]', (event, label) => this._onLabelClicked(event, label));
4785
- }
4786
- _onLabelClicked(event, label) {
4787
- let id = label.getAttribute('for');
4788
- let fieldSelector = up.form.fieldSelector(e.idSelector(id));
4789
- let fieldsAnywhere = up.fragment.all(fieldSelector, { layer: 'any' });
4790
- let fieldsInLayer = up.fragment.all(fieldSelector, { layer: this });
4791
- if (fieldsAnywhere.length > 1 && fieldsInLayer[0] !== fieldsAnywhere[0]) {
4792
- event.preventDefault();
4793
- const field = fieldsInLayer[0];
4794
- field.focus();
4795
- if (field.matches('input[type=checkbox], input[type=radio]')) {
4796
- field.click();
4797
- }
4798
- }
4799
- }
4800
- _onOutsideClicked(event, halt) {
4801
- up.log.putsEvent(event);
4802
- if (halt)
4803
- up.event.halt(event);
4804
- up.error.muteUncriticalSync(() => this.dismiss(':outside', { origin: event.target }));
4805
- }
4806
- onEscapePressed(event) {
4807
- if (this.isFront()) {
4808
- let field = up.form.focusedField();
4809
- if (field) {
4810
- field.blur();
4959
+ _onOutsideClicked(event, halt) {
4960
+ up.log.putsEvent(event);
4961
+ if (halt)
4962
+ up.event.halt(event);
4963
+ up.error.muteUncriticalSync(() => this.dismiss(':outside', { origin: event.target }));
4964
+ }
4965
+ onEscapePressed(event) {
4966
+ if (this.isFront()) {
4967
+ let field = up.form.focusedField();
4968
+ if (field) {
4969
+ field.blur();
4970
+ }
4971
+ else if (this._supportsDismissMethod('key')) {
4972
+ up.event.halt(event, { log: true });
4973
+ up.error.muteUncriticalSync(() => this.dismiss(':key'));
4974
+ }
4811
4975
  }
4812
- else if (this._supportsDismissMethod('key')) {
4976
+ }
4977
+ registerClickCloser(attribute, closeFn) {
4978
+ let selector = `[${attribute}]`;
4979
+ this.on('up:click', selector, function (event) {
4813
4980
  up.event.halt(event, { log: true });
4814
- up.error.muteUncriticalSync(() => this.dismiss(':key'));
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));
4990
+ });
4991
+ }
4992
+ _registerEventCloser(eventTypes, closeFn) {
4993
+ if (!eventTypes) {
4994
+ return;
4815
4995
  }
4996
+ return this.on(eventTypes, event => {
4997
+ event.preventDefault();
4998
+ up.error.muteUncriticalSync(() => closeFn.call(this, event, { response: event.response }));
4999
+ });
4816
5000
  }
4817
- }
4818
- registerClickCloser(attribute, closeFn) {
4819
- let selector = `[${attribute}]`;
4820
- this.on('up:click', selector, function (event) {
4821
- up.event.halt(event, { log: true });
4822
- const origin = event.target.closest(selector);
4823
- const value = e.jsonAttr(origin, attribute);
4824
- const closeOptions = { origin };
4825
- const parser = new up.OptionsParser(origin, closeOptions);
4826
- parser.booleanOrString('animation');
4827
- parser.string('easing');
4828
- parser.number('duration');
4829
- parser.string('confirm');
4830
- up.error.muteUncriticalSync(() => closeFn(value, closeOptions));
4831
- });
4832
- }
4833
- _registerEventCloser(eventTypes, closeFn) {
4834
- if (!eventTypes) {
4835
- return;
5001
+ tryAcceptForLocation(options) {
5002
+ this._tryCloseForLocation(this.acceptLocation, this.accept, options);
4836
5003
  }
4837
- return this.on(eventTypes, event => {
4838
- event.preventDefault();
4839
- up.error.muteUncriticalSync(() => closeFn.call(this, event, { response: event.response }));
4840
- });
4841
- }
4842
- tryAcceptForLocation(options) {
4843
- this._tryCloseForLocation(this.acceptLocation, this.accept, options);
4844
- }
4845
- tryDismissForLocation(options) {
4846
- this._tryCloseForLocation(this.dismissLocation, this.dismiss, options);
4847
- }
4848
- _tryCloseForLocation(urlPattern, closeFn, options) {
4849
- let location, resolution;
4850
- if (urlPattern && (location = this.location) && (resolution = urlPattern.recognize(location))) {
4851
- const closeValue = { ...resolution, location };
4852
- up.error.muteUncriticalSync(() => closeFn.call(this, closeValue, options));
5004
+ tryDismissForLocation(options) {
5005
+ this._tryCloseForLocation(this.dismissLocation, this.dismiss, options);
4853
5006
  }
4854
- }
4855
- teardownHandlers() {
4856
- super.teardownHandlers();
4857
- this.unbindParentClicked?.();
4858
- this.unbindEscapePressed?.();
4859
- this.overlayFocus.teardown();
4860
- }
4861
- destroyElements(options) {
4862
- const animation = () => this.startCloseAnimation(options);
4863
- const onFinished = () => {
4864
- this.onElementsRemoved();
4865
- options.onFinished?.();
4866
- };
4867
- const destroyOptions = { ...options, animation, onFinished, log: false };
4868
- up.destroy(this.element, destroyOptions);
4869
- }
4870
- onElementsRemoved() {
4871
- }
4872
- _startAnimation(options = {}) {
4873
- const boxDone = up.animate(this.getBoxElement(), options.boxAnimation, options);
4874
- let backdropDone;
4875
- if (this.backdrop && !up.motion.isNone(options.boxAnimation)) {
4876
- backdropDone = up.animate(this.backdropElement, options.backdropAnimation, options);
5007
+ _tryCloseForLocation(urlPattern, closeFn, options) {
5008
+ let location, resolution;
5009
+ if (urlPattern && (location = this.location) && (resolution = urlPattern.recognize(location))) {
5010
+ const closeValue = { ...resolution, location };
5011
+ up.error.muteUncriticalSync(() => closeFn.call(this, closeValue, options));
5012
+ }
4877
5013
  }
4878
- return Promise.all([boxDone, backdropDone]);
4879
- }
4880
- async startOpenAnimation(options = {}) {
4881
- await this._startAnimation({
4882
- boxAnimation: options.animation ?? this.evalOption(this.openAnimation),
4883
- backdropAnimation: 'fade-in',
4884
- easing: options.easing || this.openEasing,
4885
- duration: options.duration || this.openDuration
4886
- });
4887
- this.wasEverVisible = true;
4888
- }
4889
- startCloseAnimation(options = {}) {
4890
- return this._startAnimation({
4891
- boxAnimation: this.wasEverVisible && (options.animation ?? this.evalOption(this.closeAnimation)),
4892
- backdropAnimation: this.wasEverVisible && 'fade-out',
4893
- easing: options.easing || this.closeEasing,
4894
- duration: options.duration || this.closeDuration
4895
- });
4896
- }
4897
- accept(value = null, options = {}) {
4898
- return this._executeCloseChange('accept', value, options);
4899
- }
4900
- dismiss(value = null, options = {}) {
4901
- return this._executeCloseChange('dismiss', value, options);
4902
- }
4903
- _supportsDismissMethod(method) {
4904
- return u.contains(this.dismissable, method);
4905
- }
4906
- _executeCloseChange(verb, value, options) {
4907
- options = { ...options, verb, value, layer: this };
4908
- return new up.Change.CloseLayer(options).execute();
4909
- }
4910
- getFirstSwappableElement() {
4911
- return this.getContentElement().children[0];
4912
- }
4913
- toString() {
4914
- return `${this.mode} overlay`;
4915
- }
4916
- };
5014
+ teardownHandlers() {
5015
+ super.teardownHandlers();
5016
+ this.unbindParentClicked?.();
5017
+ this.unbindEscapePressed?.();
5018
+ this.overlayFocus.teardown();
5019
+ }
5020
+ destroyElements(options) {
5021
+ const animation = () => this.startCloseAnimation(options);
5022
+ const onFinished = () => {
5023
+ this.onElementsRemoved();
5024
+ options.onFinished?.();
5025
+ };
5026
+ const destroyOptions = { ...options, animation, onFinished, log: false };
5027
+ up.destroy(this.element, destroyOptions);
5028
+ }
5029
+ onElementsRemoved() {
5030
+ }
5031
+ _startAnimation(options = {}) {
5032
+ const boxDone = up.animate(this.getBoxElement(), options.boxAnimation, options);
5033
+ let backdropDone;
5034
+ if (this.backdrop && !up.motion.isNone(options.boxAnimation)) {
5035
+ backdropDone = up.animate(this.backdropElement, options.backdropAnimation, options);
5036
+ }
5037
+ return Promise.all([boxDone, backdropDone]);
5038
+ }
5039
+ async startOpenAnimation(options = {}) {
5040
+ let boxAnimation = options.animation ?? this.evalOption(this.openAnimation);
5041
+ let backdropAnimation = 'fade-in';
5042
+ await this._startAnimation({
5043
+ boxAnimation,
5044
+ backdropAnimation,
5045
+ easing: options.easing || this.openEasing,
5046
+ duration: options.duration || this.openDuration
5047
+ });
5048
+ this.wasEverVisible = true;
5049
+ }
5050
+ startCloseAnimation(options = {}) {
5051
+ let boxAnimation = this.wasEverVisible && (options.animation ?? this.evalOption(this.closeAnimation));
5052
+ let backdropAnimation = 'fade-out';
5053
+ return this._startAnimation({
5054
+ boxAnimation,
5055
+ backdropAnimation,
5056
+ easing: options.easing || this.closeEasing,
5057
+ duration: options.duration || this.closeDuration
5058
+ });
5059
+ }
5060
+ accept(value = null, options = {}) {
5061
+ return this._executeCloseChange('accept', value, options);
5062
+ }
5063
+ dismiss(value = null, options = {}) {
5064
+ return this._executeCloseChange('dismiss', value, options);
5065
+ }
5066
+ _supportsDismissMethod(method) {
5067
+ return u.contains(this.dismissable, method);
5068
+ }
5069
+ _executeCloseChange(verb, value, options) {
5070
+ options = { ...options, verb, value, layer: this };
5071
+ return new up.Change.CloseLayer(options).execute();
5072
+ }
5073
+ getFirstSwappableElement() {
5074
+ return this.getContentElement().children[0];
5075
+ }
5076
+ toString() {
5077
+ return `${this.mode} overlay`;
5078
+ }
5079
+ },
5080
+ _a.VISUAL_KEYS = [
5081
+ 'mode',
5082
+ 'position',
5083
+ 'align',
5084
+ 'size',
5085
+ 'origin',
5086
+ 'class',
5087
+ 'backdrop',
5088
+ 'dismissable',
5089
+ 'dismissLabel',
5090
+ 'dismissARIALabel',
5091
+ 'openAnimation',
5092
+ 'closeAnimation',
5093
+ 'openDuration',
5094
+ 'closeDuration',
5095
+ 'openEasing',
5096
+ 'closeEasing',
5097
+ 'trapFocus',
5098
+ ],
5099
+ _a);
4917
5100
 
4918
5101
 
4919
5102
  /***/ }),
4920
- /* 51 */
5103
+ /* 50 */
4921
5104
  /***/ (() => {
4922
5105
 
4923
5106
  up.Layer.OverlayWithTether = class OverlayWithTether extends up.Layer.Overlay {
@@ -4956,7 +5139,7 @@ up.Layer.OverlayWithTether = class OverlayWithTether extends up.Layer.Overlay {
4956
5139
 
4957
5140
 
4958
5141
  /***/ }),
4959
- /* 52 */
5142
+ /* 51 */
4960
5143
  /***/ (() => {
4961
5144
 
4962
5145
  up.Layer.OverlayWithViewport = class OverlayWithViewport extends up.Layer.Overlay {
@@ -4985,7 +5168,7 @@ up.Layer.OverlayWithViewport = class OverlayWithViewport extends up.Layer.Overla
4985
5168
 
4986
5169
 
4987
5170
  /***/ }),
4988
- /* 53 */
5171
+ /* 52 */
4989
5172
  /***/ (() => {
4990
5173
 
4991
5174
  var _a;
@@ -5031,7 +5214,7 @@ up.Layer.Root = (_a = class Root extends up.Layer {
5031
5214
 
5032
5215
 
5033
5216
  /***/ }),
5034
- /* 54 */
5217
+ /* 53 */
5035
5218
  /***/ (() => {
5036
5219
 
5037
5220
  var _a;
@@ -5042,7 +5225,7 @@ up.Layer.Modal = (_a = class Modal extends up.Layer.OverlayWithViewport {
5042
5225
 
5043
5226
 
5044
5227
  /***/ }),
5045
- /* 55 */
5228
+ /* 54 */
5046
5229
  /***/ (() => {
5047
5230
 
5048
5231
  var _a;
@@ -5053,7 +5236,7 @@ up.Layer.Popup = (_a = class Popup extends up.Layer.OverlayWithTether {
5053
5236
 
5054
5237
 
5055
5238
  /***/ }),
5056
- /* 56 */
5239
+ /* 55 */
5057
5240
  /***/ (() => {
5058
5241
 
5059
5242
  var _a;
@@ -5064,7 +5247,7 @@ up.Layer.Drawer = (_a = class Drawer extends up.Layer.OverlayWithViewport {
5064
5247
 
5065
5248
 
5066
5249
  /***/ }),
5067
- /* 57 */
5250
+ /* 56 */
5068
5251
  /***/ (() => {
5069
5252
 
5070
5253
  var _a;
@@ -5075,7 +5258,7 @@ up.Layer.Cover = (_a = class Cover extends up.Layer.OverlayWithViewport {
5075
5258
 
5076
5259
 
5077
5260
  /***/ }),
5078
- /* 58 */
5261
+ /* 57 */
5079
5262
  /***/ (() => {
5080
5263
 
5081
5264
  var _a;
@@ -5088,7 +5271,7 @@ up.LayerLookup = (_a = class LayerLookup {
5088
5271
  up.layer.normalizeOptions(options);
5089
5272
  }
5090
5273
  this._options = options;
5091
- this._values = u.parseTokens(options.layer);
5274
+ this._values = u.getSimpleTokens(options.layer);
5092
5275
  }
5093
5276
  all() {
5094
5277
  let results = u.flatMap(this._values, value => this._resolveValue(value));
@@ -5121,7 +5304,7 @@ up.LayerLookup = (_a = class LayerLookup {
5121
5304
  if (/^\d+$/.test(value)) {
5122
5305
  return this._forIndex(Number(value));
5123
5306
  }
5124
- if (u.isElementish(value)) {
5307
+ if (u.isElementLike(value)) {
5125
5308
  return this._forElement(value);
5126
5309
  }
5127
5310
  switch (value) {
@@ -5188,7 +5371,7 @@ up.LayerLookup = (_a = class LayerLookup {
5188
5371
 
5189
5372
 
5190
5373
  /***/ }),
5191
- /* 59 */
5374
+ /* 58 */
5192
5375
  /***/ (() => {
5193
5376
 
5194
5377
  const u = up.util;
@@ -5302,11 +5485,11 @@ up.LayerStack = class LayerStack {
5302
5485
 
5303
5486
 
5304
5487
  /***/ }),
5305
- /* 60 */
5488
+ /* 59 */
5306
5489
  /***/ (() => {
5307
5490
 
5308
5491
  const u = up.util;
5309
- up.LinkFeedbackURLs = class LinkFeedbackURLs {
5492
+ up.LinkCurrentURLs = class LinkCurrentURLs {
5310
5493
  constructor(link) {
5311
5494
  this._isSafe = up.link.isSafe(link);
5312
5495
  if (this._isSafe) {
@@ -5336,7 +5519,7 @@ up.LinkFeedbackURLs = class LinkFeedbackURLs {
5336
5519
 
5337
5520
 
5338
5521
  /***/ }),
5339
- /* 61 */
5522
+ /* 60 */
5340
5523
  /***/ (() => {
5341
5524
 
5342
5525
  const u = up.util;
@@ -5345,12 +5528,13 @@ up.LinkFollowIntent = class LinkFollowIntent {
5345
5528
  constructor(link, callback) {
5346
5529
  this._link = link;
5347
5530
  this._callback = callback;
5531
+ this._lastRequest = null;
5348
5532
  this._on('mouseenter mousedown touchstart', (event) => this._scheduleCallback(event));
5349
5533
  this._on('mouseleave', () => this._unscheduleCallback());
5350
5534
  up.fragment.onAborted(this._link, () => this._unscheduleCallback());
5351
5535
  }
5352
- _on(eventType, callback) {
5353
- up.on(this._link, eventType, { passive: true }, callback);
5536
+ _on(eventType, fn) {
5537
+ up.on(this._link, eventType, { passive: true }, fn);
5354
5538
  }
5355
5539
  _scheduleCallback(event) {
5356
5540
  if (!up.link.shouldFollowEvent(event, this._link))
@@ -5367,20 +5551,22 @@ up.LinkFollowIntent = class LinkFollowIntent {
5367
5551
  }
5368
5552
  _unscheduleCallback() {
5369
5553
  clearTimeout(this._timer);
5370
- up.network.abort((request) => (request.origin === this._link) && request.background);
5554
+ if (this._lastRequest?.background)
5555
+ this._lastRequest.abort();
5556
+ this._lastRequest = null;
5371
5557
  }
5372
5558
  _parseDelay() {
5373
5559
  return e.numberAttr(this._link, 'up-preload-delay') ?? up.link.config.preloadDelay;
5374
5560
  }
5375
5561
  _runCallback(event) {
5376
5562
  up.log.putsEvent(event);
5377
- up.error.muteUncriticalRejection(this._callback());
5563
+ this._callback({ onRequestKnown: (request) => this._lastRequest = request });
5378
5564
  }
5379
5565
  };
5380
5566
 
5381
5567
 
5382
5568
  /***/ }),
5383
- /* 62 */
5569
+ /* 61 */
5384
5570
  /***/ (() => {
5385
5571
 
5386
5572
  const u = up.util;
@@ -5476,7 +5662,7 @@ up.MotionController = class MotionController {
5476
5662
 
5477
5663
 
5478
5664
  /***/ }),
5479
- /* 63 */
5665
+ /* 62 */
5480
5666
  /***/ (() => {
5481
5667
 
5482
5668
  const u = up.util;
@@ -5491,33 +5677,34 @@ up.NonceableCallback = class NonceableCallback {
5491
5677
  return new this(match[3], match[2]);
5492
5678
  }
5493
5679
  toFunction(...argNames) {
5680
+ let script = this.script;
5494
5681
  if (this.nonce) {
5495
5682
  let callbackThis = this;
5496
5683
  return function (...args) {
5497
- return callbackThis._runAsNoncedFunction(this, argNames, args);
5684
+ return callbackThis._runAsNoncedFunction(script, this, argNames, args);
5498
5685
  };
5499
5686
  }
5500
5687
  else {
5501
- return new Function(...argNames, this.script);
5688
+ return new Function(...argNames, script);
5502
5689
  }
5503
5690
  }
5504
5691
  toString() {
5505
5692
  return `nonce-${this.nonce} ${this.script}`;
5506
5693
  }
5507
- _runAsNoncedFunction(thisArg, argNames, args) {
5694
+ _runAsNoncedFunction(script, thisArg, argNames, args) {
5508
5695
  let wrappedScript = `
5509
5696
  try {
5510
5697
  up.noncedEval.value = (function(${argNames.join()}) {
5511
- ${this.script}
5698
+ ${script}
5512
5699
  }).apply(up.noncedEval.thisArg, up.noncedEval.args)
5513
5700
  } catch (error) {
5514
5701
  up.noncedEval.error = error
5515
5702
  }
5516
5703
  `;
5517
- let script;
5704
+ let scriptElement;
5518
5705
  try {
5519
5706
  up.noncedEval = { args, thisArg: thisArg };
5520
- script = up.element.affix(document.body, 'script', { nonce: this.nonce, text: wrappedScript });
5707
+ scriptElement = e.affix(document.body, 'script', { nonce: this.nonce, text: wrappedScript });
5521
5708
  if (up.noncedEval.error) {
5522
5709
  throw up.noncedEval.error;
5523
5710
  }
@@ -5527,8 +5714,8 @@ up.NonceableCallback = class NonceableCallback {
5527
5714
  }
5528
5715
  finally {
5529
5716
  up.noncedEval = undefined;
5530
- if (script) {
5531
- script.remove();
5717
+ if (scriptElement) {
5718
+ scriptElement.remove();
5532
5719
  }
5533
5720
  }
5534
5721
  }
@@ -5562,7 +5749,7 @@ up.NonceableCallback = class NonceableCallback {
5562
5749
 
5563
5750
 
5564
5751
  /***/ }),
5565
- /* 64 */
5752
+ /* 63 */
5566
5753
  /***/ (() => {
5567
5754
 
5568
5755
  const e = up.element;
@@ -5578,7 +5765,7 @@ up.OverlayFocus = class OverlayFocus {
5578
5765
  return;
5579
5766
  }
5580
5767
  this._active = true;
5581
- this._unsetAttrs = e.setTemporaryAttrs(this._focusElement, {
5768
+ this._unsetAttrs = e.setAttrsTemp(this._focusElement, {
5582
5769
  'tabindex': '0',
5583
5770
  'role': 'dialog',
5584
5771
  'aria-modal': this._trapFocus.toString()
@@ -5635,7 +5822,7 @@ up.OverlayFocus = class OverlayFocus {
5635
5822
 
5636
5823
 
5637
5824
  /***/ }),
5638
- /* 65 */
5825
+ /* 64 */
5639
5826
  /***/ (() => {
5640
5827
 
5641
5828
  const u = up.util;
@@ -5868,6 +6055,140 @@ up.Params = class Params {
5868
6055
  };
5869
6056
 
5870
6057
 
6058
+ /***/ }),
6059
+ /* 65 */
6060
+ /***/ (() => {
6061
+
6062
+ const u = up.util;
6063
+ const e = up.element;
6064
+ up.Preview = class Preview {
6065
+ constructor({ fragment, request, renderOptions, cleaner }) {
6066
+ this.fragment = fragment;
6067
+ this.request = request;
6068
+ this.renderOptions = renderOptions;
6069
+ this._cleaner = cleaner;
6070
+ }
6071
+ undo(...args) {
6072
+ if (this.ended) {
6073
+ reportError(new up.Error('Preview used after end of request'));
6074
+ }
6075
+ else {
6076
+ this._cleaner.guard(...args);
6077
+ }
6078
+ }
6079
+ get origin() {
6080
+ return this.request.origin;
6081
+ }
6082
+ get params() {
6083
+ return this.request.params;
6084
+ }
6085
+ get layer() {
6086
+ return this.request.layer;
6087
+ }
6088
+ get ended() {
6089
+ return this.request.ended;
6090
+ }
6091
+ get expiredResponse() {
6092
+ return this.renderOptions.expiredResponse;
6093
+ }
6094
+ get revalidating() {
6095
+ return !!this.expiredResponse;
6096
+ }
6097
+ run(value, options = {}) {
6098
+ for (let fn of up.status.resolvePreviewFns(value)) {
6099
+ this.undo(up.error.guard(fn, this, options));
6100
+ }
6101
+ }
6102
+ revert() {
6103
+ this._cleaner.clean();
6104
+ }
6105
+ setAttrs(...args) {
6106
+ let [element, attrs] = this._parseMutatorArgs(args, 'val', 'val');
6107
+ this.undo(e.setAttrsTemp(element, attrs));
6108
+ }
6109
+ addClass(...args) {
6110
+ let [element, klass] = this._parseMutatorArgs(args, 'val', 'val');
6111
+ this.undo(e.addClassTemp(element, klass));
6112
+ }
6113
+ addClassBatch(elements, classes) {
6114
+ for (let element of elements) {
6115
+ for (let klass of classes) {
6116
+ this.addClass(element, klass);
6117
+ }
6118
+ }
6119
+ }
6120
+ removeClass(...args) {
6121
+ let [element, klass] = this._parseMutatorArgs(args, 'val', 'val');
6122
+ this.undo(e.removeClassTemp(element, klass));
6123
+ }
6124
+ setStyle(...args) {
6125
+ let [element, styles] = this._parseMutatorArgs(args, 'val', 'val');
6126
+ this.undo(e.setStyleTemp(element, styles));
6127
+ }
6128
+ disable(...args) {
6129
+ let [element] = this._parseMutatorArgs(args, 'val');
6130
+ this.undo(up.form.disable(element));
6131
+ }
6132
+ insert(...args) {
6133
+ let [reference, position = 'beforeend', tempValue] = this._parseMutatorArgs(args, 'val', u.isAdjacentPosition, 'val');
6134
+ this.undo(up.fragment.insertTemp(reference, position, tempValue));
6135
+ }
6136
+ show(...args) {
6137
+ let [element] = this._parseMutatorArgs(args, 'val');
6138
+ this.undo(e.showTemp(element));
6139
+ }
6140
+ hide(...args) {
6141
+ let [element] = this._parseMutatorArgs(args, 'val');
6142
+ this.undo(e.hideTemp(element));
6143
+ }
6144
+ hideContent(...args) {
6145
+ let [parent] = this._parseMutatorArgs(args, 'val');
6146
+ let wrapper = e.wrapChildren(parent);
6147
+ e.hide(wrapper);
6148
+ this.undo(() => e.unwrap(wrapper));
6149
+ }
6150
+ showPlaceholder(...args) {
6151
+ let [parent, placeholderReference] = this._parseMutatorArgs(args, 'val', 'val');
6152
+ let placeholderNodes = up.fragment.provideNodes(placeholderReference, { origin: this.origin });
6153
+ up.puts('[up-placeholder]', 'Showing placeholder %o', placeholderReference);
6154
+ if (parent) {
6155
+ this.swapContent(parent, placeholderNodes);
6156
+ }
6157
+ else if (this.layer === 'new') {
6158
+ this.openLayer(placeholderNodes, { closeAnimation: false });
6159
+ this.renderOptions.openAnimation = false;
6160
+ }
6161
+ }
6162
+ swapContent(...args) {
6163
+ let [parent, newContent] = this._parseMutatorArgs(args, 'val', 'val');
6164
+ this.hideContent(parent);
6165
+ this.insert(parent, newContent);
6166
+ }
6167
+ openLayer(content, options = {}) {
6168
+ let undoDismissValue = ':undo-preview';
6169
+ let onDismiss = ({ value }) => {
6170
+ if (value !== undoDismissValue)
6171
+ this.request.abort({ reason: 'Preview overlay dismissed' });
6172
+ };
6173
+ up.layer.open({
6174
+ ...u.pick(this.renderOptions, [...up.Layer.Overlay.VISUAL_KEYS, 'target']),
6175
+ ...options,
6176
+ content,
6177
+ abort: false,
6178
+ onDismiss
6179
+ });
6180
+ let overlay = up.layer.front;
6181
+ this.undo(() => overlay.dismiss(undoDismissValue, { preventable: false }));
6182
+ return overlay;
6183
+ }
6184
+ _parseMutatorArgs(args, ...specs) {
6185
+ let [element, ...rest] = u.args(args, ...specs);
6186
+ element = up.fragment.get(element, { layer: this.layer, origin: this.origin }) || this.fragment;
6187
+ return [element, ...rest];
6188
+ }
6189
+ };
6190
+
6191
+
5871
6192
  /***/ }),
5872
6193
  /* 66 */
5873
6194
  /***/ (() => {
@@ -5880,7 +6201,7 @@ up.ProgressBar = class ProgressBar {
5880
6201
  this._element = e.affix(document.body, 'up-progress-bar');
5881
6202
  this._element.style.transition = `width ${TRANSITION_DELAY}ms ease-out`;
5882
6203
  this._moveTo(0);
5883
- up.element.paint(this._element);
6204
+ e.paint(this._element);
5884
6205
  this._width = 31;
5885
6206
  this._nextStep();
5886
6207
  }
@@ -5924,21 +6245,22 @@ up.ProgressBar = class ProgressBar {
5924
6245
 
5925
6246
  const u = up.util;
5926
6247
  up.RenderOptions = (function () {
5927
- const GLOBAL_DEFAULTS = {
5928
- useHungry: true,
5929
- useKeep: true,
5930
- saveScroll: true,
5931
- saveFocus: true,
5932
- focus: 'keep',
5933
- abort: 'target',
5934
- failOptions: true,
6248
+ const NO_PREVIEWS = {
6249
+ preview: false,
6250
+ disable: false,
6251
+ placeholder: false,
6252
+ feedback: false,
5935
6253
  };
5936
- const PRELOAD_OVERRIDES = {
5937
- abort: false,
6254
+ const NO_INPUT_INTERFERENCE = {
6255
+ scroll: false,
6256
+ focus: 'keep',
5938
6257
  confirm: false,
5939
- feedback: false,
5940
- cache: true,
5941
- background: true,
6258
+ };
6259
+ const NO_MOTION = {
6260
+ transition: false,
6261
+ animation: false,
6262
+ openAnimation: false,
6263
+ closeAnimation: false,
5942
6264
  };
5943
6265
  const PREFLIGHT_KEYS = [
5944
6266
  'url',
@@ -5952,9 +6274,13 @@ up.RenderOptions = (function () {
5952
6274
  'abortable',
5953
6275
  'confirm',
5954
6276
  'feedback',
6277
+ 'disable',
6278
+ 'placeholder',
6279
+ 'preview',
5955
6280
  'origin',
5956
6281
  'originLayer',
5957
6282
  'baseLayer',
6283
+ 'navigate',
5958
6284
  'fail',
5959
6285
  'onError',
5960
6286
  ];
@@ -5964,8 +6290,6 @@ up.RenderOptions = (function () {
5964
6290
  'history',
5965
6291
  'source',
5966
6292
  'saveScroll',
5967
- 'navigate',
5968
- 'baseLayer',
5969
6293
  ]);
5970
6294
  const CONTENT_KEYS = [
5971
6295
  'url',
@@ -5989,15 +6313,17 @@ up.RenderOptions = (function () {
5989
6313
  return { url: u.normalizeURL(url) };
5990
6314
  }
5991
6315
  }
5992
- function preloadOverrides(options) {
5993
- if (options.preload) {
5994
- return PRELOAD_OVERRIDES;
5995
- }
6316
+ function removeUsePrefix(options) {
6317
+ u.renameKey(options, 'useData', 'data');
6318
+ u.renameKey(options, 'useHungry', 'hungry');
6319
+ u.renameKey(options, 'useKeep', 'keep');
5996
6320
  }
5997
6321
  function preprocess(options) {
5998
6322
  up.migrate.preprocessRenderOptions?.(options);
5999
- const defaults = u.merge(GLOBAL_DEFAULTS, navigateDefaults(options));
6000
- return u.merge(u.omit(defaults, LATE_KEYS), { defaults }, { inputDevice: up.event.inputDevice }, options, normalizeURL(options), rememberOriginLayer(options), preloadOverrides(options));
6323
+ up.layer.normalizeOptions(options);
6324
+ removeUsePrefix(options);
6325
+ const defaults = u.merge(up.fragment.config.renderOptions, navigateDefaults(options));
6326
+ return u.merge(u.omit(defaults, LATE_KEYS), { defaults }, { inputDevice: up.event.inputDevice }, options, normalizeURL(options), rememberOriginLayer(options));
6001
6327
  }
6002
6328
  function rememberOriginLayer({ origin, originLayer }) {
6003
6329
  if (origin && !originLayer) {
@@ -6032,13 +6358,11 @@ up.RenderOptions = (function () {
6032
6358
  }
6033
6359
  function deriveFailOptions(preprocessedOptions) {
6034
6360
  let overrides = failOverrides(preprocessedOptions);
6035
- let layers = rememberOriginLayer(overrides);
6036
6361
  if (preprocessedOptions.failOptions) {
6037
6362
  return {
6038
6363
  ...preprocessedOptions.defaults,
6039
6364
  ...u.pick(preprocessedOptions, SHARED_KEYS),
6040
6365
  ...overrides,
6041
- ...layers,
6042
6366
  ...{ failPrefixForced: true }
6043
6367
  };
6044
6368
  }
@@ -6046,7 +6370,6 @@ up.RenderOptions = (function () {
6046
6370
  return {
6047
6371
  ...preprocessedOptions,
6048
6372
  ...overrides,
6049
- ...layers,
6050
6373
  };
6051
6374
  }
6052
6375
  }
@@ -6055,6 +6378,9 @@ up.RenderOptions = (function () {
6055
6378
  finalize,
6056
6379
  assertContentGiven,
6057
6380
  deriveFailOptions,
6381
+ NO_PREVIEWS,
6382
+ NO_MOTION,
6383
+ NO_INPUT_INTERFERENCE,
6058
6384
  };
6059
6385
  })();
6060
6386
 
@@ -6135,7 +6461,6 @@ up.Request = (_a = class Request extends up.Record {
6135
6461
  'failMode',
6136
6462
  'failContext',
6137
6463
  'origin',
6138
- 'fragments',
6139
6464
  'builtAt',
6140
6465
  'wrapMethod',
6141
6466
  'contentType',
@@ -6143,7 +6468,8 @@ up.Request = (_a = class Request extends up.Record {
6143
6468
  'onLoading',
6144
6469
  'fail',
6145
6470
  'abortable',
6146
- 'badResponseTime',
6471
+ 'lateDelay',
6472
+ 'previews',
6147
6473
  ];
6148
6474
  }
6149
6475
  defaults() {
@@ -6153,6 +6479,7 @@ up.Request = (_a = class Request extends up.Record {
6153
6479
  headers: {},
6154
6480
  timeout: up.network.config.timeout,
6155
6481
  builtAt: new Date(),
6482
+ previews: [],
6156
6483
  };
6157
6484
  }
6158
6485
  constructor(options) {
@@ -6171,26 +6498,37 @@ up.Request = (_a = class Request extends up.Record {
6171
6498
  this.mode ||= this.layer.mode;
6172
6499
  this.failMode ||= this.failLayer?.mode;
6173
6500
  }
6174
- this.deferred = u.newDeferred();
6175
- this.badResponseTime ??= u.evalOption(up.network.config.badResponseTime, this);
6501
+ this.bindLayer = options.bindLayer || this.layer;
6502
+ this._fragments = options.fragments;
6503
+ this._bindFragments = options.bindFragments;
6504
+ this._deferred = u.newDeferred();
6176
6505
  this._setAutoHeaders();
6177
6506
  }
6507
+ get effectiveLateTime() {
6508
+ if (this.background) {
6509
+ return false;
6510
+ }
6511
+ else {
6512
+ return this.lateDelay ?? u.evalOption(up.network.config.lateDelay, this);
6513
+ }
6514
+ }
6515
+ isTimed() {
6516
+ return u.isNumber(this.effectiveLateTime);
6517
+ }
6178
6518
  get xhr() {
6179
6519
  return this._xhr ??= new XMLHttpRequest();
6180
6520
  }
6181
6521
  get fragments() {
6182
- if (this._fragments) {
6183
- return this._fragments;
6184
- }
6185
- else {
6186
- let steps = up.fragment.parseTargetSteps(this.target);
6187
- let selectors = u.map(steps, 'selector');
6188
- let lookupOpts = { origin: this.origin, layer: this.layer };
6189
- return u.compact(u.map(selectors, (selector) => up.fragment.get(selector, lookupOpts)));
6190
- }
6522
+ return (this._fragments ||= this._findFragments());
6523
+ }
6524
+ _findFragments() {
6525
+ let steps = up.fragment.parseTargetSteps(this.target);
6526
+ let lookupOpts = { origin: this.origin, layer: this.layer };
6527
+ let matches = u.map(steps, (step) => up.fragment.get(step.selector, lookupOpts));
6528
+ return u.compact(matches);
6191
6529
  }
6192
- set fragments(value) {
6193
- this._fragments = value;
6530
+ get bindFragments() {
6531
+ return this._bindFragments || this.fragments;
6194
6532
  }
6195
6533
  get fragment() {
6196
6534
  return this.fragments?.[0];
@@ -6205,8 +6543,10 @@ up.Request = (_a = class Request extends up.Record {
6205
6543
  u.task(() => {
6206
6544
  this.layer = undefined;
6207
6545
  this.failLayer = undefined;
6546
+ this._bindLayer = undefined;
6208
6547
  this.origin = undefined;
6209
- this.fragments = undefined;
6548
+ this._fragments = undefined;
6549
+ this._bindFragments = undefined;
6210
6550
  });
6211
6551
  }
6212
6552
  _extractHashFromURL() {
@@ -6258,6 +6598,11 @@ up.Request = (_a = class Request extends up.Record {
6258
6598
  this.abort({ reason: 'Prevented by event listener' });
6259
6599
  }
6260
6600
  }
6601
+ runPreviews(renderOptions) {
6602
+ if (!this.ended && !this.fromCache) {
6603
+ this._revertPreviews = up.status.runPreviews(this, renderOptions);
6604
+ }
6605
+ }
6261
6606
  _emitLoad() {
6262
6607
  let event = this.emit('up:request:load', { log: ['Loading %s', this.description] });
6263
6608
  return !event.defaultPrevented;
@@ -6287,35 +6632,46 @@ up.Request = (_a = class Request extends up.Record {
6287
6632
  }
6288
6633
  }
6289
6634
  _setAbortedState(reason) {
6290
- if (this._isSettled())
6635
+ if (this.ended)
6291
6636
  return;
6292
6637
  let message = 'Aborted request to ' + this.description + (reason ? ': ' + reason : '');
6293
6638
  this.state = 'aborted';
6294
- this.deferred.reject(new up.Aborted(message));
6639
+ this._reject(new up.Aborted(message));
6295
6640
  this.emit('up:request:aborted', { log: message });
6296
6641
  return true;
6297
6642
  }
6298
6643
  _setOfflineState(reason) {
6299
- if (this._isSettled())
6644
+ if (this.ended)
6300
6645
  return;
6301
6646
  let message = 'Cannot load request to ' + this.description + (reason ? ': ' + reason : '');
6302
6647
  this.state = 'offline';
6303
6648
  this.emit('up:request:offline', { log: message });
6304
- this.deferred.reject(new up.Offline(message));
6649
+ this._reject(new up.Offline(message));
6305
6650
  }
6306
6651
  respondWith(response) {
6307
6652
  this.response = response;
6308
- if (this._isSettled())
6653
+ if (this.ended)
6309
6654
  return;
6310
6655
  this.state = 'loaded';
6311
6656
  if (response.ok) {
6312
- this.deferred.resolve(response);
6657
+ this._resolve(response);
6313
6658
  }
6314
6659
  else {
6315
- this.deferred.reject(response);
6660
+ this._reject(response);
6316
6661
  }
6317
6662
  }
6318
- _isSettled() {
6663
+ _resolve(response) {
6664
+ this._onSettle();
6665
+ this._deferred.resolve(response);
6666
+ }
6667
+ _reject(responseOrError) {
6668
+ this._onSettle();
6669
+ this._deferred.reject(responseOrError);
6670
+ }
6671
+ _onSettle() {
6672
+ this._revertPreviews?.();
6673
+ }
6674
+ get ended() {
6319
6675
  return (this.state !== 'new') && (this.state !== 'loading') && (this.state !== 'tracking');
6320
6676
  }
6321
6677
  csrfHeader() {
@@ -6365,7 +6721,7 @@ up.Request = (_a = class Request extends up.Record {
6365
6721
  }
6366
6722
  _buildEventEmitter(args) {
6367
6723
  return up.EventEmitter.fromEmitArgs(args, {
6368
- layer: this.layer,
6724
+ layer: this.bindLayer,
6369
6725
  request: this,
6370
6726
  origin: this.origin
6371
6727
  });
@@ -6379,12 +6735,15 @@ up.Request = (_a = class Request extends up.Record {
6379
6735
  get description() {
6380
6736
  return this.method + ' ' + this.url;
6381
6737
  }
6382
- isPartOfSubtree(subtreeElements) {
6383
- subtreeElements = u.wrapList(subtreeElements);
6384
- return u.some(this.fragments, function (fragment) {
6385
- return u.some(subtreeElements, (subtreeElement) => subtreeElement.contains(fragment));
6738
+ isBoundToSubtrees(subtreeRoots) {
6739
+ subtreeRoots = u.wrapList(subtreeRoots);
6740
+ return u.some(this.bindFragments, function (fragment) {
6741
+ return u.some(subtreeRoots, (subtreeElement) => subtreeElement.contains(fragment));
6386
6742
  });
6387
6743
  }
6744
+ isBoundToLayers(layers) {
6745
+ return u.contains(layers, this.bindLayer);
6746
+ }
6388
6747
  get age() {
6389
6748
  return new Date() - this.builtAt;
6390
6749
  }
@@ -6447,7 +6806,7 @@ up.Request = (_a = class Request extends up.Record {
6447
6806
  }
6448
6807
  },
6449
6808
  (() => {
6450
- u.delegate(_a.prototype, ['then', 'catch', 'finally'], function () { return this.deferred; });
6809
+ u.delegatePromise(_a.prototype, '_deferred');
6451
6810
  })(),
6452
6811
  _a);
6453
6812
 
@@ -6488,8 +6847,8 @@ class Route {
6488
6847
  return true;
6489
6848
  if (!newValue)
6490
6849
  return false;
6491
- let cachedTokens = u.parseTokens(cachedValue, { separator: 'comma' });
6492
- let newTokens = u.parseTokens(newValue, { separator: 'comma' });
6850
+ let cachedTokens = up.fragment.splitTarget(cachedValue);
6851
+ let newTokens = up.fragment.splitTarget(newValue);
6493
6852
  return u.containsAll(cachedTokens, newTokens);
6494
6853
  }
6495
6854
  else {
@@ -6546,7 +6905,13 @@ up.Request.Cache = class Cache {
6546
6905
  async track(existingRequest, newRequest, options = {}) {
6547
6906
  newRequest.trackedRequest = existingRequest;
6548
6907
  newRequest.state = 'tracking';
6549
- let value = await u.always(existingRequest);
6908
+ let value;
6909
+ if (existingRequest.ended && existingRequest.response) {
6910
+ value = existingRequest.response;
6911
+ }
6912
+ else {
6913
+ value = await u.always(existingRequest);
6914
+ }
6550
6915
  if (value instanceof up.Response) {
6551
6916
  if (options.force || existingRequest.cacheRoute.satisfies(existingRequest, newRequest)) {
6552
6917
  newRequest.fromCache = true;
@@ -6562,7 +6927,7 @@ up.Request.Cache = class Cache {
6562
6927
  }
6563
6928
  else {
6564
6929
  newRequest.state = existingRequest.state;
6565
- newRequest.deferred.reject(value);
6930
+ newRequest._reject(value);
6566
6931
  }
6567
6932
  }
6568
6933
  willHaveSameResponse(existingRequest, newRequest) {
@@ -6642,8 +7007,10 @@ up.Request.Queue = class Queue {
6642
7007
  }
6643
7008
  }
6644
7009
  _scheduleSlowTimer(request) {
6645
- let timeUntilLate = Math.max(request.badResponseTime - request.age, 0);
6646
- u.timer(timeUntilLate, () => this._checkLate());
7010
+ if (!request.isTimed())
7011
+ return;
7012
+ let timeUntilLate = Math.max(request.effectiveLateTime - request.age);
7013
+ u.timer(timeUntilLate, () => this._checkForLate());
6647
7014
  }
6648
7015
  _getMaxConcurrency() {
6649
7016
  return u.evalOption(up.network.config.concurrency);
@@ -6673,8 +7040,8 @@ up.Request.Queue = class Queue {
6673
7040
  if ((responseOrError instanceof up.Response) && responseOrError.ok) {
6674
7041
  up.network.registerAliasForRedirect(request, responseOrError);
6675
7042
  }
6676
- this._checkLate();
6677
7043
  queueMicrotask(() => this._poke());
7044
+ u.task(() => this._checkForRecover());
6678
7045
  }
6679
7046
  _poke() {
6680
7047
  let request;
@@ -6683,9 +7050,7 @@ up.Request.Queue = class Queue {
6683
7050
  }
6684
7051
  }
6685
7052
  abort(...args) {
6686
- let options = u.extractOptions(args);
6687
- let { except, reason, logOnce } = options;
6688
- let conditions = args[0] ?? true;
7053
+ let [conditions = true, { except, reason, logOnce }] = u.args(args, 'val', 'options');
6689
7054
  let tester = up.Request.tester(conditions, { except });
6690
7055
  for (let list of [this._currentRequests, this._queuedRequests]) {
6691
7056
  const abortableRequests = u.filter(list, tester);
@@ -6699,22 +7064,25 @@ up.Request.Queue = class Queue {
6699
7064
  }
6700
7065
  }
6701
7066
  }
6702
- _checkLate() {
6703
- const currentLate = this._isLate();
6704
- if (this._emittedLate !== currentLate) {
6705
- this._emittedLate = currentLate;
6706
- if (currentLate) {
6707
- up.emit('up:network:late', { log: 'Server is slow to respond' });
6708
- }
6709
- else {
6710
- up.emit('up:network:recover', { log: 'Slow requests were loaded' });
6711
- }
7067
+ _checkForLate() {
7068
+ if (!this._emittedLate && this._hasLateTimedRequests()) {
7069
+ this._emittedLate = true;
7070
+ up.emit('up:network:late', { log: 'Server is slow to respond' });
7071
+ }
7072
+ }
7073
+ _checkForRecover() {
7074
+ if (this._emittedLate && !this._timedRequests.length) {
7075
+ this._emittedLate = false;
7076
+ up.emit('up:network:recover', { log: 'Slow requests were loaded' });
6712
7077
  }
6713
7078
  }
6714
- _isLate() {
6715
- const allForegroundRequests = u.reject(this.allRequests, 'background');
7079
+ get _timedRequests() {
7080
+ return this.allRequests.filter((request) => request.isTimed());
7081
+ }
7082
+ _hasLateTimedRequests() {
6716
7083
  const timerTolerance = 1;
6717
- return u.some(allForegroundRequests, (request) => request.age >= (request.badResponseTime - timerTolerance));
7084
+ const isLate = (request) => request.age >= (request.effectiveLateTime - timerTolerance);
7085
+ return u.some(this._timedRequests, isLate);
6718
7086
  }
6719
7087
  };
6720
7088
 
@@ -6873,7 +7241,7 @@ up.Response = class Response extends up.Record {
6873
7241
  }
6874
7242
  get varyHeaderNames() {
6875
7243
  let varyHeaderValue = this.header('Vary');
6876
- return u.parseTokens(varyHeaderValue, { separator: 'comma' });
7244
+ return u.getSimpleTokens(varyHeaderValue, { separator: ',' });
6877
7245
  }
6878
7246
  get contentType() {
6879
7247
  return this.header('Content-Type');
@@ -6916,15 +7284,15 @@ const u = up.util;
6916
7284
  const e = up.element;
6917
7285
  const FULL_DOCUMENT_PATTERN = /^\s*<(html|!DOCTYPE)\b/i;
6918
7286
  up.ResponseDoc = (_a = class ResponseDoc {
6919
- constructor({ document, fragment, content, target, origin, cspNonces, match }) {
7287
+ constructor({ document, fragment, content, target, origin, data, cspNonces, match }) {
6920
7288
  if (document) {
6921
- this._parseDocument(document);
7289
+ this._parseDocument(document, origin, data);
6922
7290
  }
6923
7291
  else if (fragment) {
6924
- this._parseFragment(fragment);
7292
+ this._parseFragment(fragment, origin, data);
6925
7293
  }
6926
7294
  else {
6927
- this._parseContent(content || '', target);
7295
+ this._parseContent(content || '', origin, target, data);
6928
7296
  }
6929
7297
  this._cspNonces = cspNonces;
6930
7298
  if (origin) {
@@ -6935,46 +7303,49 @@ up.ResponseDoc = (_a = class ResponseDoc {
6935
7303
  }
6936
7304
  this._match = match;
6937
7305
  }
6938
- _parseDocument(value) {
7306
+ _parseDocument(value, origin, data) {
6939
7307
  if (value instanceof Document) {
6940
7308
  this._document = value;
6941
7309
  this._isFullDocument = true;
6942
7310
  }
6943
7311
  else if (u.isString(value)) {
6944
- this._document = e.createBrokenDocumentFromHTML(value);
6945
7312
  this._isFullDocument = FULL_DOCUMENT_PATTERN.test(value);
6946
- this._isDocumentBroken = true;
7313
+ let htmlParser = (html) => [e.createBrokenDocumentFromHTML(html)];
7314
+ let nodes = up.fragment.provideNodes(value, { origin, data, htmlParser });
7315
+ if (nodes[0] instanceof Document) {
7316
+ this._document = nodes[0];
7317
+ }
7318
+ else {
7319
+ this._document = this._buildFauxDocument(nodes);
7320
+ }
6947
7321
  }
6948
7322
  else {
6949
7323
  this._document = this._buildFauxDocument(value);
6950
- this._isFullDocument = value.matches('html');
6951
7324
  }
6952
7325
  }
6953
- _parseFragment(value) {
6954
- let parsed = u.isString(value) ? e.createFromHTML(value) : value;
6955
- this._document = this._buildFauxDocument(parsed);
7326
+ _parseDocumentFromHTML(html) {
7327
+ return e.createBrokenDocumentFromHTML(html);
6956
7328
  }
6957
- _parseContent(value, target) {
7329
+ _parseFragment(value, origin, data) {
7330
+ let element = e.extractSingular(up.fragment.provideNodes(value, { origin, data }));
7331
+ this._document = this._buildFauxDocument(element);
7332
+ }
7333
+ _parseContent(value, origin, target, data) {
6958
7334
  if (!target)
6959
7335
  up.fail("must pass a { target } when passing { content }");
6960
7336
  let simplifiedTarget = u.map(up.fragment.parseTargetSteps(target), 'selector').join();
6961
- const matchingElement = e.createFromSelector(simplifiedTarget);
6962
- if (u.isString(value)) {
6963
- matchingElement.innerHTML = value;
6964
- }
6965
- else {
6966
- matchingElement.appendChild(value);
6967
- }
7337
+ let nodes = up.fragment.provideNodes(value, { origin, data });
7338
+ let matchingElement = e.createFromSelector(simplifiedTarget, { content: nodes });
6968
7339
  this._document = this._buildFauxDocument(matchingElement);
6969
7340
  }
6970
- _buildFauxDocument(node) {
7341
+ _buildFauxDocument(nodes) {
7342
+ nodes = u.wrapList(nodes);
6971
7343
  let fauxDocument = document.createElement('up-document');
6972
- fauxDocument.append(node);
6973
- fauxDocument.documentElement = node;
7344
+ fauxDocument.append(...nodes);
6974
7345
  return fauxDocument;
6975
7346
  }
6976
7347
  rootSelector() {
6977
- return up.fragment.toTarget(this._document.documentElement);
7348
+ return up.fragment.toTarget(this._document.children[0]);
6978
7349
  }
6979
7350
  get title() {
6980
7351
  return this._fromHead(this._getTitleText);
@@ -7055,7 +7426,7 @@ up.ResponseDoc = (_a = class ResponseDoc {
7055
7426
  }
7056
7427
  finalizeElement(element) {
7057
7428
  up.NonceableCallback.adoptNonces(element, this._cspNonces);
7058
- if (this._isDocumentBroken) {
7429
+ if (this._document instanceof Document) {
7059
7430
  let brokenElements = e.subtree(element, ':is(noscript,script,audio,video):not(.up-keeping, .up-keeping *)');
7060
7431
  u.each(brokenElements, e.fixParserDamage);
7061
7432
  }
@@ -7164,16 +7535,17 @@ up.RevealMotion = class RevealMotion {
7164
7535
  /***/ (() => {
7165
7536
 
7166
7537
  const u = up.util;
7167
- const CSS_HAS_SUFFIX_PATTERN = /:has\(([^)]+)\)$/;
7538
+ const e = up.element;
7168
7539
  up.Selector = class Selector {
7169
7540
  constructor(selector, elementOrDocument, options = {}) {
7170
7541
  this._filters = [];
7171
- if (!options.destroying) {
7542
+ let matchingInExternalDocument = elementOrDocument && !document.contains(elementOrDocument);
7543
+ if (!matchingInExternalDocument && !options.destroying) {
7172
7544
  this._filters.push(up.fragment.isNotDestroying);
7173
7545
  }
7174
- let matchingInExternalDocument = elementOrDocument && !document.contains(elementOrDocument);
7546
+ this._ignoreLayers = matchingInExternalDocument || options.layer === 'any' || up.layer.count === 1;
7175
7547
  let expandTargetLayer;
7176
- if (matchingInExternalDocument || options.layer === 'any') {
7548
+ if (this._ignoreLayers) {
7177
7549
  expandTargetLayer = up.layer.root;
7178
7550
  }
7179
7551
  else {
@@ -7184,44 +7556,45 @@ up.Selector = class Selector {
7184
7556
  this._filters.push(match => u.some(this._layers, layer => layer.contains(match)));
7185
7557
  expandTargetLayer = this._layers[0];
7186
7558
  }
7187
- let expandedTargets = up.fragment.expandTargets(selector, { ...options, layer: expandTargetLayer });
7188
- this._selectors = expandedTargets.map((target) => {
7189
- if (!up.browser.canHasSelector()) {
7190
- target = target.replace(CSS_HAS_SUFFIX_PATTERN, (match, descendantSelector) => {
7191
- this._filters.push(element => element.querySelector(descendantSelector));
7192
- return '';
7193
- });
7194
- }
7195
- return target || '*';
7196
- });
7559
+ this._selectors = up.fragment.expandTargets(selector, { ...options, layer: expandTargetLayer });
7197
7560
  this._unionSelector = this._selectors.join() || 'match-none';
7198
7561
  }
7199
7562
  matches(element) {
7200
- return element.matches(this._unionSelector) && this._passesFilter(element);
7563
+ return e.elementLikeMatches(element, this._unionSelector) && this._passesFilter(element);
7201
7564
  }
7202
7565
  closest(element) {
7203
- let parentElement;
7204
- if (this.matches(element)) {
7205
- return element;
7566
+ return this._filterOne(element.closest(this._unionSelector));
7567
+ }
7568
+ descendants(root = document) {
7569
+ return this._filterMany(root.querySelectorAll(this._unionSelector));
7570
+ }
7571
+ firstDescendant(root) {
7572
+ if (this._ignoreLayers) {
7573
+ root ||= document;
7574
+ return this._firstSelectorMatch((selector) => root.querySelectorAll(selector));
7206
7575
  }
7207
- else if (parentElement = element.parentElement) {
7208
- return this.closest(parentElement);
7576
+ else {
7577
+ return u.findResult(this._layers, (layer) => {
7578
+ return this._firstSelectorMatch((selector) => e.subtree(layer.element, selector));
7579
+ });
7209
7580
  }
7210
7581
  }
7582
+ subtree(root) {
7583
+ return this._filterMany(e.subtree(root, this._unionSelector));
7584
+ }
7585
+ _firstSelectorMatch(fn) {
7586
+ return u.findResult(this._selectors, (selector) => {
7587
+ return this._filterMany(fn(selector))[0];
7588
+ });
7589
+ }
7211
7590
  _passesFilter(element) {
7212
- return u.every(this._filters, filter => filter(element));
7591
+ return element && u.every(this._filters, filter => filter(element));
7213
7592
  }
7214
- descendants(root = document) {
7215
- const results = u.flatMap(this._selectors, selector => root.querySelectorAll(selector));
7216
- return u.filter(results, element => this._passesFilter(element));
7593
+ _filterOne(element) {
7594
+ return u.presence(element, this._passesFilter.bind(this));
7217
7595
  }
7218
- subtree(root) {
7219
- const results = [];
7220
- if (!(root instanceof Document) && this.matches(root)) {
7221
- results.push(root);
7222
- }
7223
- results.push(...this.descendants(root));
7224
- return results;
7596
+ _filterMany(elements) {
7597
+ return u.filter(elements, this._passesFilter.bind(this));
7225
7598
  }
7226
7599
  };
7227
7600
 
@@ -7356,7 +7729,7 @@ up.URLPattern = class URLPattern {
7356
7729
  this._groups = [];
7357
7730
  const positiveList = [];
7358
7731
  const negativeList = [];
7359
- for (let pattern of u.parseTokens(fullPattern)) {
7732
+ for (let pattern of u.getSimpleTokens(fullPattern)) {
7360
7733
  if (pattern[0] === '-') {
7361
7734
  negativeList.push(pattern.substring(1));
7362
7735
  }
@@ -7479,7 +7852,7 @@ up.framework = (function () {
7479
7852
  return !supportIssue();
7480
7853
  }
7481
7854
  function supportIssue() {
7482
- for (let feature of ['URL', 'Proxy', 'Promise', 'DOMParser', 'FormData']) {
7855
+ for (let feature of ['Promise', 'DOMParser', 'FormData', 'reportError']) {
7483
7856
  if (!window[feature]) {
7484
7857
  return `Browser doesn't support the ${feature} API`;
7485
7858
  }
@@ -7487,6 +7860,11 @@ up.framework = (function () {
7487
7860
  if (document.compatMode === 'BackCompat') {
7488
7861
  return 'Browser is in quirks mode (missing DOCTYPE?)';
7489
7862
  }
7863
+ for (let selector of [':is(*)', ':has(*)']) {
7864
+ if (!CSS.supports(`selector(${selector})`)) {
7865
+ return `Browser doesn't support the ${selector} selector`;
7866
+ }
7867
+ }
7490
7868
  }
7491
7869
  return {
7492
7870
  onEvaled,
@@ -7655,28 +8033,31 @@ up.protocol = (function () {
7655
8033
  return extractHeader(xhr, 'expireCache') || up.migrate.clearCacheFromXHR?.(xhr);
7656
8034
  }
7657
8035
  function contextFromXHR(xhr) {
7658
- return extractHeader(xhr, 'context', JSON.parse);
8036
+ return extractHeader(xhr, 'context', u.parseRelaxedJSON);
7659
8037
  }
7660
8038
  function methodFromXHR(xhr) {
7661
8039
  return extractHeader(xhr, 'method', u.normalizeMethod);
7662
8040
  }
7663
8041
  function titleFromXHR(xhr) {
7664
- return up.migrate.titleFromXHR?.(xhr) ?? extractHeader(xhr, 'title', JSON.parse);
8042
+ return up.migrate.titleFromXHR?.(xhr) ?? extractHeader(xhr, 'title', u.parseRelaxedJSON);
7665
8043
  }
7666
8044
  function eventPlansFromXHR(xhr) {
7667
- return extractHeader(xhr, 'events', JSON.parse);
8045
+ return extractHeader(xhr, 'events', u.parseRelaxedJSON);
7668
8046
  }
7669
8047
  function acceptLayerFromXHR(xhr) {
7670
- return extractHeader(xhr, 'acceptLayer', JSON.parse);
8048
+ return extractHeader(xhr, 'acceptLayer', u.parseRelaxedJSON);
7671
8049
  }
7672
8050
  function dismissLayerFromXHR(xhr) {
7673
- return extractHeader(xhr, 'dismissLayer', JSON.parse);
8051
+ return extractHeader(xhr, 'dismissLayer', u.parseRelaxedJSON);
7674
8052
  }
7675
8053
  const initialRequestMethod = u.memoize(function () {
7676
8054
  return u.normalizeMethod(up.browser.popCookie('_up_method'));
7677
8055
  });
7678
8056
  function locationFromXHR(xhr) {
7679
- return extractHeader(xhr, 'location') || xhr.responseURL;
8057
+ let location = extractHeader(xhr, 'location') || xhr.responseURL;
8058
+ if (location) {
8059
+ return u.normalizeURL(location);
8060
+ }
7680
8061
  }
7681
8062
  const config = new up.Config(() => ({
7682
8063
  methodParam: '_method',
@@ -7841,6 +8222,9 @@ up.script = (function () {
7841
8222
  ],
7842
8223
  nonceableAttributes: [
7843
8224
  'up-watch',
8225
+ 'up-on-keep',
8226
+ 'up-on-hungry',
8227
+ 'up-on-opened',
7844
8228
  'up-on-accepted',
7845
8229
  'up-on-dismissed',
7846
8230
  'up-on-loaded',
@@ -7850,7 +8234,10 @@ up.script = (function () {
7850
8234
  'up-on-offline',
7851
8235
  ],
7852
8236
  scriptSelectors: [
7853
- 'script'
8237
+ 'script:not([type])',
8238
+ 'script[type="text/javascript"]',
8239
+ 'script[type="module"]',
8240
+ 'script[type="importmap"]',
7854
8241
  ],
7855
8242
  noScriptSelectors: [
7856
8243
  'script[type="application/ld+json"]'
@@ -7881,10 +8268,13 @@ up.script = (function () {
7881
8268
  function registerAttrCompiler(...args) {
7882
8269
  let [attr, options, valueCallback] = parseProcessorArgs(args);
7883
8270
  let selector = `[${attr}]`;
8271
+ let { defaultValue } = options;
7884
8272
  let callback = (element) => {
7885
- let value = e.booleanOrStringAttr(element, attr, options.defaultValue);
7886
- if (!value)
8273
+ let value = e.booleanOrStringAttr(element, attr);
8274
+ if (value === false)
7887
8275
  return;
8276
+ if (u.isDefined(defaultValue) && value === true)
8277
+ value = defaultValue;
7888
8278
  return valueCallback(element, value);
7889
8279
  };
7890
8280
  registerProcessor([selector, options, callback]);
@@ -7911,11 +8301,7 @@ up.script = (function () {
7911
8301
  }
7912
8302
  }
7913
8303
  const parseProcessorArgs = function (args) {
7914
- const defaults = u.extractOptions(args);
7915
- const selector = args.shift();
7916
- const callback = args.pop();
7917
- const options = { ...defaults, ...u.extractOptions(args) };
7918
- return [selector, options, callback];
8304
+ return u.args(args, 'val', 'options', 'callback');
7919
8305
  };
7920
8306
  function buildProcessor(args, overrides) {
7921
8307
  let [selector, options, callback] = parseProcessorArgs(args);
@@ -7953,18 +8339,16 @@ up.script = (function () {
7953
8339
  pass.run();
7954
8340
  }
7955
8341
  function registerDestructor(element, destructor) {
7956
- let destructors = element.upDestructors;
7957
- if (!destructors) {
7958
- destructors = [];
7959
- element.upDestructors = destructors;
7960
- element.classList.add('up-can-clean');
7961
- }
7962
- if (u.isArray(destructor)) {
7963
- destructors.push(...destructor);
7964
- }
7965
- else {
7966
- destructors.push(destructor);
7967
- }
8342
+ let fns = u.scanFunctions(destructor);
8343
+ if (!fns.length)
8344
+ return;
8345
+ let registry = (element.upDestructors ||= buildDestructorRegistry(element));
8346
+ registry.guard(fns);
8347
+ }
8348
+ function buildDestructorRegistry(element) {
8349
+ let registry = u.cleaner();
8350
+ registry(e.addClassTemp(element, 'up-can-clean'));
8351
+ return registry;
7968
8352
  }
7969
8353
  function hello(element, options = {}) {
7970
8354
  element = up.fragment.get(element, options);
@@ -7981,18 +8365,12 @@ up.script = (function () {
7981
8365
  return element.upData ||= buildData(element);
7982
8366
  }
7983
8367
  function buildData(element) {
7984
- if (!element.getAttribute) {
7985
- return {};
7986
- }
7987
- let rawJSON = element.getAttribute('up-data');
7988
- let parsedJSON;
7989
- if (rawJSON) {
7990
- parsedJSON = JSON.parse(rawJSON);
7991
- if (!u.isOptions(parsedJSON)) {
7992
- return parsedJSON;
7993
- }
8368
+ let parsedJSON = e.jsonAttr(element, 'up-data') ?? {};
8369
+ if (!u.isOptions(parsedJSON)) {
8370
+ return parsedJSON;
7994
8371
  }
7995
8372
  return {
8373
+ ...element.upTemplateData,
7996
8374
  ...element.dataset,
7997
8375
  ...parsedJSON,
7998
8376
  ...element.upCompileData,
@@ -8016,6 +8394,9 @@ up.script = (function () {
8016
8394
  let selector = config.selector('scriptSelectors');
8017
8395
  u.each(e.subtree(root, selector), disableScript);
8018
8396
  }
8397
+ function isScript(value) {
8398
+ return config.matches(value, 'scriptSelectors');
8399
+ }
8019
8400
  function reset() {
8020
8401
  registeredCompilers = u.filter(registeredCompilers, 'isDefault');
8021
8402
  registeredMacros = u.filter(registeredMacros, 'isDefault');
@@ -8033,6 +8414,7 @@ up.script = (function () {
8033
8414
  findAssets,
8034
8415
  assertAssetsOK,
8035
8416
  disableSubtree: disableScriptsInSubtree,
8417
+ isScript,
8036
8418
  };
8037
8419
  })();
8038
8420
  up.compiler = up.script.compiler;
@@ -8181,7 +8563,7 @@ up.history = (function () {
8181
8563
  }
8182
8564
  }
8183
8565
  function updateLang(newLang) {
8184
- e.toggleAttr(e.root, 'lang', newLang, !!newLang);
8566
+ e.setAttrPresence(e.root, 'lang', newLang, !!newLang);
8185
8567
  }
8186
8568
  up.macro('[up-back]', function (link) {
8187
8569
  if (previousLocation) {
@@ -8223,14 +8605,18 @@ up.fragment = (function () {
8223
8605
  return tagName;
8224
8606
  }
8225
8607
  }
8608
+ const STRONG_TARGET_DERIVERS = [
8609
+ '[up-id]',
8610
+ '[id]',
8611
+ 'html',
8612
+ 'head',
8613
+ 'body',
8614
+ ];
8226
8615
  const config = new up.Config(() => ({
8227
8616
  badTargetClasses: [/^up-/],
8617
+ strongTargetDerivers: STRONG_TARGET_DERIVERS,
8228
8618
  targetDerivers: [
8229
- '[up-id]',
8230
- '[id]',
8231
- 'html',
8232
- 'head',
8233
- 'body',
8619
+ ...STRONG_TARGET_DERIVERS,
8234
8620
  'main',
8235
8621
  '[up-main]',
8236
8622
  upTagName,
@@ -8248,10 +8634,19 @@ up.fragment = (function () {
8248
8634
  'form',
8249
8635
  ],
8250
8636
  verifyDerivedTarget: true,
8637
+ renderOptions: {
8638
+ hungry: true,
8639
+ keep: true,
8640
+ saveScroll: true,
8641
+ saveFocus: true,
8642
+ focus: 'keep',
8643
+ abort: 'target',
8644
+ failOptions: true,
8645
+ feedback: true,
8646
+ },
8251
8647
  navigateOptions: {
8252
8648
  cache: 'auto',
8253
8649
  revalidate: 'auto',
8254
- feedback: true,
8255
8650
  fallback: true,
8256
8651
  focus: 'auto',
8257
8652
  scroll: 'auto',
@@ -8264,7 +8659,7 @@ up.fragment = (function () {
8264
8659
  autoFocus: ['hash', 'autofocus', 'main-if-main', 'keep', 'target-if-lost'],
8265
8660
  autoScroll: ['hash', 'layer-if-main'],
8266
8661
  autoRevalidate: (response) => response.expired,
8267
- skipResponse: defaultSkipResponse
8662
+ skipResponse: defaultSkipResponse,
8268
8663
  }));
8269
8664
  u.delegate(config, ['mainTargets'], () => up.layer.config.any);
8270
8665
  function defaultSkipResponse({ response, expiredResponse }) {
@@ -8323,14 +8718,12 @@ up.fragment = (function () {
8323
8718
  return fragment.isConnected && isNotDestroying(fragment);
8324
8719
  }
8325
8720
  function getSmart(...args) {
8326
- const options = u.extractOptions(args);
8327
- const selector = args.pop();
8328
- const root = args[0];
8329
- if (u.isElementish(selector)) {
8721
+ let [root, selector, options] = parseGetArgs(args);
8722
+ if (u.isElementLike(selector)) {
8330
8723
  return e.get(selector);
8331
8724
  }
8332
8725
  if (root) {
8333
- return getDumb(root, selector, options);
8726
+ return getFirstDescendant(root, selector, options);
8334
8727
  }
8335
8728
  return new up.FragmentFinder({
8336
8729
  selector,
@@ -8339,13 +8732,16 @@ up.fragment = (function () {
8339
8732
  match: options.match,
8340
8733
  }).find();
8341
8734
  }
8342
- function getDumb(...args) {
8343
- return getAll(...args)[0];
8735
+ function getFirstDescendant(...args) {
8736
+ let [root, selectorString, options] = parseGetArgs(args);
8737
+ let selector = new up.Selector(selectorString, root, options);
8738
+ return selector.firstDescendant(root);
8739
+ }
8740
+ function parseGetArgs(args) {
8741
+ return u.args(args, 'val', 'val', 'options');
8344
8742
  }
8345
8743
  function getAll(...args) {
8346
- const options = u.extractOptions(args);
8347
- let selectorString = args.pop();
8348
- const root = args[0];
8744
+ let [root, selectorString, options] = parseGetArgs(args);
8349
8745
  if (u.isElement(selectorString)) {
8350
8746
  return [selectorString];
8351
8747
  }
@@ -8451,8 +8847,9 @@ up.fragment = (function () {
8451
8847
  function cannotTarget(element) {
8452
8848
  throw new up.CannotTarget(untargetableMessage(element));
8453
8849
  }
8454
- function tryToTarget(element, options) {
8455
- return u.findResult(config.targetDerivers, function (deriver) {
8850
+ function tryToTarget(element, options = {}) {
8851
+ let derivers = options.strong ? config.strongTargetDerivers : config.targetDerivers;
8852
+ return u.findResult(derivers, function (deriver) {
8456
8853
  let target = deriveTarget(element, deriver);
8457
8854
  if (target && isGoodTarget(target, element, options)) {
8458
8855
  return target;
@@ -8478,7 +8875,7 @@ up.fragment = (function () {
8478
8875
  }
8479
8876
  }
8480
8877
  function deriveTargetFromPattern(element, deriver) {
8481
- let { includePath, excludeRaw } = up.element.parseSelector(deriver);
8878
+ let { includePath, excludeRaw } = e.parseSelector(deriver);
8482
8879
  if (includePath.length !== 1) {
8483
8880
  throw new up.CannotParse(deriver);
8484
8881
  }
@@ -8516,7 +8913,8 @@ up.fragment = (function () {
8516
8913
  return result;
8517
8914
  }
8518
8915
  function isGoodTarget(target, element, options = {}) {
8519
- return !isAlive(element) || !config.verifyDerivedTarget || up.fragment.get(target, { layer: element, ...options }) === element;
8916
+ let verify = options.verify ?? config.verifyDerivedTarget;
8917
+ return !isAlive(element) || !verify || up.fragment.get(target, { layer: element, ...options }) === element;
8520
8918
  }
8521
8919
  function matchesPattern(pattern, str) {
8522
8920
  if (u.isRegExp(pattern)) {
@@ -8558,7 +8956,7 @@ up.fragment = (function () {
8558
8956
  let firstSwappableTarget = toTarget(layer.getFirstSwappableElement(), options);
8559
8957
  targets.unshift(target.replace(LAYER_PSEUDO, firstSwappableTarget));
8560
8958
  }
8561
- else if (u.isElementish(target)) {
8959
+ else if (u.isElementLike(target)) {
8562
8960
  expanded.push(toTarget(target, options));
8563
8961
  }
8564
8962
  else if (u.isString(target)) {
@@ -8585,11 +8983,13 @@ up.fragment = (function () {
8585
8983
  }
8586
8984
  });
8587
8985
  }
8588
- function resolveOrigin(...args) {
8589
- return (up.migrate.resolveOrigin || modernResolveOrigin)(...args);
8986
+ function resolveOrigin(target, options) {
8987
+ if (!u.isString(target))
8988
+ return target;
8989
+ return (up.migrate.resolveOrigin || modernResolveOrigin)(target, options);
8590
8990
  }
8591
8991
  function splitTarget(target) {
8592
- return u.parseTokens(target, { separator: 'comma' });
8992
+ return u.getComplexTokens(target);
8593
8993
  }
8594
8994
  function parseTargetSteps(target, options = {}) {
8595
8995
  let defaultPlacement = options.defaultPlacement || 'swap';
@@ -8601,7 +9001,7 @@ up.fragment = (function () {
8601
9001
  continue;
8602
9002
  let placement = defaultPlacement;
8603
9003
  let maybe = defaultMaybe;
8604
- selector = selector.replace(/\b::?(before|after)\b/, (_match, customPlacement) => {
9004
+ selector = selector.replace(/\b::?(before|after|content)\b/, (_match, customPlacement) => {
8605
9005
  placement = customPlacement;
8606
9006
  return '';
8607
9007
  });
@@ -8669,13 +9069,13 @@ up.fragment = (function () {
8669
9069
  let elements;
8670
9070
  if (options.target) {
8671
9071
  elements = getAll(options.target, options);
8672
- testFn = (request) => request.isPartOfSubtree(elements);
9072
+ testFn = (request) => request.isBoundToSubtrees(elements);
8673
9073
  reason ||= 'Aborting requests within fragment';
8674
9074
  }
8675
9075
  else {
8676
9076
  let layers = up.layer.getAll(options);
8677
9077
  elements = u.map(layers, 'element');
8678
- testFn = (request) => u.contains(layers, request.layer);
9078
+ testFn = (request) => request.isBoundToLayers(layers);
8679
9079
  reason ||= 'Aborting requests within ' + layers.join(', ');
8680
9080
  }
8681
9081
  let testFnWithAbortable = (request) => request.abortable && testFn(request);
@@ -8690,8 +9090,8 @@ up.fragment = (function () {
8690
9090
  up.destructor(fragment, unsubscribe);
8691
9091
  return unsubscribe;
8692
9092
  }
8693
- function onFirstIntersect(origin, callback, { margin = 0 } = {}) {
8694
- if (e.isIntersectingWindow(origin, { margin })) {
9093
+ function onFirstIntersect(element, callback, { margin = 0 } = {}) {
9094
+ if (e.isIntersectingWindow(element, { margin })) {
8695
9095
  callback();
8696
9096
  return;
8697
9097
  }
@@ -8706,15 +9106,62 @@ up.fragment = (function () {
8706
9106
  }
8707
9107
  let observer = new IntersectionObserver(processIntersectEntries, { rootMargin: `${margin}px` });
8708
9108
  let disconnect = () => observer.disconnect();
8709
- observer.observe(origin);
8710
- onAborted(origin, disconnect);
9109
+ observer.observe(element);
9110
+ up.destructor(element, disconnect);
9111
+ }
9112
+ const STARTS_WITH_SELECTOR = /^([\w-]+|\*)?(#|\.|[:[][a-z-]{3,})/;
9113
+ function provideNodes(value, { origin, originLayer, data, htmlParser = e.createNodesFromHTML } = {}) {
9114
+ if (u.isString(value) && STARTS_WITH_SELECTOR.test(value)) {
9115
+ let [parsedValue, parsedData] = u.parseScalarJSONPairs(value)[0];
9116
+ data = { ...data, ...parsedData };
9117
+ value = up.fragment.get(parsedValue, { layer: 'closest', origin, originLayer }) || up.fail(`Cannot find template "%s"`, value);
9118
+ }
9119
+ if (u.isString(value)) {
9120
+ value = htmlParser(value);
9121
+ }
9122
+ if (isTemplate(value)) {
9123
+ value = cloneTemplate(value, data, { htmlParser });
9124
+ }
9125
+ return u.wrapList(value);
9126
+ }
9127
+ function isTemplate(value) {
9128
+ return u.isElement(value) && value.matches('template, script[type]') && !up.script.isScript(value);
9129
+ }
9130
+ function cloneTemplate(templateOrSelector, data = {}, { origin, htmlParser } = {}) {
9131
+ let template = getSmart(templateOrSelector, { origin }) || up.fail('Template not found: %o', templateOrSelector);
9132
+ let event = up.emit(template, 'up:template:clone', { data, nodes: null, log: ["Using template %o", templateOrSelector] });
9133
+ let nodes = event.nodes ?? defaultTemplateNodes(template, htmlParser);
9134
+ for (let node of nodes) {
9135
+ node.upTemplateData = data;
9136
+ }
9137
+ return nodes;
9138
+ }
9139
+ function defaultTemplateNodes(template, htmlParser = e.createNodesFromHTML) {
9140
+ let templateText = template.innerHTML;
9141
+ return htmlParser(templateText);
9142
+ }
9143
+ function insertTemp(...args) {
9144
+ let [reference, position = 'beforeend', tempValue] = u.args(args, 'val', u.isAdjacentPosition, 'val');
9145
+ let tempNodes = provideNodes(tempValue, { origin: reference });
9146
+ let tempElement = e.wrapIfRequired(tempNodes);
9147
+ let oldPosition = document.contains(tempElement) && e.documentPosition(tempElement);
9148
+ reference.insertAdjacentElement(position, tempElement);
9149
+ if (oldPosition) {
9150
+ return () => {
9151
+ oldPosition[0].insertAdjacentElement(oldPosition[1], tempElement);
9152
+ };
9153
+ }
9154
+ else {
9155
+ up.hello(tempElement);
9156
+ return () => up.destroy(tempElement);
9157
+ }
8711
9158
  }
8712
9159
  up.on('up:framework:boot', function () {
8713
9160
  const { documentElement } = document;
8714
9161
  documentElement.setAttribute('up-source', normalizeSource(location.href));
8715
9162
  up.hello(documentElement);
8716
9163
  if (!up.browser.canPushState()) {
8717
- return up.warn('Cannot push history changes. Next fragment update will load in a new page.');
9164
+ return up.warn('Cannot push history changes. Next render pass with history will load a full page.');
8718
9165
  }
8719
9166
  });
8720
9167
  return {
@@ -8724,7 +9171,7 @@ up.fragment = (function () {
8724
9171
  render,
8725
9172
  navigate,
8726
9173
  get: getSmart,
8727
- getDumb,
9174
+ getFirstDescendant,
8728
9175
  all: getAll,
8729
9176
  subtree: getSubtree,
8730
9177
  contains,
@@ -8758,6 +9205,9 @@ up.fragment = (function () {
8758
9205
  targetForSteps,
8759
9206
  compressNestedSteps,
8760
9207
  containsMainPseudo,
9208
+ insertTemp,
9209
+ provideNodes,
9210
+ cloneTemplate,
8761
9211
  };
8762
9212
  })();
8763
9213
  up.reload = up.fragment.reload;
@@ -8765,6 +9215,7 @@ up.destroy = up.fragment.destroy;
8765
9215
  up.render = up.fragment.render;
8766
9216
  up.navigate = up.fragment.navigate;
8767
9217
  up.visit = up.fragment.visit;
9218
+ up.template = { clone: up.fragment.cloneTemplate };
8768
9219
  u.delegate(up, ['context'], () => up.layer.current);
8769
9220
 
8770
9221
 
@@ -8801,7 +9252,7 @@ up.viewport = (function () {
8801
9252
  up.compiler(config.selectorFn('anchoredRightSelectors'), function (element) {
8802
9253
  return bodyShifter.onAnchoredElementInserted(element);
8803
9254
  });
8804
- function reveal(element, options) {
9255
+ const reveal = up.mockable(function (element, options) {
8805
9256
  options = u.options(options);
8806
9257
  element = f.get(element, options);
8807
9258
  if (!(options.layer = up.layer.get(element))) {
@@ -8813,7 +9264,7 @@ up.viewport = (function () {
8813
9264
  const motion = new up.RevealMotion(element, options);
8814
9265
  motion.start();
8815
9266
  return up.migrate.formerlyAsync?.('up.reveal()') || true;
8816
- }
9267
+ });
8817
9268
  function doFocus(element, { preventScroll, force, inputDevice, focusVisible } = {}) {
8818
9269
  if (force) {
8819
9270
  if (!element.hasAttribute('tabindex') && element.tabIndex === -1) {
@@ -8846,7 +9297,7 @@ up.viewport = (function () {
8846
9297
  function revealHash(hash = location.hash, options) {
8847
9298
  let match = firstHashTarget(hash, options);
8848
9299
  if (match) {
8849
- return up.reveal(match, { top: true });
9300
+ return reveal(match, { top: true });
8850
9301
  }
8851
9302
  }
8852
9303
  function allSelector() {
@@ -8950,11 +9401,11 @@ up.viewport = (function () {
8950
9401
  return new up.FIFOCache({ capacity: 30, normalizeKey: u.matchableURL });
8951
9402
  }
8952
9403
  function parseOptions(args) {
8953
- const options = u.copy(u.extractOptions(args));
9404
+ const [reference, options] = u.args(args, 'val', 'options');
8954
9405
  options.layer = up.layer.get(options);
8955
9406
  let viewports;
8956
- if (args[0]) {
8957
- viewports = [closest(args[0], options)];
9407
+ if (reference) {
9408
+ viewports = [closest(reference, options)];
8958
9409
  }
8959
9410
  else if (options.around) {
8960
9411
  viewports = getAround(options.around, options);
@@ -9014,7 +9465,7 @@ up.viewport = (function () {
9014
9465
  function firstHashTarget(hash, options = {}) {
9015
9466
  if (hash = pureHash(hash)) {
9016
9467
  const selector = [
9017
- e.attrSelector('id', hash),
9468
+ e.idSelector(hash),
9018
9469
  'a' + e.attrSelector('name', hash)
9019
9470
  ].join();
9020
9471
  return f.get(selector, options);
@@ -9040,16 +9491,19 @@ up.viewport = (function () {
9040
9491
  }
9041
9492
  return to;
9042
9493
  }
9043
- let userScrolled = false;
9044
- up.on('scroll', { once: true, beforeBoot: true }, () => userScrolled = true);
9045
- up.on('up:framework:boot', function () {
9046
- u.task(function () {
9047
- if (!userScrolled) {
9048
- return revealHash();
9049
- }
9050
- });
9494
+ document.addEventListener('DOMContentLoaded', function () {
9495
+ revealHash();
9496
+ u.task(revealHash);
9051
9497
  });
9052
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
+ });
9053
9507
  return {
9054
9508
  reveal,
9055
9509
  revealHash,
@@ -9374,7 +9828,7 @@ up.network = (function () {
9374
9828
  cacheSize: 70,
9375
9829
  cacheExpireAge: 15 * 1000,
9376
9830
  cacheEvictAge: 90 * 60 * 1000,
9377
- badResponseTime: 400,
9831
+ lateDelay: 400,
9378
9832
  fail(response) { return (response.status < 200 || response.status > 299) && response.status !== 304; },
9379
9833
  autoCache(request) { return request.isSafe(); },
9380
9834
  expireCache(request, _response) { return !request.isSafe(); },
@@ -9399,10 +9853,7 @@ up.network = (function () {
9399
9853
  return request;
9400
9854
  }
9401
9855
  function parseRequestOptions(args) {
9402
- const options = u.extractOptions(args);
9403
- if (!options.url) {
9404
- options.url = args[0];
9405
- }
9856
+ let options = u.parseArgIntoOptions(args, 'url');
9406
9857
  up.migrate.handleRequestOptions?.(options);
9407
9858
  return options;
9408
9859
  }
@@ -9550,7 +10001,7 @@ up.layer = (function () {
9550
10001
  openAnimation: 'fade-in',
9551
10002
  closeAnimation: 'fade-out',
9552
10003
  dismissLabel: '×',
9553
- dismissAriaLabel: 'Dismiss dialog',
10004
+ dismissARIALabel: 'Dismiss dialog',
9554
10005
  dismissable: true,
9555
10006
  history: 'auto',
9556
10007
  trapFocus: true,
@@ -9630,10 +10081,7 @@ up.layer = (function () {
9630
10081
  }
9631
10082
  }
9632
10083
  }
9633
- else if (options.mode) {
9634
- options.layer = 'new';
9635
- }
9636
- else if (u.isElementish(options.target)) {
10084
+ else if (u.isElementLike(options.target)) {
9637
10085
  options.layer = stack.get(options.target, { normalizeLayerOptions: false });
9638
10086
  }
9639
10087
  else if (options.origin) {
@@ -9834,7 +10282,7 @@ up.link = (function () {
9834
10282
  parser.boolean('abortable');
9835
10283
  parser.boolean('background');
9836
10284
  parser.string('contentType');
9837
- parser.number('badResponseTime');
10285
+ parser.booleanOrNumber('lateDelay');
9838
10286
  parser.number('timeout');
9839
10287
  return options;
9840
10288
  }
@@ -9843,7 +10291,6 @@ up.link = (function () {
9843
10291
  options = u.options(options);
9844
10292
  const parser = new up.OptionsParser(link, options, { fail: true, ...parserOptions });
9845
10293
  parser.include(parseRequestOptions);
9846
- parser.boolean('feedback');
9847
10294
  options.origin ||= link;
9848
10295
  parser.boolean('fail');
9849
10296
  parser.boolean('navigate', { default: true });
@@ -9851,11 +10298,12 @@ up.link = (function () {
9851
10298
  parser.string('target');
9852
10299
  parser.booleanOrString('fallback');
9853
10300
  parser.string('match');
9854
- parser.string('content');
9855
- parser.string('fragment');
9856
10301
  parser.string('document');
9857
- parser.boolean('useKeep');
9858
- parser.boolean('useHungry');
10302
+ parser.string('fragment');
10303
+ parser.string('content');
10304
+ parser.boolean('keep', { attr: 'up-use-keep' });
10305
+ parser.boolean('hungry', { attr: 'up-use-hungry' });
10306
+ parser.json('data', { attr: 'up-use-data' });
9859
10307
  parser.callback('onLoaded');
9860
10308
  parser.callback('onRendered', { mainKey: 'result' });
9861
10309
  parser.callback('onFinished', { mainKey: 'result' });
@@ -9879,6 +10327,7 @@ up.link = (function () {
9879
10327
  parser.string('acceptLocation');
9880
10328
  parser.string('dismissLocation');
9881
10329
  parser.booleanOrString('history');
10330
+ parser.include(up.status.statusOptions);
9882
10331
  parser.booleanOrString('focus');
9883
10332
  parser.boolean('saveScroll');
9884
10333
  parser.boolean('saveFocus');
@@ -9905,10 +10354,15 @@ up.link = (function () {
9905
10354
  }
9906
10355
  const guardEvent = up.event.build('up:link:preload', { log: ['Preloading link %o', link] });
9907
10356
  return follow(link, {
10357
+ abort: false,
9908
10358
  abortable: false,
10359
+ background: true,
10360
+ cache: true,
10361
+ ...up.RenderOptions.NO_INPUT_INTERFERENCE,
10362
+ ...up.RenderOptions.NO_PREVIEWS,
9909
10363
  ...options,
9910
10364
  guardEvent,
9911
- preload: true
10365
+ preload: true,
9912
10366
  });
9913
10367
  }
9914
10368
  function preloadIssue(link) {
@@ -10031,7 +10485,7 @@ up.link = (function () {
10031
10485
  return follow(link, forcedOptions, { defaults });
10032
10486
  }
10033
10487
  up.attribute('up-defer', { defaultValue: 'insert' }, function (link, condition) {
10034
- let doLoad = () => up.error.muteUncriticalRejection(loadDeferred(link));
10488
+ let doLoad = (options) => up.error.muteUncriticalRejection(loadDeferred(link, options));
10035
10489
  onLoadCondition(condition, link, doLoad);
10036
10490
  });
10037
10491
  up.on('up:click', config.selectorFn('followSelectors'), function (event, link) {
@@ -10048,14 +10502,16 @@ up.link = (function () {
10048
10502
  'up-href': e.attr(childLink, 'href'),
10049
10503
  ...e.upAttrs(childLink)
10050
10504
  });
10051
- area.classList.add(...e.upClasses(childLink));
10505
+ e.addClasses(area, e.upClasses(childLink));
10052
10506
  makeFollowable(area);
10053
10507
  }
10054
10508
  });
10055
10509
  up.compiler(config.selectorFn('preloadSelectors'), function (link) {
10056
10510
  if (!isPreloadDisabled(link)) {
10057
- let doPreload = () => up.error.muteUncriticalRejection(preload(link));
10058
- let condition = e.booleanOrStringAttr(link, 'up-preload', null) ?? 'hover';
10511
+ let doPreload = (options) => up.error.muteUncriticalRejection(preload(link, options));
10512
+ let condition = e.booleanOrStringAttr(link, 'up-preload');
10513
+ if (condition === true || u.isUndefined(condition))
10514
+ condition = 'hover';
10059
10515
  onLoadCondition(condition, link, doPreload);
10060
10516
  }
10061
10517
  });
@@ -10096,10 +10552,11 @@ up.form = (function () {
10096
10552
  const e = up.element;
10097
10553
  const config = new up.Config(() => ({
10098
10554
  groupSelectors: ['[up-form-group]', 'fieldset', 'label', 'form'],
10099
- fieldSelectors: ['select', 'input:not([type=submit]):not([type=image])', 'button[type]:not([type=submit])', 'textarea'],
10555
+ fieldSelectors: ['select', 'input:not([type=submit], [type=image], [type=button])', 'button[type]:not([type=submit], [type=button])', 'textarea'],
10100
10556
  submitSelectors: ['form:is([up-submit], [up-target], [up-layer], [up-transition])'],
10101
10557
  noSubmitSelectors: ['[up-submit=false]', '[target]', e.crossOriginSelector('action')],
10102
10558
  submitButtonSelectors: ['input[type=submit]', 'input[type=image]', 'button[type=submit]', 'button:not([type])'],
10559
+ genericButtonSelectors: ['input[type=button]', 'button[type=button]'],
10103
10560
  watchInputEvents: ['input', 'change'],
10104
10561
  watchInputDelay: 0,
10105
10562
  watchChangeEvents: ['change'],
@@ -10124,6 +10581,9 @@ up.form = (function () {
10124
10581
  function findSubmitButtons(root) {
10125
10582
  return e.subtree(root, submitButtonSelector());
10126
10583
  }
10584
+ function findGenericButtons(root) {
10585
+ return e.subtree(root, config.selector('genericButtonSelectors'));
10586
+ }
10127
10587
  function isSubmitButton(element) {
10128
10588
  return element?.matches(submitButtonSelector());
10129
10589
  }
@@ -10139,7 +10599,6 @@ up.form = (function () {
10139
10599
  let parser = new up.OptionsParser(form, options, parserOptions);
10140
10600
  parser.include(destinationOptions);
10141
10601
  parser.string('failTarget', { default: up.fragment.tryToTarget(form) });
10142
- parser.booleanOrString('disable');
10143
10602
  options.guardEvent ||= up.event.build('up:form:submit', {
10144
10603
  submitButton: options.submitButton,
10145
10604
  log: 'Submitting form',
@@ -10147,14 +10606,14 @@ up.form = (function () {
10147
10606
  form,
10148
10607
  });
10149
10608
  options.origin ||= up.viewport.focusedElementWithin(form) || options.submitButton || form;
10609
+ options.activeElements = u.uniq([options.origin, options.submitButton, form].filter(u.isElement));
10150
10610
  parser.include(up.link.followOptions);
10151
10611
  return options;
10152
10612
  }
10153
10613
  function watchOptions(field, options, parserOptions = {}) {
10154
10614
  options = u.options(options);
10155
10615
  let parser = new up.OptionsParser(field, options, { ...parserOptions, closest: true, attrPrefix: 'up-watch-' });
10156
- parser.boolean('feedback');
10157
- parser.booleanOrString('disable');
10616
+ parser.include(up.status.statusOptions);
10158
10617
  parser.string('event');
10159
10618
  parser.number('delay');
10160
10619
  let config = up.form.config;
@@ -10169,61 +10628,52 @@ up.form = (function () {
10169
10628
  return options;
10170
10629
  }
10171
10630
  function disableContainer(container) {
10172
- let focusedElement = document.activeElement;
10631
+ let controls = [
10632
+ ...findFields(container),
10633
+ ...findSubmitButtons(container),
10634
+ ...findGenericButtons(container),
10635
+ ];
10636
+ return u.sequence(u.map(controls, disableControl));
10637
+ }
10638
+ function disableControl(control) {
10639
+ if (control.disabled)
10640
+ return;
10173
10641
  let focusFallback;
10174
- let controls = [...findFields(container), ...findSubmitButtons(container)];
10175
- for (let control of controls) {
10176
- if (control === focusedElement) {
10177
- focusFallback = findGroup(focusedElement);
10178
- }
10179
- raiseDisableStack(control);
10180
- }
10181
- if (focusFallback) {
10642
+ if (document.activeElement === control) {
10643
+ focusFallback = findGroup(control);
10644
+ control.disabled = true;
10182
10645
  up.focus(focusFallback, { force: true, preventScroll: true });
10183
10646
  }
10184
- return function () {
10185
- controls.forEach(lowerDisableStack);
10186
- };
10187
- }
10188
- function raiseDisableStack(control) {
10189
- if (!control.upDisableCount) {
10190
- control.upDisableCount ||= 0;
10191
- control.upOriginalDisabled = control.disabled;
10192
- }
10193
- control.upDisableCount++;
10194
- control.disabled = true;
10195
- }
10196
- function lowerDisableStack(control) {
10197
- if (control.upDisableCount) {
10198
- if (!control.disabled) {
10199
- control.upDisableCount = 0;
10200
- }
10201
- else {
10202
- control.upDisableCount--;
10203
- if (!control.upDisableCount) {
10204
- control.disabled = control.upOriginalDisabled;
10205
- }
10206
- }
10647
+ else {
10648
+ control.disabled = true;
10207
10649
  }
10650
+ return () => { control.disabled = false; };
10208
10651
  }
10209
- function disableWhile(promise, options) {
10210
- let undoDisable = handleDisableOption(options);
10211
- u.always(promise, undoDisable);
10212
- }
10213
- function handleDisableOption({ disable, origin }) {
10214
- if (!disable)
10215
- return u.noop;
10216
- let missingOption = (key) => { up.fail("Cannot process { disable: '%s' } option without { %s }", disable, key); };
10217
- let getOrigin = () => origin || missingOption('origin');
10218
- let getOriginForm = () => getScope(getOrigin());
10219
- let containers;
10652
+ function getDisableContainers(disable, origin) {
10653
+ let originScope = () => getScope(origin);
10220
10654
  if (disable === true) {
10221
- containers = [getOriginForm()];
10655
+ return [originScope()];
10656
+ }
10657
+ else if (u.isElement(disable)) {
10658
+ return [disable];
10222
10659
  }
10223
10660
  else if (u.isString(disable)) {
10224
- containers = up.fragment.subtree(getOriginForm(), disable, { origin });
10661
+ return up.fragment.subtree(originScope(), disable, { origin });
10662
+ }
10663
+ else if (u.isArray(disable)) {
10664
+ return u.flatMap(disable, (d) => getDisableContainers(d, origin));
10225
10665
  }
10226
- return u.sequence(containers.map(disableContainer));
10666
+ else {
10667
+ return [];
10668
+ }
10669
+ }
10670
+ function getDisablePreviewFn(disable, origin) {
10671
+ return function (preview) {
10672
+ let containers = getDisableContainers(disable, origin);
10673
+ for (let container of containers) {
10674
+ preview.disable(container);
10675
+ }
10676
+ };
10227
10677
  }
10228
10678
  function destinationOptions(form, options, parserOptions) {
10229
10679
  options = u.options(options);
@@ -10251,10 +10701,10 @@ up.form = (function () {
10251
10701
  }
10252
10702
  return options;
10253
10703
  }
10254
- function watch(root, ...args) {
10704
+ function watch(...args) {
10705
+ let [root, options, callback] = u.args(args, 'val', 'options', 'callback');
10255
10706
  root = up.element.get(root);
10256
- const callback = u.extractCallback(args) || watchCallbackFromElement(root) || up.fail('No callback given for up.watch()');
10257
- let options = u.extractOptions(args);
10707
+ callback ||= watchCallbackFromElement(root) || up.fail('No callback given for up.watch()');
10258
10708
  const watcher = new up.FieldWatcher(root, options, callback);
10259
10709
  watcher.start();
10260
10710
  return () => watcher.stop();
@@ -10262,12 +10712,12 @@ up.form = (function () {
10262
10712
  function watchCallbackFromElement(element) {
10263
10713
  let rawCallback = element.getAttribute('up-watch');
10264
10714
  if (rawCallback) {
10265
- return up.NonceableCallback.fromString(rawCallback).toFunction('value', 'name').bind(element);
10715
+ return up.NonceableCallback.fromString(rawCallback).toFunction('value', 'name', 'options').bind(element);
10266
10716
  }
10267
10717
  }
10268
10718
  function autosubmit(target, options = {}) {
10269
10719
  const onChange = (_diff, renderOptions) => submit(target, renderOptions);
10270
- return watch(target, { options, batch: true }, onChange);
10720
+ return watch(target, { ...options, batch: true }, onChange);
10271
10721
  }
10272
10722
  function getGroupSelectors() {
10273
10723
  return up.migrate.migratedFormGroupSelectors?.() || config.groupSelectors;
@@ -10279,10 +10729,10 @@ up.form = (function () {
10279
10729
  return u.findResult(getGroupSelectors(), function (groupSelector) {
10280
10730
  let group = field.closest(groupSelector);
10281
10731
  if (group) {
10282
- let goodDerivedGroupTarget = up.fragment.tryToTarget(group);
10732
+ let strongDerivedGroupTarget = up.fragment.tryToTarget(group, { strong: true });
10283
10733
  let goodDerivedFieldTarget = up.fragment.tryToTarget(field);
10284
10734
  let groupHasFieldTarget = goodDerivedFieldTarget && (group !== field) && `${groupSelector}:has(${goodDerivedFieldTarget})`;
10285
- let target = goodDerivedGroupTarget || groupHasFieldTarget;
10735
+ let target = strongDerivedGroupTarget || groupHasFieldTarget;
10286
10736
  if (target) {
10287
10737
  return {
10288
10738
  target,
@@ -10374,7 +10824,7 @@ up.form = (function () {
10374
10824
  target.classList.add('up-switched');
10375
10825
  });
10376
10826
  function parseSwitchTokens(str) {
10377
- return u.parseTokens(str, { json: true });
10827
+ return u.getSimpleTokens(str, { json: true });
10378
10828
  }
10379
10829
  function findSwitcherForTarget(target) {
10380
10830
  const form = getScope(target);
@@ -10389,8 +10839,13 @@ up.form = (function () {
10389
10839
  const element = up.fragment.get(elementOrSelector, options);
10390
10840
  return element.form || element.closest('form');
10391
10841
  }
10392
- function getScope(element, options) {
10393
- return getForm(element, options) || up.layer.get(element).element;
10842
+ function getScope(origin, options) {
10843
+ if (origin) {
10844
+ return getForm(origin, options) || up.layer.get(origin).element;
10845
+ }
10846
+ else {
10847
+ return up.layer.current.element;
10848
+ }
10394
10849
  }
10395
10850
  function focusedField() {
10396
10851
  return u.presence(document.activeElement, isField);
@@ -10442,8 +10897,8 @@ up.form = (function () {
10442
10897
  submitButtons: findSubmitButtons,
10443
10898
  focusedField,
10444
10899
  switchTarget,
10445
- disableWhile,
10446
10900
  disable: disableContainer,
10901
+ getDisablePreviewFn,
10447
10902
  group: findGroup,
10448
10903
  groupSolution: findGroupSolution,
10449
10904
  groupSelectors: getGroupSelectors,
@@ -10461,22 +10916,24 @@ up.validate = up.form.validate;
10461
10916
  /* 98 */
10462
10917
  /***/ (() => {
10463
10918
 
10464
- up.feedback = (function () {
10919
+ up.status = (function () {
10465
10920
  const u = up.util;
10466
10921
  const e = up.element;
10922
+ let namedPreviewFns = {};
10467
10923
  const config = new up.Config(() => ({
10468
10924
  currentClasses: ['up-current'],
10925
+ activeClasses: ['up-active'],
10926
+ loadingClasses: ['up-loading'],
10469
10927
  navSelectors: ['[up-nav]', 'nav'],
10470
10928
  noNavSelectors: ['[up-nav=false]'],
10471
10929
  }));
10472
10930
  function reset() {
10473
10931
  up.layer.root.feedbackLocation = null;
10932
+ namedPreviewFns = u.pickBy(namedPreviewFns, 'isDefault');
10474
10933
  }
10475
- const CLASS_ACTIVE = 'up-active';
10476
- const CLASS_LOADING = 'up-loading';
10477
10934
  const SELECTOR_LINK = 'a, [up-href]';
10478
- function linkURLs(link) {
10479
- return link.upFeedbackURLs ||= new up.LinkFeedbackURLs(link);
10935
+ function linkCurrentURLs(link) {
10936
+ return link.upCurrentURLs ||= new up.LinkCurrentURLs(link);
10480
10937
  }
10481
10938
  function updateFragment(fragment, { layer } = {}) {
10482
10939
  layer ||= up.layer.get(fragment);
@@ -10485,11 +10942,11 @@ up.feedback = (function () {
10485
10942
  const navLinkSelector = `${navSelector} :is(${SELECTOR_LINK}), ${navSelector}:is(${SELECTOR_LINK})`;
10486
10943
  const links = up.fragment.all(navLinkSelector, { layer });
10487
10944
  for (let link of links) {
10488
- const isCurrent = linkURLs(link).isCurrent(layerLocation);
10945
+ const isCurrent = linkCurrentURLs(link).isCurrent(layerLocation);
10489
10946
  for (let currentClass of config.currentClasses) {
10490
10947
  link.classList.toggle(currentClass, isCurrent);
10491
10948
  }
10492
- e.toggleAttr(link, 'aria-current', 'page', isCurrent);
10949
+ e.setAttrPresence(link, 'aria-current', 'page', isCurrent);
10493
10950
  }
10494
10951
  }
10495
10952
  function getMatchableLayerLocation(layer) {
@@ -10498,24 +10955,88 @@ up.feedback = (function () {
10498
10955
  function findActivatableArea(element) {
10499
10956
  return e.ancestor(element, SELECTOR_LINK) || element;
10500
10957
  }
10501
- function showAroundRequest(request, options) {
10502
- if (!options.feedback) {
10958
+ function runPreviews(request, renderOptions) {
10959
+ let { bindLayer } = request;
10960
+ let focusCapsule = up.FocusCapsule.preserve(bindLayer);
10961
+ let applyPreviews = () => doRunPreviews(request, renderOptions);
10962
+ let revertPreviews = bindLayer.asCurrent(applyPreviews);
10963
+ up.on('focusin', { once: true }, () => focusCapsule = null);
10964
+ return () => {
10965
+ bindLayer.asCurrent(revertPreviews);
10966
+ focusCapsule?.restore(bindLayer, { preventScroll: true });
10967
+ };
10968
+ }
10969
+ function doRunPreviews(request, renderOptions) {
10970
+ let { fragment, fragments, origin } = request;
10971
+ let cleaner = u.cleaner();
10972
+ let previewForFragment = (fragment) => new up.Preview({ fragment, request, renderOptions, cleaner });
10973
+ let singlePreview = previewForFragment(fragment);
10974
+ singlePreview.run(resolvePreviewFns(renderOptions.preview));
10975
+ singlePreview.run(getPlaceholderPreviewFn(renderOptions.placeholder));
10976
+ singlePreview.run(getFeedbackClassesPreviewFn(renderOptions.feedback, fragments));
10977
+ singlePreview.run(up.form.getDisablePreviewFn(renderOptions.disable, origin));
10978
+ for (let fragment of fragments) {
10979
+ let eachPreview = previewForFragment(fragment);
10980
+ eachPreview.run(e.matchSelectorMap(renderOptions.previewMap, fragment));
10981
+ eachPreview.run(e.matchSelectorMap(renderOptions.placeholderMap, fragment).flatMap(getPlaceholderPreviewFn));
10982
+ }
10983
+ return cleaner.clean;
10984
+ }
10985
+ function getPlaceholderPreviewFn(placeholder) {
10986
+ if (!placeholder)
10503
10987
  return;
10988
+ return function (preview) {
10989
+ preview.showPlaceholder(placeholder);
10990
+ };
10991
+ }
10992
+ function resolvePreviewFns(value) {
10993
+ if (u.isFunction(value)) {
10994
+ return [value];
10995
+ }
10996
+ else if (u.isString(value)) {
10997
+ return resolvePreviewString(value);
10504
10998
  }
10505
- let clean = (fn) => u.always(request, fn);
10506
- let activeElement = getActiveElementFromRenderOptions(request);
10507
- if (activeElement) {
10508
- clean(e.addTemporaryClass(activeElement, CLASS_ACTIVE));
10999
+ else if (u.isArray(value)) {
11000
+ return value.flatMap(resolvePreviewFns);
10509
11001
  }
10510
- for (let fragment of request.fragments) {
10511
- clean(e.addTemporaryClass(fragment, CLASS_LOADING));
11002
+ else {
11003
+ return [];
10512
11004
  }
10513
11005
  }
10514
- function getActiveElementFromRenderOptions(request) {
10515
- let activeElement = request.origin;
10516
- if (activeElement) {
10517
- return findActivatableArea(activeElement);
10518
- }
11006
+ function resolvePreviewString(str) {
11007
+ return u.map(u.parseScalarJSONPairs(str), ([name, parsedOptions]) => {
11008
+ let previewFn = namedPreviewFns[name] || up.fail('Unknown preview "%s"', name);
11009
+ return function (preview, runOptions) {
11010
+ up.puts('[up-preview]', 'Showing preview %o', name);
11011
+ return previewFn(preview, parsedOptions || runOptions);
11012
+ };
11013
+ });
11014
+ }
11015
+ function getActiveElements({ origin, activeElements }) {
11016
+ activeElements ||= u.wrapList(origin);
11017
+ return activeElements.map(findActivatableArea);
11018
+ }
11019
+ function registerPreview(name, previewFn) {
11020
+ previewFn.isDefault = up.framework.evaling;
11021
+ namedPreviewFns[name] = previewFn;
11022
+ }
11023
+ function getFeedbackClassesPreviewFn(feedbackOption, fragments) {
11024
+ if (!feedbackOption)
11025
+ return;
11026
+ return function (preview) {
11027
+ preview.addClassBatch(getActiveElements(preview.renderOptions), config.activeClasses);
11028
+ preview.addClassBatch(fragments, config.loadingClasses);
11029
+ };
11030
+ }
11031
+ function statusOptions(element, options, parserOptions) {
11032
+ options = u.options(options);
11033
+ const parser = new up.OptionsParser(element, options, parserOptions);
11034
+ parser.booleanOrString('disable');
11035
+ parser.boolean('feedback');
11036
+ parser.string('preview');
11037
+ parser.booleanOrString('revalidatePreview');
11038
+ parser.string('placeholder');
11039
+ return options;
10519
11040
  }
10520
11041
  function updateLayerIfLocationChanged(layer) {
10521
11042
  const processedLocation = layer.feedbackLocation;
@@ -10543,9 +11064,13 @@ up.feedback = (function () {
10543
11064
  up.on('up:framework:reset', reset);
10544
11065
  return {
10545
11066
  config,
10546
- showAroundRequest,
11067
+ preview: registerPreview,
11068
+ resolvePreviewFns,
11069
+ runPreviews,
11070
+ statusOptions,
10547
11071
  };
10548
11072
  })();
11073
+ up.preview = up.status.preview;
10549
11074
 
10550
11075
 
10551
11076
  /***/ }),
@@ -10560,9 +11085,9 @@ up.radio = (function () {
10560
11085
  pollInterval: 30000,
10561
11086
  }));
10562
11087
  function hungrySteps(renderOptions) {
10563
- let { useHungry, origin, layer: renderLayer } = renderOptions;
11088
+ let { hungry, origin, layer: renderLayer, meta } = renderOptions;
10564
11089
  let steps = { current: [], other: [] };
10565
- if (!useHungry)
11090
+ if (!hungry)
10566
11091
  return steps;
10567
11092
  let hungrySelector = config.selector('hungrySelectors');
10568
11093
  const layerPreference = [renderLayer, ...renderLayer.ancestors, ...renderLayer.descendants];
@@ -10586,8 +11111,9 @@ up.radio = (function () {
10586
11111
  origin,
10587
11112
  ...motionOptions,
10588
11113
  placement: 'swap',
10589
- useKeep: true,
11114
+ keep: true,
10590
11115
  maybe: true,
11116
+ meta,
10591
11117
  selectEvent,
10592
11118
  selectCallback,
10593
11119
  originalRenderOptions: renderOptions,
@@ -10613,6 +11139,7 @@ up.radio = (function () {
10613
11139
  parser.number('interval', { default: config.pollInterval });
10614
11140
  parser.string('ifLayer', { default: 'front' });
10615
11141
  parser.include(up.link.requestOptions);
11142
+ parser.include(up.status.statusOptions);
10616
11143
  return options;
10617
11144
  }
10618
11145
  up.attribute('up-poll', function (fragment) {