unpoly-rails 3.9.5 → 3.10.0.rc1

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-rc1'
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;
@@ -2016,20 +2213,20 @@ up.RenderJob = (_a = class RenderJob {
2016
2213
  }
2017
2214
  _getChange() {
2018
2215
  if (this.options.url) {
2019
- let onRequest = (request) => this._handleAbortOption(request);
2020
- return new up.Change.FromURL({ ...this.options, onRequest });
2021
- }
2022
- else if (this.options.response) {
2023
- let onRender = () => this._handleAbortOption(null);
2024
- return new up.Change.FromResponse({ ...this.options, onRender });
2216
+ let onRequestProcessed = (request) => this._handleAbortOption(request);
2217
+ return new up.Change.FromURL({ ...this.options, onRequestProcessed });
2025
2218
  }
2026
2219
  else {
2027
2220
  let onRender = () => this._handleAbortOption(null);
2028
- return new up.Change.FromContent({ ...this.options, onRender });
2221
+ if (this.options.response) {
2222
+ return new up.Change.FromResponse({ ...this.options, onRender });
2223
+ }
2224
+ else {
2225
+ return new up.Change.FromContent({ ...this.options, onRender });
2226
+ }
2029
2227
  }
2030
2228
  }
2031
- _guardRender() {
2032
- up.browser.assertConfirmed(this.options);
2229
+ _emitGuardEvent() {
2033
2230
  let guardEvent = u.pluckKey(this.options, 'guardEvent');
2034
2231
  if (guardEvent) {
2035
2232
  guardEvent.renderOptions = this.options;
@@ -2037,24 +2234,23 @@ up.RenderJob = (_a = class RenderJob {
2037
2234
  throw new up.Aborted(`Rendering was prevented by ${guardEvent.type} listener`);
2038
2235
  }
2039
2236
  }
2040
- up.RenderOptions.assertContentGiven(this.options);
2041
2237
  }
2042
2238
  _handleAbortOption(request) {
2043
2239
  let { abort } = this.options;
2044
2240
  if (!abort || !up.network.isBusy())
2045
2241
  return;
2046
- let { fragments, layer, origin, newLayer } = this._getChange().getPreflightProps();
2242
+ let { bindFragments, bindLayer, origin, layer } = this._getChange().getPreflightProps();
2047
2243
  let abortOptions = {
2048
2244
  except: request,
2049
2245
  logOnce: ['up.render()', 'Change with { abort } option will abort other requests'],
2050
- newLayer,
2246
+ newLayer: (layer === 'new'),
2051
2247
  origin,
2052
2248
  };
2053
2249
  if (abort === 'target') {
2054
- up.fragment.abort(fragments, abortOptions);
2250
+ up.fragment.abort(bindFragments, { ...abortOptions });
2055
2251
  }
2056
2252
  else if (abort === 'layer') {
2057
- up.fragment.abort({ ...abortOptions, layer });
2253
+ up.fragment.abort({ ...abortOptions, layer: bindLayer });
2058
2254
  }
2059
2255
  else if (abort === 'all' || abort === true) {
2060
2256
  up.fragment.abort({ ...abortOptions, layer: 'any' });
@@ -2063,12 +2259,12 @@ up.RenderJob = (_a = class RenderJob {
2063
2259
  abort(abortOptions);
2064
2260
  }
2065
2261
  else {
2066
- up.fragment.abort(abort, { ...abortOptions, layer });
2262
+ up.fragment.abort(abort, { ...abortOptions, layer: bindLayer });
2067
2263
  }
2068
2264
  }
2069
2265
  },
2070
2266
  (() => {
2071
- u.delegate(_a.prototype, ['then', 'catch', 'finally'], function () { return this._rendered; });
2267
+ u.delegatePromise(_a.prototype, '_rendered');
2072
2268
  u.memoizeMethod(_a.prototype, {
2073
2269
  _awaitFinished: true,
2074
2270
  _getChange: true,
@@ -2081,21 +2277,14 @@ up.RenderJob = (_a = class RenderJob {
2081
2277
  /* 26 */
2082
2278
  /***/ (() => {
2083
2279
 
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 {
2280
+ up.Change.DestroyFragment = class DestroyFragment extends up.Change {
2093
2281
  constructor(options) {
2094
2282
  super(options);
2095
2283
  this._layer = up.layer.get(options) || up.layer.current;
2096
2284
  this._element = this.options.element;
2097
2285
  this._animation = this.options.animation;
2098
2286
  this._log = this.options.log;
2287
+ this._onFinished = this.options.onFinished;
2099
2288
  }
2100
2289
  execute() {
2101
2290
  this._parent = this._element.parentNode;
@@ -2111,12 +2300,12 @@ up.Change.DestroyFragment = class DestroyFragment extends up.Change.Removal {
2111
2300
  this._emitDestroyed();
2112
2301
  await this._animate();
2113
2302
  this._wipe();
2114
- this.onFinished();
2303
+ this._onFinished?.();
2115
2304
  }
2116
2305
  _destroyNow() {
2117
2306
  this._wipe();
2118
2307
  this._emitDestroyed();
2119
- this.onFinished();
2308
+ this._onFinished?.();
2120
2309
  }
2121
2310
  _animate() {
2122
2311
  return up.motion.animate(this._element, this._animation, this.options);
@@ -2136,7 +2325,7 @@ up.Change.DestroyFragment = class DestroyFragment extends up.Change.Removal {
2136
2325
 
2137
2326
 
2138
2327
  /***/ }),
2139
- /* 28 */
2328
+ /* 27 */
2140
2329
  /***/ (() => {
2141
2330
 
2142
2331
  let u = up.util;
@@ -2153,9 +2342,10 @@ up.Change.OpenLayer = class OpenLayer extends up.Change.Addition {
2153
2342
  context: this._buildLayer().context,
2154
2343
  origin: this.options.origin,
2155
2344
  target: this.target,
2156
- layer: this._baseLayer,
2157
- fragments: u.compact([up.fragment.get(':main', { layer: this._baseLayer })]),
2158
- newLayer: true,
2345
+ bindLayer: this._baseLayer,
2346
+ layer: 'new',
2347
+ bindFragments: u.compact([up.fragment.get(':main', { layer: this._baseLayer })]),
2348
+ fragments: [],
2159
2349
  };
2160
2350
  }
2161
2351
  execute(responseDoc, onApplicable) {
@@ -2205,7 +2395,7 @@ up.Change.OpenLayer = class OpenLayer extends up.Change.Addition {
2205
2395
  fragments: [this._content],
2206
2396
  target: this.target,
2207
2397
  });
2208
- up.hello(this.layer.element, { ...this.options, layer: this.layer });
2398
+ up.hello(this.layer.element, { ...this.options, layer: this.layer, dataRoot: this._content });
2209
2399
  this._handleScroll();
2210
2400
  this._newOverlayResult.finished = this._finish();
2211
2401
  this.layer.opening = false;
@@ -2290,7 +2480,7 @@ up.Change.OpenLayer = class OpenLayer extends up.Change.Addition {
2290
2480
 
2291
2481
 
2292
2482
  /***/ }),
2293
- /* 29 */
2483
+ /* 28 */
2294
2484
  /***/ (() => {
2295
2485
 
2296
2486
  var _a;
@@ -2306,14 +2496,16 @@ up.Change.UpdateLayer = (_a = class UpdateLayer extends up.Change.Addition {
2306
2496
  }
2307
2497
  getPreflightProps() {
2308
2498
  this._matchPreflight();
2499
+ let fragments = this._getFragments();
2309
2500
  return {
2310
2501
  layer: this.layer,
2502
+ bindLayer: this.layer,
2311
2503
  mode: this.layer.mode,
2312
2504
  context: u.merge(this.layer.context, this._context),
2313
2505
  origin: this.options.origin,
2314
2506
  target: this._bestPreflightSelector(),
2315
- fragments: this._getFragments(),
2316
- newLayer: false,
2507
+ fragments,
2508
+ bindFragments: fragments,
2317
2509
  };
2318
2510
  }
2319
2511
  _bestPreflightSelector() {
@@ -2439,7 +2631,7 @@ up.Change.UpdateLayer = (_a = class UpdateLayer extends up.Change.Addition {
2439
2631
 
2440
2632
 
2441
2633
  /***/ }),
2442
- /* 30 */
2634
+ /* 29 */
2443
2635
  /***/ (() => {
2444
2636
 
2445
2637
  const u = up.util;
@@ -2511,7 +2703,7 @@ up.Change.UpdateSteps = class UpdateSteps extends up.Change.Addition {
2511
2703
  up.script.clean(step.oldElement, { layer: step.layer });
2512
2704
  },
2513
2705
  afterDetach() {
2514
- up.element.cleanJQuery();
2706
+ e.cleanJQuery();
2515
2707
  up.fragment.emitDestroyed(step.oldElement, { parent, log: false });
2516
2708
  },
2517
2709
  scrollNew: () => {
@@ -2555,7 +2747,7 @@ up.Change.UpdateSteps = class UpdateSteps extends up.Change.Addition {
2555
2747
  }
2556
2748
  }
2557
2749
  _findKeepPlan(options) {
2558
- if (!options.useKeep) {
2750
+ if (!options.keep) {
2559
2751
  return;
2560
2752
  }
2561
2753
  const { oldElement, newElement } = options;
@@ -2570,7 +2762,7 @@ up.Change.UpdateSteps = class UpdateSteps extends up.Change.Addition {
2570
2762
  partner = up.fragment.get(newElement, partnerSelector, lookupOpts);
2571
2763
  }
2572
2764
  else {
2573
- partner = up.fragment.subtree(newElement, partnerSelector, lookupOpts)[0];
2765
+ partner = e.subtreeFirst(newElement, partnerSelector, lookupOpts);
2574
2766
  }
2575
2767
  if (partner && e.booleanAttr(partner, 'up-keep') !== false) {
2576
2768
  const plan = {
@@ -2586,7 +2778,7 @@ up.Change.UpdateSteps = class UpdateSteps extends up.Change.Addition {
2586
2778
  }
2587
2779
  _preserveKeepables(step) {
2588
2780
  const keepPlans = [];
2589
- if (step.useKeep) {
2781
+ if (step.keep) {
2590
2782
  for (let keepable of step.oldElement.querySelectorAll('[up-keep]')) {
2591
2783
  let keepPlan = this._findKeepPlan({ ...step, oldElement: keepable, descendantsOnly: true });
2592
2784
  if (keepPlan) {
@@ -2647,11 +2839,11 @@ up.Change.UpdateSteps = class UpdateSteps extends up.Change.Addition {
2647
2839
 
2648
2840
 
2649
2841
  /***/ }),
2650
- /* 31 */
2842
+ /* 30 */
2651
2843
  /***/ (() => {
2652
2844
 
2653
2845
  const u = up.util;
2654
- up.Change.CloseLayer = class CloseLayer extends up.Change.Removal {
2846
+ up.Change.CloseLayer = class CloseLayer extends up.Change {
2655
2847
  constructor(options) {
2656
2848
  super(options);
2657
2849
  this._verb = options.verb;
@@ -2723,27 +2915,29 @@ up.Change.CloseLayer = class CloseLayer extends up.Change.Removal {
2723
2915
 
2724
2916
 
2725
2917
  /***/ }),
2726
- /* 32 */
2918
+ /* 31 */
2727
2919
  /***/ (() => {
2728
2920
 
2729
2921
  var _a;
2730
2922
  const u = up.util;
2731
2923
  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);
2924
+ async execute() {
2925
+ let newPageReason = this._newPageReason();
2926
+ if (newPageReason) {
2927
+ up.puts('up.render()', newPageReason);
2736
2928
  up.network.loadPage(this.options);
2737
2929
  return u.unresolvablePromise();
2738
2930
  }
2739
2931
  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
2932
  if (this.options.preload) {
2744
2933
  return this.request;
2745
2934
  }
2746
- return u.always(this.request, responseOrError => this._onRequestSettled(responseOrError));
2935
+ this._onRequestProcessed();
2936
+ return await u.always(this.request, responseOrError => this._onRequestSettled(responseOrError));
2937
+ }
2938
+ _onRequestProcessed() {
2939
+ this.options.onRequestProcessed?.(this.request);
2940
+ this.request.runPreviews(this.options);
2747
2941
  }
2748
2942
  _newPageReason() {
2749
2943
  if (u.isCrossOrigin(this.options.url)) {
@@ -2759,15 +2953,16 @@ up.Change.FromURL = (_a = class FromURL extends up.Change {
2759
2953
  return {
2760
2954
  ...this.options,
2761
2955
  ...successAttrs,
2762
- ...u.renameKeys(failAttrs, up.fragment.failKey)
2956
+ ...u.withRenamedKeys(failAttrs, up.fragment.failKey),
2957
+ onProcessed: this._onRequestProcessed.bind(this),
2763
2958
  };
2764
2959
  }
2765
2960
  getPreflightProps() {
2766
2961
  return this._getRequestAttrs();
2767
2962
  }
2768
- _preflightPropsForRenderOptions(renderOptions, requestAttributesOptions) {
2769
- const preview = new up.Change.FromContent({ ...renderOptions, preview: true });
2770
- return preview.getPreflightProps(requestAttributesOptions);
2963
+ _preflightPropsForRenderOptions(renderOptions, getPreflightPropsOptions) {
2964
+ const preflightChange = new up.Change.FromContent({ ...renderOptions, preflight: true });
2965
+ return preflightChange.getPreflightProps(getPreflightPropsOptions);
2771
2966
  }
2772
2967
  _onRequestSettled(response) {
2773
2968
  if (response instanceof up.Response) {
@@ -2801,7 +2996,7 @@ up.Change.FromURL = (_a = class FromURL extends up.Change {
2801
2996
 
2802
2997
 
2803
2998
  /***/ }),
2804
- /* 33 */
2999
+ /* 32 */
2805
3000
  /***/ (() => {
2806
3001
 
2807
3002
  var _a;
@@ -2862,17 +3057,17 @@ up.Change.FromResponse = (_a = class FromResponse extends up.Change {
2862
3057
  up.puts('up.render()', 'Revalidating cached response for target "%s"', effectiveTarget);
2863
3058
  let verifyResult = await up.reload(effectiveTarget, {
2864
3059
  ...originalRenderOptions,
3060
+ ...up.RenderOptions.NO_MOTION,
3061
+ ...up.RenderOptions.NO_INPUT_INTERFERENCE,
3062
+ ...up.RenderOptions.NO_PREVIEWS,
2865
3063
  preferOldElements: renderResult.fragments,
2866
3064
  layer: renderResult.layer,
2867
3065
  onFinished: null,
2868
- scroll: false,
2869
- focus: 'keep',
2870
- transition: false,
2871
- cache: false,
2872
- confirm: false,
2873
- feedback: false,
2874
- abort: false,
2875
3066
  expiredResponse: this._response,
3067
+ preview: this._revalidatePreview(originalRenderOptions),
3068
+ abort: false,
3069
+ cache: false,
3070
+ background: true,
2876
3071
  });
2877
3072
  if (!verifyResult.none) {
2878
3073
  renderResult = verifyResult;
@@ -2880,6 +3075,14 @@ up.Change.FromResponse = (_a = class FromResponse extends up.Change {
2880
3075
  }
2881
3076
  return renderResult;
2882
3077
  }
3078
+ _revalidatePreview({ preview, revalidatePreview }) {
3079
+ if (revalidatePreview === true) {
3080
+ return preview;
3081
+ }
3082
+ else {
3083
+ return revalidatePreview;
3084
+ }
3085
+ }
2883
3086
  _loadedEventProps() {
2884
3087
  const { expiredResponse } = this.options;
2885
3088
  return {
@@ -2939,7 +3142,7 @@ up.Change.FromResponse = (_a = class FromResponse extends up.Change {
2939
3142
 
2940
3143
 
2941
3144
  /***/ }),
2942
- /* 34 */
3145
+ /* 33 */
2943
3146
  /***/ (() => {
2944
3147
 
2945
3148
  var _a;
@@ -2948,7 +3151,7 @@ up.Change.FromContent = (_a = class FromContent extends up.Change {
2948
3151
  constructor(options) {
2949
3152
  super(options);
2950
3153
  this._origin = options.origin;
2951
- this._preview = options.preview;
3154
+ this._preflight = options.preflight;
2952
3155
  this._layers = up.layer.getAll(options);
2953
3156
  }
2954
3157
  _getPlans() {
@@ -3003,7 +3206,7 @@ up.Change.FromContent = (_a = class FromContent extends up.Change {
3003
3206
  this.options.onRender?.();
3004
3207
  }
3005
3208
  _getResponseDoc() {
3006
- if (this._preview)
3209
+ if (this._preflight)
3007
3210
  return;
3008
3211
  const docOptions = u.pick(this.options, [
3009
3212
  'target',
@@ -3013,6 +3216,7 @@ up.Change.FromContent = (_a = class FromContent extends up.Change {
3013
3216
  'html',
3014
3217
  'cspNonces',
3015
3218
  'origin',
3219
+ 'data',
3016
3220
  ]);
3017
3221
  up.migrate.handleResponseDocOptions?.(docOptions);
3018
3222
  if (this._defaultPlacement() === 'content') {
@@ -3021,7 +3225,7 @@ up.Change.FromContent = (_a = class FromContent extends up.Change {
3021
3225
  return new up.ResponseDoc(docOptions);
3022
3226
  }
3023
3227
  _improveOptionsFromResponseDoc() {
3024
- if (this._preview)
3228
+ if (this._preflight)
3025
3229
  return;
3026
3230
  let responseDoc = this._getResponseDoc();
3027
3231
  if (this.options.fragment) {
@@ -3093,17 +3297,18 @@ up.Change.FromContent = (_a = class FromContent extends up.Change {
3093
3297
 
3094
3298
 
3095
3299
  /***/ }),
3096
- /* 35 */
3300
+ /* 34 */
3097
3301
  /***/ (() => {
3098
3302
 
3099
3303
  const u = up.util;
3100
3304
  up.CompilerPass = class CompilerPass {
3101
- constructor(root, compilers, { layer, data, dataMap, meta }) {
3305
+ constructor(root, compilers, { layer, data, dataRoot, dataMap, meta }) {
3102
3306
  layer ||= up.layer.get(root) || up.layer.current;
3103
3307
  this._root = root;
3104
3308
  this._compilers = compilers;
3105
3309
  this._layer = layer;
3106
3310
  this._data = data;
3311
+ this._dataRoot = dataRoot || root;
3107
3312
  this._dataMap = dataMap;
3108
3313
  meta ||= {};
3109
3314
  meta.layer = layer;
@@ -3119,7 +3324,7 @@ up.CompilerPass = class CompilerPass {
3119
3324
  }
3120
3325
  setCompileData() {
3121
3326
  if (this._data) {
3122
- this._root.upCompileData = this._data;
3327
+ this._dataRoot.upCompileData = this._data;
3123
3328
  }
3124
3329
  if (this._dataMap) {
3125
3330
  for (let selector in this._dataMap) {
@@ -3154,10 +3359,7 @@ up.CompilerPass = class CompilerPass {
3154
3359
  compileArgs.push(data, this._meta);
3155
3360
  }
3156
3361
  const result = this._applyCompilerFunction(compiler, element, compileArgs);
3157
- let destructorOrDestructors = this._destructorPresence(result);
3158
- if (destructorOrDestructors) {
3159
- up.destructor(element, destructorOrDestructors);
3160
- }
3362
+ up.destructor(element, result);
3161
3363
  }
3162
3364
  _compileBatch(compiler, elements) {
3163
3365
  const compileArgs = [elements];
@@ -3166,18 +3368,13 @@ up.CompilerPass = class CompilerPass {
3166
3368
  compileArgs.push(dataList, this._meta);
3167
3369
  }
3168
3370
  const result = this._applyCompilerFunction(compiler, elements, compileArgs);
3169
- if (this._destructorPresence(result)) {
3371
+ if (result) {
3170
3372
  up.fail('Compilers with { batch: true } cannot return destructors');
3171
3373
  }
3172
3374
  }
3173
3375
  _applyCompilerFunction(compiler, elementOrElements, compileArgs) {
3174
3376
  return up.error.guard(() => compiler.apply(elementOrElements, compileArgs));
3175
3377
  }
3176
- _destructorPresence(result) {
3177
- if (u.isFunction(result) || (u.isArray(result) && (u.every(result, u.isFunction)))) {
3178
- return result;
3179
- }
3180
- }
3181
3378
  _select(selector) {
3182
3379
  return up.fragment.subtree(this._root, u.evalOption(selector), { layer: this._layer });
3183
3380
  }
@@ -3195,7 +3392,7 @@ up.CompilerPass = class CompilerPass {
3195
3392
 
3196
3393
 
3197
3394
  /***/ }),
3198
- /* 36 */
3395
+ /* 35 */
3199
3396
  /***/ (() => {
3200
3397
 
3201
3398
  const u = up.util;
@@ -3279,7 +3476,7 @@ up.CSSTransition = class CSSTransition {
3279
3476
  if (oldTransition['transition-property'] !== 'all') {
3280
3477
  const oldTransitionProperties = oldTransition['transition-property'].split(/\s*,\s*/);
3281
3478
  const oldTransitionFrame = e.style(this._element, oldTransitionProperties);
3282
- this._setOldTransitionTargetFrame = e.setTemporaryStyle(this._element, oldTransitionFrame);
3479
+ this._setOldTransitionTargetFrame = e.setStyleTemp(this._element, oldTransitionFrame);
3283
3480
  }
3284
3481
  this._setOldTransition = e.concludeCSSTransition(this._element);
3285
3482
  }
@@ -3300,7 +3497,7 @@ up.CSSTransition = class CSSTransition {
3300
3497
 
3301
3498
 
3302
3499
  /***/ }),
3303
- /* 37 */
3500
+ /* 36 */
3304
3501
  /***/ (() => {
3305
3502
 
3306
3503
  const u = up.util;
@@ -3311,27 +3508,19 @@ up.DestructorPass = class DestructorPass {
3311
3508
  }
3312
3509
  run() {
3313
3510
  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');
3511
+ let registry = u.pluckKey(cleanable, 'upDestructors');
3512
+ registry?.clean(cleanable);
3321
3513
  }
3322
3514
  }
3323
3515
  _selectCleanables() {
3324
3516
  const selectOptions = { ...this._options, destroying: true };
3325
3517
  return up.fragment.subtree(this._fragment, '.up-can-clean', selectOptions);
3326
3518
  }
3327
- _applyDestructorFunction(destructor, element) {
3328
- up.error.guard(() => destructor(element));
3329
- }
3330
3519
  };
3331
3520
 
3332
3521
 
3333
3522
  /***/ }),
3334
- /* 38 */
3523
+ /* 37 */
3335
3524
  /***/ (() => {
3336
3525
 
3337
3526
  const u = up.util;
@@ -3393,7 +3582,7 @@ up.EventEmitter = class EventEmitter extends up.Record {
3393
3582
  static fromEmitArgs(args, defaults = {}) {
3394
3583
  let options = u.extractOptions(args);
3395
3584
  options = u.merge(defaults, options);
3396
- if (u.isElementish(args[0])) {
3585
+ if (u.isElementLike(args[0])) {
3397
3586
  options.target = e.get(args.shift());
3398
3587
  }
3399
3588
  else if (args[0] instanceof up.Layer) {
@@ -3430,7 +3619,7 @@ up.EventEmitter = class EventEmitter extends up.Record {
3430
3619
 
3431
3620
 
3432
3621
  /***/ }),
3433
- /* 39 */
3622
+ /* 38 */
3434
3623
  /***/ (() => {
3435
3624
 
3436
3625
  const u = up.util;
@@ -3534,7 +3723,7 @@ up.EventListener = class EventListener extends up.Record {
3534
3723
 
3535
3724
 
3536
3725
  /***/ }),
3537
- /* 40 */
3726
+ /* 39 */
3538
3727
  /***/ (() => {
3539
3728
 
3540
3729
  const u = up.util;
@@ -3554,13 +3743,13 @@ up.EventListenerGroup = class EventListenerGroup extends up.Record {
3554
3743
  ];
3555
3744
  }
3556
3745
  bind() {
3557
- const unbindFns = [];
3746
+ const cleaner = u.cleaner();
3558
3747
  this._eachListenerAttributes(function (attrs) {
3559
3748
  const listener = new up.EventListener(attrs);
3560
3749
  listener.bind();
3561
- return unbindFns.push(listener.unbind.bind(listener));
3750
+ return cleaner(listener.unbind.bind(listener));
3562
3751
  });
3563
- return u.sequence(unbindFns);
3752
+ return cleaner.clean;
3564
3753
  }
3565
3754
  _eachListenerAttributes(fn) {
3566
3755
  for (let element of this.elements) {
@@ -3593,7 +3782,7 @@ up.EventListenerGroup = class EventListenerGroup extends up.Record {
3593
3782
  else {
3594
3783
  elements = [document];
3595
3784
  }
3596
- let eventTypes = u.parseTokens(args.shift());
3785
+ let eventTypes = u.getSimpleTokens(args.shift());
3597
3786
  let fixTypes = up.migrate.fixEventTypes;
3598
3787
  if (fixTypes) {
3599
3788
  eventTypes = fixTypes(eventTypes);
@@ -3607,7 +3796,7 @@ up.EventListenerGroup = class EventListenerGroup extends up.Record {
3607
3796
 
3608
3797
 
3609
3798
  /***/ }),
3610
- /* 41 */
3799
+ /* 40 */
3611
3800
  /***/ (() => {
3612
3801
 
3613
3802
  const u = up.util;
@@ -3618,26 +3807,24 @@ up.FieldWatcher = class FieldWatcher {
3618
3807
  this._scope = up.form.getScope(root);
3619
3808
  this._callback = callback;
3620
3809
  this._batch = options.batch;
3621
- this._abortable = options.abortable;
3622
3810
  }
3623
3811
  start() {
3624
3812
  this._scheduledValues = null;
3625
3813
  this._processedValues = this._readFieldValues();
3626
3814
  this._currentTimer = null;
3627
3815
  this._callbackRunning = false;
3628
- this._unbindFns = [];
3816
+ this._cleaner = u.cleaner();
3629
3817
  this._watchFieldsWithin(this._root);
3630
3818
  this._root.addEventListener('up:fragment:inserted', ({ target }) => {
3631
3819
  if (target !== this._root)
3632
3820
  this._watchFieldsWithin(target);
3633
3821
  });
3634
- this._unbindFns.push(up.fragment.onAborted(this._scope, () => this._abort()));
3635
- this._unbindFns.push(up.on(this._scope, 'reset', () => this._onFormReset()));
3822
+ this._cleaner(up.fragment.onAborted(this._scope, () => this._abort()));
3823
+ this._cleaner(up.on(this._scope, 'reset', () => this._onFormReset()));
3636
3824
  }
3637
3825
  stop() {
3638
3826
  this._abort();
3639
- for (let unbindFn of this._unbindFns)
3640
- unbindFn();
3827
+ this._cleaner.clean();
3641
3828
  }
3642
3829
  _fieldOptions(field) {
3643
3830
  let rootOptions = u.copy(this._options);
@@ -3650,7 +3837,7 @@ up.FieldWatcher = class FieldWatcher {
3650
3837
  }
3651
3838
  _watchField(field) {
3652
3839
  let fieldOptions = this._fieldOptions(field);
3653
- this._unbindFns.push(up.on(field, fieldOptions.event, () => this._check(fieldOptions)));
3840
+ this._cleaner(up.on(field, fieldOptions.event, () => this._check(fieldOptions)));
3654
3841
  }
3655
3842
  _abort() {
3656
3843
  this._scheduledValues = null;
@@ -3677,13 +3864,12 @@ up.FieldWatcher = class FieldWatcher {
3677
3864
  return;
3678
3865
  if (!this._scope.isConnected)
3679
3866
  return;
3680
- let fieldOptions = this._scheduledFieldOptions;
3867
+ let callbackOptions = u.omit(this._scheduledFieldOptions, ['event', 'delay']);
3681
3868
  const diff = this._changedValues(this._processedValues, this._scheduledValues);
3682
3869
  this._processedValues = this._scheduledValues;
3683
3870
  this._scheduledValues = null;
3684
3871
  this._callbackRunning = true;
3685
3872
  this._scheduledFieldOptions = null;
3686
- let callbackOptions = { ...fieldOptions, disable: false };
3687
3873
  const callbackReturnValues = [];
3688
3874
  if (this._batch) {
3689
3875
  callbackReturnValues.push(this._runCallback(diff, callbackOptions));
@@ -3696,14 +3882,13 @@ up.FieldWatcher = class FieldWatcher {
3696
3882
  }
3697
3883
  if (u.some(callbackReturnValues, u.isPromise)) {
3698
3884
  let callbackDone = Promise.allSettled(callbackReturnValues);
3699
- up.form.disableWhile(callbackDone, fieldOptions);
3700
3885
  await callbackDone;
3701
3886
  }
3702
3887
  this._callbackRunning = false;
3703
3888
  this._requestCallback();
3704
3889
  }
3705
3890
  _runCallback(...args) {
3706
- return up.error.guard(() => this._callback(...args));
3891
+ return up.error.guard(this._callback, ...args);
3707
3892
  }
3708
3893
  _changedValues(previous, next) {
3709
3894
  const changes = {};
@@ -3735,7 +3920,7 @@ up.FieldWatcher = class FieldWatcher {
3735
3920
 
3736
3921
 
3737
3922
  /***/ }),
3738
- /* 42 */
3923
+ /* 41 */
3739
3924
  /***/ (() => {
3740
3925
 
3741
3926
  const u = up.util;
@@ -3854,47 +4039,52 @@ up.FormValidator = class FormValidator {
3854
4039
  return;
3855
4040
  if (this._nextRenderTimer)
3856
4041
  return;
3857
- let dirtySolutions = this._dirtySolutions;
4042
+ let options = this._mergeRenderOptions(this._dirtySolutions);
3858
4043
  this._dirtySolutions = [];
4044
+ this._rendering = true;
4045
+ let renderingPromise = this._nextRenderPromise;
4046
+ this._resetNextRenderPromise();
4047
+ try {
4048
+ renderingPromise.resolve(up.render(options));
4049
+ await renderingPromise;
4050
+ }
4051
+ finally {
4052
+ this._rendering = false;
4053
+ this._renderDirtySolutions();
4054
+ }
4055
+ }
4056
+ _mergeRenderOptions(dirtySolutions) {
3859
4057
  let dirtyOrigins = u.map(dirtySolutions, 'origin');
3860
4058
  let dirtyFields = u.flatMap(dirtyOrigins, up.form.fields);
3861
4059
  let dirtyNames = u.uniq(u.map(dirtyFields, 'name'));
3862
- let dataMap = this._buildDataMap(dirtySolutions);
3863
4060
  let dirtyRenderOptionsList = u.map(dirtySolutions, 'renderOptions');
3864
- let options = u.mergeDefined(...dirtyRenderOptionsList, { dataMap }, up.form.destinationOptions(this._form));
4061
+ let options = u.mergeDefined(...dirtyRenderOptionsList, up.form.destinationOptions(this._form));
3865
4062
  options.target = u.map(dirtySolutions, 'target').join(', ');
3866
- options.feedback = u.some(dirtyRenderOptionsList, 'feedback');
3867
4063
  options.origin = this._form;
3868
4064
  options.focus ??= 'keep';
3869
4065
  options.failOptions = false;
3870
4066
  options.defaultMaybe = true;
3871
4067
  options.params = up.Params.merge(options.params, ...u.map(dirtyRenderOptionsList, 'params'));
3872
- options.headers = u.merge(...u.map(dirtyRenderOptionsList, 'headers'));
4068
+ options.headers = u.merge(options.headers, ...u.map(dirtyRenderOptionsList, 'headers'));
3873
4069
  this._addValidateHeader(options.headers, dirtyNames);
4070
+ options.feedback = u.some(dirtyRenderOptionsList, 'feedback');
4071
+ options.data = undefined;
4072
+ options.dataMap = u.mapObject(dirtySolutions, ({ target, element, renderOptions: { data, keepData } }) => [
4073
+ target,
4074
+ keepData ? up.data(element) : data
4075
+ ]);
4076
+ options.preview = undefined;
4077
+ options.previewMap = u.mapObject(dirtySolutions, ({ target, renderOptions: { preview } }) => [target, preview]);
4078
+ options.placeholder = undefined;
4079
+ options.placeholderMap = u.mapObject(dirtySolutions, ({ target, renderOptions: { placeholder } }) => [target, placeholder]);
4080
+ options.disable = dirtySolutions.map((solution) => up.fragment.resolveOrigin(solution.renderOptions.disable, solution));
3874
4081
  options.guardEvent = up.event.build('up:form:validate', {
3875
4082
  fields: dirtyFields,
3876
4083
  log: 'Validating form',
3877
4084
  params: options.params,
3878
4085
  form: this._form,
3879
4086
  });
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
- }
4087
+ return options;
3898
4088
  }
3899
4089
  _addValidateHeader(headers, names) {
3900
4090
  let key = up.protocol.headerize('validate');
@@ -3903,20 +4093,6 @@ up.FormValidator = class FormValidator {
3903
4093
  value = ':unknown';
3904
4094
  headers[key] = value;
3905
4095
  }
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
4096
  static forElement(element) {
3921
4097
  let form = up.form.get(element);
3922
4098
  return form.upFormValidator ||= new this(form);
@@ -3925,19 +4101,23 @@ up.FormValidator = class FormValidator {
3925
4101
 
3926
4102
 
3927
4103
  /***/ }),
3928
- /* 43 */
4104
+ /* 42 */
3929
4105
  /***/ (() => {
3930
4106
 
3931
4107
  up.FocusCapsule = class FocusCapsule {
3932
- constructor(target, cursorProps) {
4108
+ constructor(element, target, cursorProps) {
4109
+ this._element = element;
3933
4110
  this._target = target;
3934
4111
  this._cursorProps = cursorProps;
3935
4112
  }
3936
- restore(layer, options) {
4113
+ wasLost() {
4114
+ return document.activeElement !== this._element;
4115
+ }
4116
+ restore(layer, focusOptions) {
3937
4117
  let rediscoveredElement = up.fragment.get(this._target, { layer });
3938
4118
  if (rediscoveredElement) {
3939
4119
  up.viewport.copyCursorProps(this._cursorProps, rediscoveredElement);
3940
- up.focus(rediscoveredElement, options);
4120
+ up.focus(rediscoveredElement, focusOptions);
3941
4121
  return true;
3942
4122
  }
3943
4123
  }
@@ -3949,13 +4129,13 @@ up.FocusCapsule = class FocusCapsule {
3949
4129
  if (!target)
3950
4130
  return;
3951
4131
  const cursorProps = up.viewport.copyCursorProps(focusedElement);
3952
- return new this(target, cursorProps);
4132
+ return new this(focusedElement, target, cursorProps);
3953
4133
  }
3954
4134
  };
3955
4135
 
3956
4136
 
3957
4137
  /***/ }),
3958
- /* 44 */
4138
+ /* 43 */
3959
4139
  /***/ (() => {
3960
4140
 
3961
4141
  const u = up.util;
@@ -3973,14 +4153,14 @@ up.FragmentProcessor = class FragmentProcessor extends up.Record {
3973
4153
  return this.tryProcess(preprocessed);
3974
4154
  }
3975
4155
  preprocess(opt) {
3976
- return u.parseTokens(opt, { separator: 'or' });
4156
+ return u.getComplexTokens(opt);
3977
4157
  }
3978
4158
  tryProcess(opt) {
3979
4159
  if (u.isArray(opt)) {
3980
4160
  return this.processArray(opt);
3981
4161
  }
3982
4162
  if (u.isFunction(opt)) {
3983
- let result = up.error.guard(() => opt(this.fragment, this.attributes()));
4163
+ let result = up.error.guard(opt, this.fragment, this.attributes());
3984
4164
  return this.tryProcess(result);
3985
4165
  }
3986
4166
  if (u.isElement(opt)) {
@@ -4020,7 +4200,7 @@ up.FragmentProcessor = class FragmentProcessor extends up.Record {
4020
4200
 
4021
4201
 
4022
4202
  /***/ }),
4023
- /* 45 */
4203
+ /* 44 */
4024
4204
  /***/ (() => {
4025
4205
 
4026
4206
  const u = up.util;
@@ -4057,19 +4237,19 @@ up.FragmentFinder = class FragmentFinder {
4057
4237
  if (parts) {
4058
4238
  let parent = up.fragment.closest(this._origin, parts[1], this._options);
4059
4239
  if (parent) {
4060
- return up.fragment.getDumb(parent, parts[2]);
4240
+ return up.fragment.getFirstDescendant(parent, parts[2]);
4061
4241
  }
4062
4242
  }
4063
4243
  });
4064
4244
  }
4065
4245
  _findFirst() {
4066
- return up.fragment.getDumb(this._document, this._selector, this._options);
4246
+ return up.fragment.getFirstDescendant(this._document, this._selector, this._options);
4067
4247
  }
4068
4248
  };
4069
4249
 
4070
4250
 
4071
4251
  /***/ }),
4072
- /* 46 */
4252
+ /* 45 */
4073
4253
  /***/ (() => {
4074
4254
 
4075
4255
  const u = up.util;
@@ -4130,7 +4310,7 @@ up.FragmentFocus = class FragmentFocus extends up.FragmentProcessor {
4130
4310
  return up.viewport.restoreFocus({ layer: this.layer });
4131
4311
  }
4132
4312
  _autofocus() {
4133
- let autofocusElement = this.fragment && e.subtree(this.fragment, '[autofocus]')[0];
4313
+ let autofocusElement = this.fragment && e.subtreeFirst(this.fragment, '[autofocus]');
4134
4314
  if (autofocusElement) {
4135
4315
  return this._focusElement(autofocusElement);
4136
4316
  }
@@ -4148,13 +4328,13 @@ up.FragmentFocus = class FragmentFocus extends up.FragmentProcessor {
4148
4328
  }
4149
4329
  }
4150
4330
  _wasFocusLost() {
4151
- return !this.layer.hasFocus();
4331
+ return this.focusCapsule?.wasLost();
4152
4332
  }
4153
4333
  };
4154
4334
 
4155
4335
 
4156
4336
  /***/ }),
4157
- /* 47 */
4337
+ /* 46 */
4158
4338
  /***/ (() => {
4159
4339
 
4160
4340
  const e = up.element;
@@ -4223,17 +4403,17 @@ up.FragmentPolling = class FragmentPolling {
4223
4403
  (this._options.ifLayer === 'any' || this._isOnFrontLayer());
4224
4404
  }
4225
4405
  _clearReloadTimer() {
4226
- clearTimeout(this.reloadTimer);
4227
- this.reloadTimer = null;
4406
+ clearTimeout(this._reloadTimer);
4407
+ this._reloadTimer = null;
4228
4408
  }
4229
4409
  _scheduleRemainingTime() {
4230
- if (!this.reloadTimer && !this._loading) {
4410
+ if (!this._reloadTimer && !this._loading) {
4231
4411
  this._clearReloadTimer();
4232
- this.reloadTimer = setTimeout(this._onTimerReached.bind(this), this._getRemainingDelay());
4412
+ this._reloadTimer = setTimeout(this._onTimerReached.bind(this), this._getRemainingDelay());
4233
4413
  }
4234
4414
  }
4235
4415
  _onTimerReached() {
4236
- this.reloadTimer = null;
4416
+ this._reloadTimer = null;
4237
4417
  this._tryReload();
4238
4418
  }
4239
4419
  _tryReload() {
@@ -4309,7 +4489,7 @@ up.FragmentPolling = class FragmentPolling {
4309
4489
 
4310
4490
 
4311
4491
  /***/ }),
4312
- /* 48 */
4492
+ /* 47 */
4313
4493
  /***/ (() => {
4314
4494
 
4315
4495
  const u = up.util;
@@ -4373,7 +4553,7 @@ up.FragmentScrolling = class FragmentScrolling extends up.FragmentProcessor {
4373
4553
 
4374
4554
 
4375
4555
  /***/ }),
4376
- /* 49 */
4556
+ /* 48 */
4377
4557
  /***/ (() => {
4378
4558
 
4379
4559
  const e = up.element;
@@ -4639,285 +4819,294 @@ up.Layer = class Layer extends up.Record {
4639
4819
 
4640
4820
 
4641
4821
  /***/ }),
4642
- /* 50 */
4822
+ /* 49 */
4643
4823
  /***/ (() => {
4644
4824
 
4825
+ var _a;
4645
4826
  const e = up.element;
4646
4827
  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'];
4828
+ up.Layer.Overlay = (_a = class Overlay extends up.Layer {
4829
+ keys() {
4830
+ return [
4831
+ ...super.keys(),
4832
+ ...this.constructor.VISUAL_KEYS,
4833
+ 'onOpened',
4834
+ 'onAccept',
4835
+ 'onAccepted',
4836
+ 'onDismiss',
4837
+ 'onDismissed',
4838
+ 'acceptEvent',
4839
+ 'dismissEvent',
4840
+ 'acceptLocation',
4841
+ 'dismissLocation',
4842
+ 'opening'
4843
+ ];
4844
+ }
4845
+ constructor(options) {
4846
+ super(options);
4847
+ if (this.dismissable === true) {
4848
+ this.dismissable = ['button', 'key', 'outside'];
4849
+ }
4850
+ else if (this.dismissable === false) {
4851
+ this.dismissable = [];
4852
+ }
4853
+ else {
4854
+ this.dismissable = u.getSimpleTokens(this.dismissable);
4855
+ }
4856
+ if (this.acceptLocation) {
4857
+ this.acceptLocation = new up.URLPattern(this.acceptLocation);
4858
+ }
4859
+ if (this.dismissLocation) {
4860
+ this.dismissLocation = new up.URLPattern(this.dismissLocation);
4861
+ }
4684
4862
  }
4685
- else if (this.dismissable === false) {
4686
- this.dismissable = [];
4863
+ callback(name) {
4864
+ let fn = this[name];
4865
+ if (fn) {
4866
+ return fn.bind(this);
4867
+ }
4687
4868
  }
4688
- else {
4689
- this.dismissable = u.parseTokens(this.dismissable);
4869
+ createElement(parentElement) {
4870
+ this.nesting ||= this._suggestVisualNesting();
4871
+ const elementAttrs = u.compactObject(u.pick(this, ['align', 'position', 'size', 'class', 'nesting']));
4872
+ this.element = this.affixPart(parentElement, null, elementAttrs);
4690
4873
  }
4691
- if (this.acceptLocation) {
4692
- this.acceptLocation = new up.URLPattern(this.acceptLocation);
4874
+ createBackdropElement(parentElement) {
4875
+ this.backdropElement = this.affixPart(parentElement, 'backdrop');
4693
4876
  }
4694
- if (this.dismissLocation) {
4695
- this.dismissLocation = new up.URLPattern(this.dismissLocation);
4877
+ createViewportElement(parentElement) {
4878
+ this.viewportElement = this.affixPart(parentElement, 'viewport', { 'up-viewport': '' });
4696
4879
  }
4697
- }
4698
- callback(name) {
4699
- let fn = this[name];
4700
- if (fn) {
4701
- return fn.bind(this);
4880
+ createBoxElement(parentElement) {
4881
+ this.boxElement = this.affixPart(parentElement, 'box');
4702
4882
  }
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();
4883
+ createContentElement(parentElement) {
4884
+ this.contentElement = this.affixPart(parentElement, 'content');
4744
4885
  }
4745
- else {
4746
- return 0;
4886
+ setContent(content) {
4887
+ this.contentElement.append(content);
4888
+ this.onContentSet();
4747
4889
  }
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
- });
4890
+ onContentSet() {
4891
+ }
4892
+ createDismissElement(parentElement) {
4893
+ this.dismissElement = this.affixPart(parentElement, 'dismiss', {
4894
+ 'up-dismiss': '":button"',
4895
+ 'aria-label': this.dismissARIALabel
4896
+ });
4897
+ return e.affix(this.dismissElement, 'span[aria-hidden="true"]', { text: this.dismissLabel });
4898
+ }
4899
+ affixPart(parentElement, part, options = {}) {
4900
+ return e.affix(parentElement, this.selector(part), options);
4901
+ }
4902
+ static selector(part) {
4903
+ return u.compact(['up', this.mode, part]).join('-');
4904
+ }
4905
+ _suggestVisualNesting() {
4906
+ const { parent } = this;
4907
+ if (this.mode === parent.mode) {
4908
+ return 1 + parent._suggestVisualNesting();
4762
4909
  }
4763
4910
  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
- });
4911
+ return 0;
4912
+ }
4913
+ }
4914
+ setupHandlers() {
4915
+ super.setupHandlers();
4916
+ this.overlayFocus = new up.OverlayFocus(this);
4917
+ if (this._supportsDismissMethod('button')) {
4918
+ this.createDismissElement(this.getBoxElement());
4919
+ }
4920
+ if (this._supportsDismissMethod('outside')) {
4921
+ if (this.viewportElement) {
4922
+ up.on(this.viewportElement, 'up:click', event => {
4923
+ if (event.target === this.viewportElement) {
4924
+ this._onOutsideClicked(event, true);
4925
+ }
4926
+ });
4927
+ }
4928
+ else {
4929
+ this.unbindParentClicked = this.parent.on('up:click', (event, element) => {
4930
+ if (!up.layer.isWithinForeignOverlay(element)) {
4931
+ const originClicked = this.origin && this.origin.contains(element);
4932
+ this._onOutsideClicked(event, originClicked);
4933
+ }
4934
+ });
4935
+ }
4936
+ }
4937
+ if (this._supportsDismissMethod('key')) {
4938
+ this.unbindEscapePressed = up.event.onEscape(event => this.onEscapePressed(event));
4939
+ }
4940
+ this.registerClickCloser('up-accept', (value, closeOptions) => {
4941
+ this.accept(value, closeOptions);
4942
+ });
4943
+ this.registerClickCloser('up-dismiss', (value, closeOptions) => {
4944
+ this.dismiss(value, closeOptions);
4945
+ });
4946
+ up.migrate.registerLayerCloser?.(this);
4947
+ this._registerEventCloser(this.acceptEvent, this.accept);
4948
+ this._registerEventCloser(this.dismissEvent, this.dismiss);
4949
+ this.on('up:click', 'label[for]', (event, label) => this._onLabelClicked(event, label));
4950
+ }
4951
+ _onLabelClicked(event, label) {
4952
+ let id = label.getAttribute('for');
4953
+ let fieldSelector = up.form.fieldSelector(e.idSelector(id));
4954
+ let fieldsAnywhere = up.fragment.all(fieldSelector, { layer: 'any' });
4955
+ let fieldsInLayer = up.fragment.all(fieldSelector, { layer: this });
4956
+ if (fieldsAnywhere.length > 1 && fieldsInLayer[0] !== fieldsAnywhere[0]) {
4957
+ event.preventDefault();
4958
+ const field = fieldsInLayer[0];
4959
+ field.focus();
4960
+ if (field.matches('input[type=checkbox], input[type=radio]')) {
4961
+ field.click();
4962
+ }
4770
4963
  }
4771
4964
  }
4772
- if (this._supportsDismissMethod('key')) {
4773
- this.unbindEscapePressed = up.event.onEscape(event => this.onEscapePressed(event));
4965
+ _onOutsideClicked(event, halt) {
4966
+ up.log.putsEvent(event);
4967
+ if (halt)
4968
+ up.event.halt(event);
4969
+ up.error.muteUncriticalSync(() => this.dismiss(':outside', { origin: event.target }));
4774
4970
  }
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();
4971
+ onEscapePressed(event) {
4972
+ if (this.isFront()) {
4973
+ let field = up.form.focusedField();
4974
+ if (field) {
4975
+ field.blur();
4976
+ }
4977
+ else if (this._supportsDismissMethod('key')) {
4978
+ up.event.halt(event, { log: true });
4979
+ up.error.muteUncriticalSync(() => this.dismiss(':key'));
4980
+ }
4811
4981
  }
4812
- else if (this._supportsDismissMethod('key')) {
4982
+ }
4983
+ registerClickCloser(attribute, closeFn) {
4984
+ let selector = `[${attribute}]`;
4985
+ this.on('up:click', selector, function (event) {
4813
4986
  up.event.halt(event, { log: true });
4814
- up.error.muteUncriticalSync(() => this.dismiss(':key'));
4987
+ const origin = event.target.closest(selector);
4988
+ const value = e.jsonAttr(origin, attribute);
4989
+ const closeOptions = { origin };
4990
+ const parser = new up.OptionsParser(origin, closeOptions);
4991
+ parser.booleanOrString('animation');
4992
+ parser.string('easing');
4993
+ parser.number('duration');
4994
+ parser.string('confirm');
4995
+ up.error.muteUncriticalSync(() => closeFn(value, closeOptions));
4996
+ });
4997
+ }
4998
+ _registerEventCloser(eventTypes, closeFn) {
4999
+ if (!eventTypes) {
5000
+ return;
4815
5001
  }
5002
+ return this.on(eventTypes, event => {
5003
+ event.preventDefault();
5004
+ up.error.muteUncriticalSync(() => closeFn.call(this, event, { response: event.response }));
5005
+ });
4816
5006
  }
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;
5007
+ tryAcceptForLocation(options) {
5008
+ this._tryCloseForLocation(this.acceptLocation, this.accept, options);
4836
5009
  }
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));
5010
+ tryDismissForLocation(options) {
5011
+ this._tryCloseForLocation(this.dismissLocation, this.dismiss, options);
4853
5012
  }
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);
5013
+ _tryCloseForLocation(urlPattern, closeFn, options) {
5014
+ let location, resolution;
5015
+ if (urlPattern && (location = this.location) && (resolution = urlPattern.recognize(location))) {
5016
+ const closeValue = { ...resolution, location };
5017
+ up.error.muteUncriticalSync(() => closeFn.call(this, closeValue, options));
5018
+ }
4877
5019
  }
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
- };
5020
+ teardownHandlers() {
5021
+ super.teardownHandlers();
5022
+ this.unbindParentClicked?.();
5023
+ this.unbindEscapePressed?.();
5024
+ this.overlayFocus.teardown();
5025
+ }
5026
+ destroyElements(options) {
5027
+ const animation = () => this.startCloseAnimation(options);
5028
+ const onFinished = () => {
5029
+ this.onElementsRemoved();
5030
+ options.onFinished?.();
5031
+ };
5032
+ const destroyOptions = { ...options, animation, onFinished, log: false };
5033
+ up.destroy(this.element, destroyOptions);
5034
+ }
5035
+ onElementsRemoved() {
5036
+ }
5037
+ _startAnimation(options = {}) {
5038
+ const boxDone = up.animate(this.getBoxElement(), options.boxAnimation, options);
5039
+ let backdropDone;
5040
+ if (this.backdrop && !up.motion.isNone(options.boxAnimation)) {
5041
+ backdropDone = up.animate(this.backdropElement, options.backdropAnimation, options);
5042
+ }
5043
+ return Promise.all([boxDone, backdropDone]);
5044
+ }
5045
+ async startOpenAnimation(options = {}) {
5046
+ let boxAnimation = options.animation ?? this.evalOption(this.openAnimation);
5047
+ let backdropAnimation = 'fade-in';
5048
+ await this._startAnimation({
5049
+ boxAnimation,
5050
+ backdropAnimation,
5051
+ easing: options.easing || this.openEasing,
5052
+ duration: options.duration || this.openDuration
5053
+ });
5054
+ this.wasEverVisible = true;
5055
+ }
5056
+ startCloseAnimation(options = {}) {
5057
+ let boxAnimation = this.wasEverVisible && (options.animation ?? this.evalOption(this.closeAnimation));
5058
+ let backdropAnimation = 'fade-out';
5059
+ return this._startAnimation({
5060
+ boxAnimation,
5061
+ backdropAnimation,
5062
+ easing: options.easing || this.closeEasing,
5063
+ duration: options.duration || this.closeDuration
5064
+ });
5065
+ }
5066
+ accept(value = null, options = {}) {
5067
+ return this._executeCloseChange('accept', value, options);
5068
+ }
5069
+ dismiss(value = null, options = {}) {
5070
+ return this._executeCloseChange('dismiss', value, options);
5071
+ }
5072
+ _supportsDismissMethod(method) {
5073
+ return u.contains(this.dismissable, method);
5074
+ }
5075
+ _executeCloseChange(verb, value, options) {
5076
+ options = { ...options, verb, value, layer: this };
5077
+ return new up.Change.CloseLayer(options).execute();
5078
+ }
5079
+ getFirstSwappableElement() {
5080
+ return this.getContentElement().children[0];
5081
+ }
5082
+ toString() {
5083
+ return `${this.mode} overlay`;
5084
+ }
5085
+ },
5086
+ _a.VISUAL_KEYS = [
5087
+ 'mode',
5088
+ 'position',
5089
+ 'align',
5090
+ 'size',
5091
+ 'origin',
5092
+ 'class',
5093
+ 'backdrop',
5094
+ 'dismissable',
5095
+ 'dismissLabel',
5096
+ 'dismissARIALabel',
5097
+ 'openAnimation',
5098
+ 'closeAnimation',
5099
+ 'openDuration',
5100
+ 'closeDuration',
5101
+ 'openEasing',
5102
+ 'closeEasing',
5103
+ 'trapFocus',
5104
+ ],
5105
+ _a);
4917
5106
 
4918
5107
 
4919
5108
  /***/ }),
4920
- /* 51 */
5109
+ /* 50 */
4921
5110
  /***/ (() => {
4922
5111
 
4923
5112
  up.Layer.OverlayWithTether = class OverlayWithTether extends up.Layer.Overlay {
@@ -4956,7 +5145,7 @@ up.Layer.OverlayWithTether = class OverlayWithTether extends up.Layer.Overlay {
4956
5145
 
4957
5146
 
4958
5147
  /***/ }),
4959
- /* 52 */
5148
+ /* 51 */
4960
5149
  /***/ (() => {
4961
5150
 
4962
5151
  up.Layer.OverlayWithViewport = class OverlayWithViewport extends up.Layer.Overlay {
@@ -4985,7 +5174,7 @@ up.Layer.OverlayWithViewport = class OverlayWithViewport extends up.Layer.Overla
4985
5174
 
4986
5175
 
4987
5176
  /***/ }),
4988
- /* 53 */
5177
+ /* 52 */
4989
5178
  /***/ (() => {
4990
5179
 
4991
5180
  var _a;
@@ -5031,7 +5220,7 @@ up.Layer.Root = (_a = class Root extends up.Layer {
5031
5220
 
5032
5221
 
5033
5222
  /***/ }),
5034
- /* 54 */
5223
+ /* 53 */
5035
5224
  /***/ (() => {
5036
5225
 
5037
5226
  var _a;
@@ -5042,7 +5231,7 @@ up.Layer.Modal = (_a = class Modal extends up.Layer.OverlayWithViewport {
5042
5231
 
5043
5232
 
5044
5233
  /***/ }),
5045
- /* 55 */
5234
+ /* 54 */
5046
5235
  /***/ (() => {
5047
5236
 
5048
5237
  var _a;
@@ -5053,7 +5242,7 @@ up.Layer.Popup = (_a = class Popup extends up.Layer.OverlayWithTether {
5053
5242
 
5054
5243
 
5055
5244
  /***/ }),
5056
- /* 56 */
5245
+ /* 55 */
5057
5246
  /***/ (() => {
5058
5247
 
5059
5248
  var _a;
@@ -5064,7 +5253,7 @@ up.Layer.Drawer = (_a = class Drawer extends up.Layer.OverlayWithViewport {
5064
5253
 
5065
5254
 
5066
5255
  /***/ }),
5067
- /* 57 */
5256
+ /* 56 */
5068
5257
  /***/ (() => {
5069
5258
 
5070
5259
  var _a;
@@ -5075,7 +5264,7 @@ up.Layer.Cover = (_a = class Cover extends up.Layer.OverlayWithViewport {
5075
5264
 
5076
5265
 
5077
5266
  /***/ }),
5078
- /* 58 */
5267
+ /* 57 */
5079
5268
  /***/ (() => {
5080
5269
 
5081
5270
  var _a;
@@ -5088,7 +5277,7 @@ up.LayerLookup = (_a = class LayerLookup {
5088
5277
  up.layer.normalizeOptions(options);
5089
5278
  }
5090
5279
  this._options = options;
5091
- this._values = u.parseTokens(options.layer);
5280
+ this._values = u.getSimpleTokens(options.layer);
5092
5281
  }
5093
5282
  all() {
5094
5283
  let results = u.flatMap(this._values, value => this._resolveValue(value));
@@ -5121,7 +5310,7 @@ up.LayerLookup = (_a = class LayerLookup {
5121
5310
  if (/^\d+$/.test(value)) {
5122
5311
  return this._forIndex(Number(value));
5123
5312
  }
5124
- if (u.isElementish(value)) {
5313
+ if (u.isElementLike(value)) {
5125
5314
  return this._forElement(value);
5126
5315
  }
5127
5316
  switch (value) {
@@ -5188,7 +5377,7 @@ up.LayerLookup = (_a = class LayerLookup {
5188
5377
 
5189
5378
 
5190
5379
  /***/ }),
5191
- /* 59 */
5380
+ /* 58 */
5192
5381
  /***/ (() => {
5193
5382
 
5194
5383
  const u = up.util;
@@ -5302,11 +5491,11 @@ up.LayerStack = class LayerStack {
5302
5491
 
5303
5492
 
5304
5493
  /***/ }),
5305
- /* 60 */
5494
+ /* 59 */
5306
5495
  /***/ (() => {
5307
5496
 
5308
5497
  const u = up.util;
5309
- up.LinkFeedbackURLs = class LinkFeedbackURLs {
5498
+ up.LinkCurrentURLs = class LinkCurrentURLs {
5310
5499
  constructor(link) {
5311
5500
  this._isSafe = up.link.isSafe(link);
5312
5501
  if (this._isSafe) {
@@ -5336,7 +5525,7 @@ up.LinkFeedbackURLs = class LinkFeedbackURLs {
5336
5525
 
5337
5526
 
5338
5527
  /***/ }),
5339
- /* 61 */
5528
+ /* 60 */
5340
5529
  /***/ (() => {
5341
5530
 
5342
5531
  const u = up.util;
@@ -5380,7 +5569,7 @@ up.LinkFollowIntent = class LinkFollowIntent {
5380
5569
 
5381
5570
 
5382
5571
  /***/ }),
5383
- /* 62 */
5572
+ /* 61 */
5384
5573
  /***/ (() => {
5385
5574
 
5386
5575
  const u = up.util;
@@ -5476,7 +5665,7 @@ up.MotionController = class MotionController {
5476
5665
 
5477
5666
 
5478
5667
  /***/ }),
5479
- /* 63 */
5668
+ /* 62 */
5480
5669
  /***/ (() => {
5481
5670
 
5482
5671
  const u = up.util;
@@ -5491,33 +5680,36 @@ up.NonceableCallback = class NonceableCallback {
5491
5680
  return new this(match[3], match[2]);
5492
5681
  }
5493
5682
  toFunction(...argNames) {
5683
+ let scriptExpression = this.script;
5684
+ if (!/\b(;|return|throw)\b/.test(scriptExpression))
5685
+ scriptExpression = `return ${scriptExpression}`;
5494
5686
  if (this.nonce) {
5495
5687
  let callbackThis = this;
5496
5688
  return function (...args) {
5497
- return callbackThis._runAsNoncedFunction(this, argNames, args);
5689
+ return callbackThis._runAsNoncedFunction(scriptExpression, this, argNames, args);
5498
5690
  };
5499
5691
  }
5500
5692
  else {
5501
- return new Function(...argNames, this.script);
5693
+ return new Function(...argNames, scriptExpression);
5502
5694
  }
5503
5695
  }
5504
5696
  toString() {
5505
5697
  return `nonce-${this.nonce} ${this.script}`;
5506
5698
  }
5507
- _runAsNoncedFunction(thisArg, argNames, args) {
5699
+ _runAsNoncedFunction(script, thisArg, argNames, args) {
5508
5700
  let wrappedScript = `
5509
5701
  try {
5510
5702
  up.noncedEval.value = (function(${argNames.join()}) {
5511
- ${this.script}
5703
+ ${script}
5512
5704
  }).apply(up.noncedEval.thisArg, up.noncedEval.args)
5513
5705
  } catch (error) {
5514
5706
  up.noncedEval.error = error
5515
5707
  }
5516
5708
  `;
5517
- let script;
5709
+ let scriptElement;
5518
5710
  try {
5519
5711
  up.noncedEval = { args, thisArg: thisArg };
5520
- script = up.element.affix(document.body, 'script', { nonce: this.nonce, text: wrappedScript });
5712
+ scriptElement = e.affix(document.body, 'script', { nonce: this.nonce, text: wrappedScript });
5521
5713
  if (up.noncedEval.error) {
5522
5714
  throw up.noncedEval.error;
5523
5715
  }
@@ -5527,8 +5719,8 @@ up.NonceableCallback = class NonceableCallback {
5527
5719
  }
5528
5720
  finally {
5529
5721
  up.noncedEval = undefined;
5530
- if (script) {
5531
- script.remove();
5722
+ if (scriptElement) {
5723
+ scriptElement.remove();
5532
5724
  }
5533
5725
  }
5534
5726
  }
@@ -5562,7 +5754,7 @@ up.NonceableCallback = class NonceableCallback {
5562
5754
 
5563
5755
 
5564
5756
  /***/ }),
5565
- /* 64 */
5757
+ /* 63 */
5566
5758
  /***/ (() => {
5567
5759
 
5568
5760
  const e = up.element;
@@ -5578,7 +5770,7 @@ up.OverlayFocus = class OverlayFocus {
5578
5770
  return;
5579
5771
  }
5580
5772
  this._active = true;
5581
- this._unsetAttrs = e.setTemporaryAttrs(this._focusElement, {
5773
+ this._unsetAttrs = e.setAttrsTemp(this._focusElement, {
5582
5774
  'tabindex': '0',
5583
5775
  'role': 'dialog',
5584
5776
  'aria-modal': this._trapFocus.toString()
@@ -5635,7 +5827,7 @@ up.OverlayFocus = class OverlayFocus {
5635
5827
 
5636
5828
 
5637
5829
  /***/ }),
5638
- /* 65 */
5830
+ /* 64 */
5639
5831
  /***/ (() => {
5640
5832
 
5641
5833
  const u = up.util;
@@ -5868,6 +6060,140 @@ up.Params = class Params {
5868
6060
  };
5869
6061
 
5870
6062
 
6063
+ /***/ }),
6064
+ /* 65 */
6065
+ /***/ (() => {
6066
+
6067
+ const u = up.util;
6068
+ const e = up.element;
6069
+ up.Preview = class Preview {
6070
+ constructor({ fragment, request, renderOptions, cleaner }) {
6071
+ this.fragment = fragment;
6072
+ this.request = request;
6073
+ this.renderOptions = renderOptions;
6074
+ this._cleaner = cleaner;
6075
+ }
6076
+ undo(...args) {
6077
+ if (this.ended) {
6078
+ reportError(new up.Error('Preview used after end of request'));
6079
+ }
6080
+ else {
6081
+ this._cleaner.guard(...args);
6082
+ }
6083
+ }
6084
+ get origin() {
6085
+ return this.request.origin;
6086
+ }
6087
+ get params() {
6088
+ return this.request.params;
6089
+ }
6090
+ get layer() {
6091
+ return this.request.layer;
6092
+ }
6093
+ get ended() {
6094
+ return this.request.ended;
6095
+ }
6096
+ get expiredResponse() {
6097
+ return this.renderOptions.expiredResponse;
6098
+ }
6099
+ get revalidating() {
6100
+ return !!this.expiredResponse;
6101
+ }
6102
+ run(value, options = {}) {
6103
+ for (let fn of up.status.resolvePreviewFns(value)) {
6104
+ this.undo(up.error.guard(fn, this, options));
6105
+ }
6106
+ }
6107
+ revert() {
6108
+ this._cleaner.clean();
6109
+ }
6110
+ setAttrs(...args) {
6111
+ let [element, attrs] = this._parseMutatorArgs(args, 'val', 'val');
6112
+ this.undo(e.setAttrsTemp(element, attrs));
6113
+ }
6114
+ addClass(...args) {
6115
+ let [element, klass] = this._parseMutatorArgs(args, 'val', 'val');
6116
+ this.undo(e.addClassTemp(element, klass));
6117
+ }
6118
+ addClassBatch(elements, classes) {
6119
+ for (let element of elements) {
6120
+ for (let klass of classes) {
6121
+ this.addClass(element, klass);
6122
+ }
6123
+ }
6124
+ }
6125
+ removeClass(...args) {
6126
+ let [element, klass] = this._parseMutatorArgs(args, 'val', 'val');
6127
+ this.undo(e.removeClassTemp(element, klass));
6128
+ }
6129
+ setStyle(...args) {
6130
+ let [element, styles] = this._parseMutatorArgs(args, 'val', 'val');
6131
+ this.undo(e.setStyleTemp(element, styles));
6132
+ }
6133
+ disable(...args) {
6134
+ let [element] = this._parseMutatorArgs(args, 'val');
6135
+ this.undo(up.form.disable(element));
6136
+ }
6137
+ insert(...args) {
6138
+ let [reference, position = 'beforeend', tempValue] = this._parseMutatorArgs(args, 'val', u.isAdjacentPosition, 'val');
6139
+ this.undo(up.fragment.insertTemp(reference, position, tempValue));
6140
+ }
6141
+ show(...args) {
6142
+ let [element] = this._parseMutatorArgs(args, 'val');
6143
+ this.undo(e.showTemp(element));
6144
+ }
6145
+ hide(...args) {
6146
+ let [element] = this._parseMutatorArgs(args, 'val');
6147
+ this.undo(e.hideTemp(element));
6148
+ }
6149
+ hideContent(...args) {
6150
+ let [parent] = this._parseMutatorArgs(args, 'val');
6151
+ let wrapper = e.wrapChildren(parent);
6152
+ e.hide(wrapper);
6153
+ this.undo(() => e.unwrap(wrapper));
6154
+ }
6155
+ showPlaceholder(...args) {
6156
+ let [parent, placeholderReference] = this._parseMutatorArgs(args, 'val', 'val');
6157
+ let placeholderNodes = up.fragment.provideNodes(placeholderReference, { origin: this.origin });
6158
+ up.puts('[up-placeholder]', 'Showing placeholder %o', placeholderReference);
6159
+ if (parent) {
6160
+ this.swapContent(parent, placeholderNodes);
6161
+ }
6162
+ else if (this.layer === 'new') {
6163
+ this.openLayer(placeholderNodes, { closeAnimation: false });
6164
+ this.renderOptions.openAnimation = false;
6165
+ }
6166
+ }
6167
+ swapContent(...args) {
6168
+ let [parent, newContent] = this._parseMutatorArgs(args, 'val', 'val');
6169
+ this.hideContent(parent);
6170
+ this.insert(parent, newContent);
6171
+ }
6172
+ openLayer(content, options = {}) {
6173
+ let undoDismissValue = ':undo-preview';
6174
+ let onDismiss = ({ value }) => {
6175
+ if (value !== undoDismissValue)
6176
+ this.request.abort({ reason: 'Preview overlay dismissed' });
6177
+ };
6178
+ up.layer.open({
6179
+ ...u.pick(this.renderOptions, [...up.Layer.Overlay.VISUAL_KEYS, 'target']),
6180
+ ...options,
6181
+ content,
6182
+ abort: false,
6183
+ onDismiss
6184
+ });
6185
+ let overlay = up.layer.front;
6186
+ this.undo(() => overlay.dismiss(undoDismissValue, { preventable: false }));
6187
+ return overlay;
6188
+ }
6189
+ _parseMutatorArgs(args, ...specs) {
6190
+ let [element, ...rest] = u.args(args, ...specs);
6191
+ element = up.fragment.get(element, { layer: this.layer, origin: this.origin }) || this.fragment;
6192
+ return [element, ...rest];
6193
+ }
6194
+ };
6195
+
6196
+
5871
6197
  /***/ }),
5872
6198
  /* 66 */
5873
6199
  /***/ (() => {
@@ -5880,7 +6206,7 @@ up.ProgressBar = class ProgressBar {
5880
6206
  this._element = e.affix(document.body, 'up-progress-bar');
5881
6207
  this._element.style.transition = `width ${TRANSITION_DELAY}ms ease-out`;
5882
6208
  this._moveTo(0);
5883
- up.element.paint(this._element);
6209
+ e.paint(this._element);
5884
6210
  this._width = 31;
5885
6211
  this._nextStep();
5886
6212
  }
@@ -5924,21 +6250,22 @@ up.ProgressBar = class ProgressBar {
5924
6250
 
5925
6251
  const u = up.util;
5926
6252
  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,
6253
+ const NO_PREVIEWS = {
6254
+ preview: false,
6255
+ disable: false,
6256
+ placeholder: false,
6257
+ feedback: false,
5935
6258
  };
5936
- const PRELOAD_OVERRIDES = {
5937
- abort: false,
6259
+ const NO_INPUT_INTERFERENCE = {
6260
+ scroll: false,
6261
+ focus: 'keep',
5938
6262
  confirm: false,
5939
- feedback: false,
5940
- cache: true,
5941
- background: true,
6263
+ };
6264
+ const NO_MOTION = {
6265
+ transition: false,
6266
+ animation: false,
6267
+ openAnimation: false,
6268
+ closeAnimation: false,
5942
6269
  };
5943
6270
  const PREFLIGHT_KEYS = [
5944
6271
  'url',
@@ -5952,9 +6279,13 @@ up.RenderOptions = (function () {
5952
6279
  'abortable',
5953
6280
  'confirm',
5954
6281
  'feedback',
6282
+ 'disable',
6283
+ 'placeholder',
6284
+ 'preview',
5955
6285
  'origin',
5956
6286
  'originLayer',
5957
6287
  'baseLayer',
6288
+ 'navigate',
5958
6289
  'fail',
5959
6290
  'onError',
5960
6291
  ];
@@ -5964,8 +6295,6 @@ up.RenderOptions = (function () {
5964
6295
  'history',
5965
6296
  'source',
5966
6297
  'saveScroll',
5967
- 'navigate',
5968
- 'baseLayer',
5969
6298
  ]);
5970
6299
  const CONTENT_KEYS = [
5971
6300
  'url',
@@ -5989,15 +6318,17 @@ up.RenderOptions = (function () {
5989
6318
  return { url: u.normalizeURL(url) };
5990
6319
  }
5991
6320
  }
5992
- function preloadOverrides(options) {
5993
- if (options.preload) {
5994
- return PRELOAD_OVERRIDES;
5995
- }
6321
+ function removeUsePrefix(options) {
6322
+ u.renameKey(options, 'useData', 'data');
6323
+ u.renameKey(options, 'useHungry', 'hungry');
6324
+ u.renameKey(options, 'useKeep', 'keep');
5996
6325
  }
5997
6326
  function preprocess(options) {
5998
6327
  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));
6328
+ up.layer.normalizeOptions(options);
6329
+ removeUsePrefix(options);
6330
+ const defaults = u.merge(up.fragment.config.renderOptions, navigateDefaults(options));
6331
+ return u.merge(u.omit(defaults, LATE_KEYS), { defaults }, { inputDevice: up.event.inputDevice }, options, normalizeURL(options), rememberOriginLayer(options));
6001
6332
  }
6002
6333
  function rememberOriginLayer({ origin, originLayer }) {
6003
6334
  if (origin && !originLayer) {
@@ -6032,13 +6363,11 @@ up.RenderOptions = (function () {
6032
6363
  }
6033
6364
  function deriveFailOptions(preprocessedOptions) {
6034
6365
  let overrides = failOverrides(preprocessedOptions);
6035
- let layers = rememberOriginLayer(overrides);
6036
6366
  if (preprocessedOptions.failOptions) {
6037
6367
  return {
6038
6368
  ...preprocessedOptions.defaults,
6039
6369
  ...u.pick(preprocessedOptions, SHARED_KEYS),
6040
6370
  ...overrides,
6041
- ...layers,
6042
6371
  ...{ failPrefixForced: true }
6043
6372
  };
6044
6373
  }
@@ -6046,7 +6375,6 @@ up.RenderOptions = (function () {
6046
6375
  return {
6047
6376
  ...preprocessedOptions,
6048
6377
  ...overrides,
6049
- ...layers,
6050
6378
  };
6051
6379
  }
6052
6380
  }
@@ -6055,6 +6383,9 @@ up.RenderOptions = (function () {
6055
6383
  finalize,
6056
6384
  assertContentGiven,
6057
6385
  deriveFailOptions,
6386
+ NO_PREVIEWS,
6387
+ NO_MOTION,
6388
+ NO_INPUT_INTERFERENCE,
6058
6389
  };
6059
6390
  })();
6060
6391
 
@@ -6135,7 +6466,6 @@ up.Request = (_a = class Request extends up.Record {
6135
6466
  'failMode',
6136
6467
  'failContext',
6137
6468
  'origin',
6138
- 'fragments',
6139
6469
  'builtAt',
6140
6470
  'wrapMethod',
6141
6471
  'contentType',
@@ -6143,7 +6473,8 @@ up.Request = (_a = class Request extends up.Record {
6143
6473
  'onLoading',
6144
6474
  'fail',
6145
6475
  'abortable',
6146
- 'badResponseTime',
6476
+ 'lateDelay',
6477
+ 'previews',
6147
6478
  ];
6148
6479
  }
6149
6480
  defaults() {
@@ -6153,6 +6484,7 @@ up.Request = (_a = class Request extends up.Record {
6153
6484
  headers: {},
6154
6485
  timeout: up.network.config.timeout,
6155
6486
  builtAt: new Date(),
6487
+ previews: [],
6156
6488
  };
6157
6489
  }
6158
6490
  constructor(options) {
@@ -6171,26 +6503,37 @@ up.Request = (_a = class Request extends up.Record {
6171
6503
  this.mode ||= this.layer.mode;
6172
6504
  this.failMode ||= this.failLayer?.mode;
6173
6505
  }
6174
- this.deferred = u.newDeferred();
6175
- this.badResponseTime ??= u.evalOption(up.network.config.badResponseTime, this);
6506
+ this.bindLayer = options.bindLayer || this.layer;
6507
+ this._fragments = options.fragments;
6508
+ this._bindFragments = options.bindFragments;
6509
+ this._deferred = u.newDeferred();
6176
6510
  this._setAutoHeaders();
6177
6511
  }
6512
+ get effectiveLateTime() {
6513
+ if (this.background) {
6514
+ return false;
6515
+ }
6516
+ else {
6517
+ return this.lateDelay ?? u.evalOption(up.network.config.lateDelay, this);
6518
+ }
6519
+ }
6520
+ isTimed() {
6521
+ return u.isNumber(this.effectiveLateTime);
6522
+ }
6178
6523
  get xhr() {
6179
6524
  return this._xhr ??= new XMLHttpRequest();
6180
6525
  }
6181
6526
  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
- }
6527
+ return (this._fragments ||= this._findFragments());
6191
6528
  }
6192
- set fragments(value) {
6193
- this._fragments = value;
6529
+ _findFragments() {
6530
+ let steps = up.fragment.parseTargetSteps(this.target);
6531
+ let lookupOpts = { origin: this.origin, layer: this.layer };
6532
+ let matches = u.map(steps, (step) => up.fragment.get(step.selector, lookupOpts));
6533
+ return u.compact(matches);
6534
+ }
6535
+ get bindFragments() {
6536
+ return this._bindFragments || this.fragments;
6194
6537
  }
6195
6538
  get fragment() {
6196
6539
  return this.fragments?.[0];
@@ -6205,8 +6548,10 @@ up.Request = (_a = class Request extends up.Record {
6205
6548
  u.task(() => {
6206
6549
  this.layer = undefined;
6207
6550
  this.failLayer = undefined;
6551
+ this._bindLayer = undefined;
6208
6552
  this.origin = undefined;
6209
- this.fragments = undefined;
6553
+ this._fragments = undefined;
6554
+ this._bindFragments = undefined;
6210
6555
  });
6211
6556
  }
6212
6557
  _extractHashFromURL() {
@@ -6258,6 +6603,11 @@ up.Request = (_a = class Request extends up.Record {
6258
6603
  this.abort({ reason: 'Prevented by event listener' });
6259
6604
  }
6260
6605
  }
6606
+ runPreviews(renderOptions) {
6607
+ if (!this.ended && !this.fromCache) {
6608
+ this._revertPreviews = up.status.runPreviews(this, renderOptions);
6609
+ }
6610
+ }
6261
6611
  _emitLoad() {
6262
6612
  let event = this.emit('up:request:load', { log: ['Loading %s', this.description] });
6263
6613
  return !event.defaultPrevented;
@@ -6287,35 +6637,46 @@ up.Request = (_a = class Request extends up.Record {
6287
6637
  }
6288
6638
  }
6289
6639
  _setAbortedState(reason) {
6290
- if (this._isSettled())
6640
+ if (this.ended)
6291
6641
  return;
6292
6642
  let message = 'Aborted request to ' + this.description + (reason ? ': ' + reason : '');
6293
6643
  this.state = 'aborted';
6294
- this.deferred.reject(new up.Aborted(message));
6644
+ this._reject(new up.Aborted(message));
6295
6645
  this.emit('up:request:aborted', { log: message });
6296
6646
  return true;
6297
6647
  }
6298
6648
  _setOfflineState(reason) {
6299
- if (this._isSettled())
6649
+ if (this.ended)
6300
6650
  return;
6301
6651
  let message = 'Cannot load request to ' + this.description + (reason ? ': ' + reason : '');
6302
6652
  this.state = 'offline';
6303
6653
  this.emit('up:request:offline', { log: message });
6304
- this.deferred.reject(new up.Offline(message));
6654
+ this._reject(new up.Offline(message));
6305
6655
  }
6306
6656
  respondWith(response) {
6307
6657
  this.response = response;
6308
- if (this._isSettled())
6658
+ if (this.ended)
6309
6659
  return;
6310
6660
  this.state = 'loaded';
6311
6661
  if (response.ok) {
6312
- this.deferred.resolve(response);
6662
+ this._resolve(response);
6313
6663
  }
6314
6664
  else {
6315
- this.deferred.reject(response);
6665
+ this._reject(response);
6316
6666
  }
6317
6667
  }
6318
- _isSettled() {
6668
+ _resolve(response) {
6669
+ this._onSettle();
6670
+ this._deferred.resolve(response);
6671
+ }
6672
+ _reject(responseOrError) {
6673
+ this._onSettle();
6674
+ this._deferred.reject(responseOrError);
6675
+ }
6676
+ _onSettle() {
6677
+ this._revertPreviews?.();
6678
+ }
6679
+ get ended() {
6319
6680
  return (this.state !== 'new') && (this.state !== 'loading') && (this.state !== 'tracking');
6320
6681
  }
6321
6682
  csrfHeader() {
@@ -6365,7 +6726,7 @@ up.Request = (_a = class Request extends up.Record {
6365
6726
  }
6366
6727
  _buildEventEmitter(args) {
6367
6728
  return up.EventEmitter.fromEmitArgs(args, {
6368
- layer: this.layer,
6729
+ layer: this.bindLayer,
6369
6730
  request: this,
6370
6731
  origin: this.origin
6371
6732
  });
@@ -6379,12 +6740,15 @@ up.Request = (_a = class Request extends up.Record {
6379
6740
  get description() {
6380
6741
  return this.method + ' ' + this.url;
6381
6742
  }
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));
6743
+ isBoundToSubtrees(subtreeRoots) {
6744
+ subtreeRoots = u.wrapList(subtreeRoots);
6745
+ return u.some(this.bindFragments, function (fragment) {
6746
+ return u.some(subtreeRoots, (subtreeElement) => subtreeElement.contains(fragment));
6386
6747
  });
6387
6748
  }
6749
+ isBoundToLayers(layers) {
6750
+ return u.contains(layers, this.bindLayer);
6751
+ }
6388
6752
  get age() {
6389
6753
  return new Date() - this.builtAt;
6390
6754
  }
@@ -6447,7 +6811,7 @@ up.Request = (_a = class Request extends up.Record {
6447
6811
  }
6448
6812
  },
6449
6813
  (() => {
6450
- u.delegate(_a.prototype, ['then', 'catch', 'finally'], function () { return this.deferred; });
6814
+ u.delegatePromise(_a.prototype, '_deferred');
6451
6815
  })(),
6452
6816
  _a);
6453
6817
 
@@ -6488,8 +6852,8 @@ class Route {
6488
6852
  return true;
6489
6853
  if (!newValue)
6490
6854
  return false;
6491
- let cachedTokens = u.parseTokens(cachedValue, { separator: 'comma' });
6492
- let newTokens = u.parseTokens(newValue, { separator: 'comma' });
6855
+ let cachedTokens = up.fragment.splitTarget(cachedValue);
6856
+ let newTokens = up.fragment.splitTarget(newValue);
6493
6857
  return u.containsAll(cachedTokens, newTokens);
6494
6858
  }
6495
6859
  else {
@@ -6546,7 +6910,13 @@ up.Request.Cache = class Cache {
6546
6910
  async track(existingRequest, newRequest, options = {}) {
6547
6911
  newRequest.trackedRequest = existingRequest;
6548
6912
  newRequest.state = 'tracking';
6549
- let value = await u.always(existingRequest);
6913
+ let value;
6914
+ if (existingRequest.ended && existingRequest.response) {
6915
+ value = existingRequest.response;
6916
+ }
6917
+ else {
6918
+ value = await u.always(existingRequest);
6919
+ }
6550
6920
  if (value instanceof up.Response) {
6551
6921
  if (options.force || existingRequest.cacheRoute.satisfies(existingRequest, newRequest)) {
6552
6922
  newRequest.fromCache = true;
@@ -6562,7 +6932,7 @@ up.Request.Cache = class Cache {
6562
6932
  }
6563
6933
  else {
6564
6934
  newRequest.state = existingRequest.state;
6565
- newRequest.deferred.reject(value);
6935
+ newRequest._reject(value);
6566
6936
  }
6567
6937
  }
6568
6938
  willHaveSameResponse(existingRequest, newRequest) {
@@ -6642,8 +7012,10 @@ up.Request.Queue = class Queue {
6642
7012
  }
6643
7013
  }
6644
7014
  _scheduleSlowTimer(request) {
6645
- let timeUntilLate = Math.max(request.badResponseTime - request.age, 0);
6646
- u.timer(timeUntilLate, () => this._checkLate());
7015
+ if (!request.isTimed())
7016
+ return;
7017
+ let timeUntilLate = Math.max(request.effectiveLateTime - request.age);
7018
+ u.timer(timeUntilLate, () => this._checkForLate());
6647
7019
  }
6648
7020
  _getMaxConcurrency() {
6649
7021
  return u.evalOption(up.network.config.concurrency);
@@ -6673,8 +7045,8 @@ up.Request.Queue = class Queue {
6673
7045
  if ((responseOrError instanceof up.Response) && responseOrError.ok) {
6674
7046
  up.network.registerAliasForRedirect(request, responseOrError);
6675
7047
  }
6676
- this._checkLate();
6677
7048
  queueMicrotask(() => this._poke());
7049
+ u.task(() => this._checkForRecover());
6678
7050
  }
6679
7051
  _poke() {
6680
7052
  let request;
@@ -6683,9 +7055,7 @@ up.Request.Queue = class Queue {
6683
7055
  }
6684
7056
  }
6685
7057
  abort(...args) {
6686
- let options = u.extractOptions(args);
6687
- let { except, reason, logOnce } = options;
6688
- let conditions = args[0] ?? true;
7058
+ let [conditions = true, { except, reason, logOnce }] = u.args(args, 'val', 'options');
6689
7059
  let tester = up.Request.tester(conditions, { except });
6690
7060
  for (let list of [this._currentRequests, this._queuedRequests]) {
6691
7061
  const abortableRequests = u.filter(list, tester);
@@ -6699,22 +7069,25 @@ up.Request.Queue = class Queue {
6699
7069
  }
6700
7070
  }
6701
7071
  }
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
- }
7072
+ _checkForLate() {
7073
+ if (!this._emittedLate && this._hasLateTimedRequests()) {
7074
+ this._emittedLate = true;
7075
+ up.emit('up:network:late', { log: 'Server is slow to respond' });
7076
+ }
7077
+ }
7078
+ _checkForRecover() {
7079
+ if (this._emittedLate && !this._timedRequests.length) {
7080
+ this._emittedLate = false;
7081
+ up.emit('up:network:recover', { log: 'Slow requests were loaded' });
6712
7082
  }
6713
7083
  }
6714
- _isLate() {
6715
- const allForegroundRequests = u.reject(this.allRequests, 'background');
7084
+ get _timedRequests() {
7085
+ return this.allRequests.filter((request) => request.isTimed());
7086
+ }
7087
+ _hasLateTimedRequests() {
6716
7088
  const timerTolerance = 1;
6717
- return u.some(allForegroundRequests, (request) => request.age >= (request.badResponseTime - timerTolerance));
7089
+ const isLate = (request) => request.age >= (request.effectiveLateTime - timerTolerance);
7090
+ return u.some(this._timedRequests, isLate);
6718
7091
  }
6719
7092
  };
6720
7093
 
@@ -6873,7 +7246,7 @@ up.Response = class Response extends up.Record {
6873
7246
  }
6874
7247
  get varyHeaderNames() {
6875
7248
  let varyHeaderValue = this.header('Vary');
6876
- return u.parseTokens(varyHeaderValue, { separator: 'comma' });
7249
+ return u.getSimpleTokens(varyHeaderValue, { separator: ',' });
6877
7250
  }
6878
7251
  get contentType() {
6879
7252
  return this.header('Content-Type');
@@ -6916,15 +7289,15 @@ const u = up.util;
6916
7289
  const e = up.element;
6917
7290
  const FULL_DOCUMENT_PATTERN = /^\s*<(html|!DOCTYPE)\b/i;
6918
7291
  up.ResponseDoc = (_a = class ResponseDoc {
6919
- constructor({ document, fragment, content, target, origin, cspNonces, match }) {
7292
+ constructor({ document, fragment, content, target, origin, data, cspNonces, match }) {
6920
7293
  if (document) {
6921
- this._parseDocument(document);
7294
+ this._parseDocument(document, origin, data);
6922
7295
  }
6923
7296
  else if (fragment) {
6924
- this._parseFragment(fragment);
7297
+ this._parseFragment(fragment, origin, data);
6925
7298
  }
6926
7299
  else {
6927
- this._parseContent(content || '', target);
7300
+ this._parseContent(content || '', origin, target, data);
6928
7301
  }
6929
7302
  this._cspNonces = cspNonces;
6930
7303
  if (origin) {
@@ -6935,46 +7308,49 @@ up.ResponseDoc = (_a = class ResponseDoc {
6935
7308
  }
6936
7309
  this._match = match;
6937
7310
  }
6938
- _parseDocument(value) {
7311
+ _parseDocument(value, origin, data) {
6939
7312
  if (value instanceof Document) {
6940
7313
  this._document = value;
6941
7314
  this._isFullDocument = true;
6942
7315
  }
6943
7316
  else if (u.isString(value)) {
6944
- this._document = e.createBrokenDocumentFromHTML(value);
6945
7317
  this._isFullDocument = FULL_DOCUMENT_PATTERN.test(value);
6946
- this._isDocumentBroken = true;
7318
+ let htmlParser = (html) => [e.createBrokenDocumentFromHTML(html)];
7319
+ let nodes = up.fragment.provideNodes(value, { origin, data, htmlParser });
7320
+ if (nodes[0] instanceof Document) {
7321
+ this._document = nodes[0];
7322
+ }
7323
+ else {
7324
+ this._document = this._buildFauxDocument(nodes);
7325
+ }
6947
7326
  }
6948
7327
  else {
6949
7328
  this._document = this._buildFauxDocument(value);
6950
- this._isFullDocument = value.matches('html');
6951
7329
  }
6952
7330
  }
6953
- _parseFragment(value) {
6954
- let parsed = u.isString(value) ? e.createFromHTML(value) : value;
6955
- this._document = this._buildFauxDocument(parsed);
7331
+ _parseDocumentFromHTML(html) {
7332
+ return e.createBrokenDocumentFromHTML(html);
7333
+ }
7334
+ _parseFragment(value, origin, data) {
7335
+ let element = e.extractSingular(up.fragment.provideNodes(value, { origin, data }));
7336
+ this._document = this._buildFauxDocument(element);
6956
7337
  }
6957
- _parseContent(value, target) {
7338
+ _parseContent(value, origin, target, data) {
6958
7339
  if (!target)
6959
7340
  up.fail("must pass a { target } when passing { content }");
6960
7341
  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
- }
7342
+ let nodes = up.fragment.provideNodes(value, { origin, data });
7343
+ let matchingElement = e.createFromSelector(simplifiedTarget, { content: nodes });
6968
7344
  this._document = this._buildFauxDocument(matchingElement);
6969
7345
  }
6970
- _buildFauxDocument(node) {
7346
+ _buildFauxDocument(nodes) {
7347
+ nodes = u.wrapList(nodes);
6971
7348
  let fauxDocument = document.createElement('up-document');
6972
- fauxDocument.append(node);
6973
- fauxDocument.documentElement = node;
7349
+ fauxDocument.append(...nodes);
6974
7350
  return fauxDocument;
6975
7351
  }
6976
7352
  rootSelector() {
6977
- return up.fragment.toTarget(this._document.documentElement);
7353
+ return up.fragment.toTarget(this._document.children[0]);
6978
7354
  }
6979
7355
  get title() {
6980
7356
  return this._fromHead(this._getTitleText);
@@ -7055,7 +7431,7 @@ up.ResponseDoc = (_a = class ResponseDoc {
7055
7431
  }
7056
7432
  finalizeElement(element) {
7057
7433
  up.NonceableCallback.adoptNonces(element, this._cspNonces);
7058
- if (this._isDocumentBroken) {
7434
+ if (this._document instanceof Document) {
7059
7435
  let brokenElements = e.subtree(element, ':is(noscript,script,audio,video):not(.up-keeping, .up-keeping *)');
7060
7436
  u.each(brokenElements, e.fixParserDamage);
7061
7437
  }
@@ -7164,16 +7540,17 @@ up.RevealMotion = class RevealMotion {
7164
7540
  /***/ (() => {
7165
7541
 
7166
7542
  const u = up.util;
7167
- const CSS_HAS_SUFFIX_PATTERN = /:has\(([^)]+)\)$/;
7543
+ const e = up.element;
7168
7544
  up.Selector = class Selector {
7169
7545
  constructor(selector, elementOrDocument, options = {}) {
7170
7546
  this._filters = [];
7171
- if (!options.destroying) {
7547
+ let matchingInExternalDocument = elementOrDocument && !document.contains(elementOrDocument);
7548
+ if (!matchingInExternalDocument && !options.destroying) {
7172
7549
  this._filters.push(up.fragment.isNotDestroying);
7173
7550
  }
7174
- let matchingInExternalDocument = elementOrDocument && !document.contains(elementOrDocument);
7551
+ this._ignoreLayers = matchingInExternalDocument || options.layer === 'any' || up.layer.count === 1;
7175
7552
  let expandTargetLayer;
7176
- if (matchingInExternalDocument || options.layer === 'any') {
7553
+ if (this._ignoreLayers) {
7177
7554
  expandTargetLayer = up.layer.root;
7178
7555
  }
7179
7556
  else {
@@ -7184,44 +7561,45 @@ up.Selector = class Selector {
7184
7561
  this._filters.push(match => u.some(this._layers, layer => layer.contains(match)));
7185
7562
  expandTargetLayer = this._layers[0];
7186
7563
  }
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
- });
7564
+ this._selectors = up.fragment.expandTargets(selector, { ...options, layer: expandTargetLayer });
7197
7565
  this._unionSelector = this._selectors.join() || 'match-none';
7198
7566
  }
7199
7567
  matches(element) {
7200
- return element.matches(this._unionSelector) && this._passesFilter(element);
7568
+ return e.elementLikeMatches(element, this._unionSelector) && this._passesFilter(element);
7201
7569
  }
7202
7570
  closest(element) {
7203
- let parentElement;
7204
- if (this.matches(element)) {
7205
- return element;
7571
+ return this._filterOne(element.closest(this._unionSelector));
7572
+ }
7573
+ descendants(root = document) {
7574
+ return this._filterMany(root.querySelectorAll(this._unionSelector));
7575
+ }
7576
+ firstDescendant(root) {
7577
+ if (this._ignoreLayers) {
7578
+ root ||= document;
7579
+ return this._firstSelectorMatch((selector) => root.querySelectorAll(selector));
7206
7580
  }
7207
- else if (parentElement = element.parentElement) {
7208
- return this.closest(parentElement);
7581
+ else {
7582
+ return u.findResult(this._layers, (layer) => {
7583
+ return this._firstSelectorMatch((selector) => e.subtree(layer.element, selector));
7584
+ });
7209
7585
  }
7210
7586
  }
7587
+ subtree(root) {
7588
+ return this._filterMany(e.subtree(root, this._unionSelector));
7589
+ }
7590
+ _firstSelectorMatch(fn) {
7591
+ return u.findResult(this._selectors, (selector) => {
7592
+ return this._filterMany(fn(selector))[0];
7593
+ });
7594
+ }
7211
7595
  _passesFilter(element) {
7212
- return u.every(this._filters, filter => filter(element));
7596
+ return element && u.every(this._filters, filter => filter(element));
7213
7597
  }
7214
- descendants(root = document) {
7215
- const results = u.flatMap(this._selectors, selector => root.querySelectorAll(selector));
7216
- return u.filter(results, element => this._passesFilter(element));
7598
+ _filterOne(element) {
7599
+ return u.presence(element, this._passesFilter.bind(this));
7217
7600
  }
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;
7601
+ _filterMany(elements) {
7602
+ return u.filter(elements, this._passesFilter.bind(this));
7225
7603
  }
7226
7604
  };
7227
7605
 
@@ -7356,7 +7734,7 @@ up.URLPattern = class URLPattern {
7356
7734
  this._groups = [];
7357
7735
  const positiveList = [];
7358
7736
  const negativeList = [];
7359
- for (let pattern of u.parseTokens(fullPattern)) {
7737
+ for (let pattern of u.getSimpleTokens(fullPattern)) {
7360
7738
  if (pattern[0] === '-') {
7361
7739
  negativeList.push(pattern.substring(1));
7362
7740
  }
@@ -7479,7 +7857,7 @@ up.framework = (function () {
7479
7857
  return !supportIssue();
7480
7858
  }
7481
7859
  function supportIssue() {
7482
- for (let feature of ['URL', 'Proxy', 'Promise', 'DOMParser', 'FormData']) {
7860
+ for (let feature of ['Promise', 'DOMParser', 'FormData', 'reportError']) {
7483
7861
  if (!window[feature]) {
7484
7862
  return `Browser doesn't support the ${feature} API`;
7485
7863
  }
@@ -7487,6 +7865,11 @@ up.framework = (function () {
7487
7865
  if (document.compatMode === 'BackCompat') {
7488
7866
  return 'Browser is in quirks mode (missing DOCTYPE?)';
7489
7867
  }
7868
+ for (let selector of [':is(*)', ':has(*)']) {
7869
+ if (!CSS.supports(`selector(${selector})`)) {
7870
+ return `Browser doesn't support the ${selector} selector`;
7871
+ }
7872
+ }
7490
7873
  }
7491
7874
  return {
7492
7875
  onEvaled,
@@ -7655,22 +8038,22 @@ up.protocol = (function () {
7655
8038
  return extractHeader(xhr, 'expireCache') || up.migrate.clearCacheFromXHR?.(xhr);
7656
8039
  }
7657
8040
  function contextFromXHR(xhr) {
7658
- return extractHeader(xhr, 'context', JSON.parse);
8041
+ return extractHeader(xhr, 'context', u.parseRelaxedJSON);
7659
8042
  }
7660
8043
  function methodFromXHR(xhr) {
7661
8044
  return extractHeader(xhr, 'method', u.normalizeMethod);
7662
8045
  }
7663
8046
  function titleFromXHR(xhr) {
7664
- return up.migrate.titleFromXHR?.(xhr) ?? extractHeader(xhr, 'title', JSON.parse);
8047
+ return up.migrate.titleFromXHR?.(xhr) ?? extractHeader(xhr, 'title', u.parseRelaxedJSON);
7665
8048
  }
7666
8049
  function eventPlansFromXHR(xhr) {
7667
- return extractHeader(xhr, 'events', JSON.parse);
8050
+ return extractHeader(xhr, 'events', u.parseRelaxedJSON);
7668
8051
  }
7669
8052
  function acceptLayerFromXHR(xhr) {
7670
- return extractHeader(xhr, 'acceptLayer', JSON.parse);
8053
+ return extractHeader(xhr, 'acceptLayer', u.parseRelaxedJSON);
7671
8054
  }
7672
8055
  function dismissLayerFromXHR(xhr) {
7673
- return extractHeader(xhr, 'dismissLayer', JSON.parse);
8056
+ return extractHeader(xhr, 'dismissLayer', u.parseRelaxedJSON);
7674
8057
  }
7675
8058
  const initialRequestMethod = u.memoize(function () {
7676
8059
  return u.normalizeMethod(up.browser.popCookie('_up_method'));
@@ -7841,6 +8224,9 @@ up.script = (function () {
7841
8224
  ],
7842
8225
  nonceableAttributes: [
7843
8226
  'up-watch',
8227
+ 'up-on-keep',
8228
+ 'up-on-hungry',
8229
+ 'up-on-opened',
7844
8230
  'up-on-accepted',
7845
8231
  'up-on-dismissed',
7846
8232
  'up-on-loaded',
@@ -7848,9 +8234,13 @@ up.script = (function () {
7848
8234
  'up-on-finished',
7849
8235
  'up-on-error',
7850
8236
  'up-on-offline',
8237
+ 'up-placeholder',
7851
8238
  ],
7852
8239
  scriptSelectors: [
7853
- 'script'
8240
+ 'script:not([type])',
8241
+ 'script[type="text/javascript"]',
8242
+ 'script[type="module"]',
8243
+ 'script[type="importmap"]',
7854
8244
  ],
7855
8245
  noScriptSelectors: [
7856
8246
  'script[type="application/ld+json"]'
@@ -7881,10 +8271,13 @@ up.script = (function () {
7881
8271
  function registerAttrCompiler(...args) {
7882
8272
  let [attr, options, valueCallback] = parseProcessorArgs(args);
7883
8273
  let selector = `[${attr}]`;
8274
+ let { defaultValue } = options;
7884
8275
  let callback = (element) => {
7885
- let value = e.booleanOrStringAttr(element, attr, options.defaultValue);
7886
- if (!value)
8276
+ let value = e.booleanOrStringAttr(element, attr);
8277
+ if (value === false)
7887
8278
  return;
8279
+ if (u.isDefined(defaultValue) && value === true)
8280
+ value = defaultValue;
7888
8281
  return valueCallback(element, value);
7889
8282
  };
7890
8283
  registerProcessor([selector, options, callback]);
@@ -7911,11 +8304,7 @@ up.script = (function () {
7911
8304
  }
7912
8305
  }
7913
8306
  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];
8307
+ return u.args(args, 'val', 'options', 'callback');
7919
8308
  };
7920
8309
  function buildProcessor(args, overrides) {
7921
8310
  let [selector, options, callback] = parseProcessorArgs(args);
@@ -7953,18 +8342,16 @@ up.script = (function () {
7953
8342
  pass.run();
7954
8343
  }
7955
8344
  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
- }
8345
+ let fns = u.scanFunctions(destructor);
8346
+ if (!fns.length)
8347
+ return;
8348
+ let registry = (element.upDestructors ||= buildDestructorRegistry(element));
8349
+ registry.guard(fns);
8350
+ }
8351
+ function buildDestructorRegistry(element) {
8352
+ let registry = u.cleaner();
8353
+ registry(e.addClassTemp(element, 'up-can-clean'));
8354
+ return registry;
7968
8355
  }
7969
8356
  function hello(element, options = {}) {
7970
8357
  element = up.fragment.get(element, options);
@@ -7981,18 +8368,12 @@ up.script = (function () {
7981
8368
  return element.upData ||= buildData(element);
7982
8369
  }
7983
8370
  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
- }
8371
+ let parsedJSON = e.jsonAttr(element, 'up-data') ?? {};
8372
+ if (!u.isOptions(parsedJSON)) {
8373
+ return parsedJSON;
7994
8374
  }
7995
8375
  return {
8376
+ ...element.upTemplateData,
7996
8377
  ...element.dataset,
7997
8378
  ...parsedJSON,
7998
8379
  ...element.upCompileData,
@@ -8016,6 +8397,9 @@ up.script = (function () {
8016
8397
  let selector = config.selector('scriptSelectors');
8017
8398
  u.each(e.subtree(root, selector), disableScript);
8018
8399
  }
8400
+ function isScript(value) {
8401
+ return config.matches(value, 'scriptSelectors');
8402
+ }
8019
8403
  function reset() {
8020
8404
  registeredCompilers = u.filter(registeredCompilers, 'isDefault');
8021
8405
  registeredMacros = u.filter(registeredMacros, 'isDefault');
@@ -8033,6 +8417,7 @@ up.script = (function () {
8033
8417
  findAssets,
8034
8418
  assertAssetsOK,
8035
8419
  disableSubtree: disableScriptsInSubtree,
8420
+ isScript,
8036
8421
  };
8037
8422
  })();
8038
8423
  up.compiler = up.script.compiler;
@@ -8181,7 +8566,7 @@ up.history = (function () {
8181
8566
  }
8182
8567
  }
8183
8568
  function updateLang(newLang) {
8184
- e.toggleAttr(e.root, 'lang', newLang, !!newLang);
8569
+ e.setAttrPresence(e.root, 'lang', newLang, !!newLang);
8185
8570
  }
8186
8571
  up.macro('[up-back]', function (link) {
8187
8572
  if (previousLocation) {
@@ -8223,14 +8608,18 @@ up.fragment = (function () {
8223
8608
  return tagName;
8224
8609
  }
8225
8610
  }
8611
+ const STRONG_TARGET_DERIVERS = [
8612
+ '[up-id]',
8613
+ '[id]',
8614
+ 'html',
8615
+ 'head',
8616
+ 'body',
8617
+ ];
8226
8618
  const config = new up.Config(() => ({
8227
8619
  badTargetClasses: [/^up-/],
8620
+ strongTargetDerivers: STRONG_TARGET_DERIVERS,
8228
8621
  targetDerivers: [
8229
- '[up-id]',
8230
- '[id]',
8231
- 'html',
8232
- 'head',
8233
- 'body',
8622
+ ...STRONG_TARGET_DERIVERS,
8234
8623
  'main',
8235
8624
  '[up-main]',
8236
8625
  upTagName,
@@ -8248,10 +8637,19 @@ up.fragment = (function () {
8248
8637
  'form',
8249
8638
  ],
8250
8639
  verifyDerivedTarget: true,
8640
+ renderOptions: {
8641
+ hungry: true,
8642
+ keep: true,
8643
+ saveScroll: true,
8644
+ saveFocus: true,
8645
+ focus: 'keep',
8646
+ abort: 'target',
8647
+ failOptions: true,
8648
+ feedback: true,
8649
+ },
8251
8650
  navigateOptions: {
8252
8651
  cache: 'auto',
8253
8652
  revalidate: 'auto',
8254
- feedback: true,
8255
8653
  fallback: true,
8256
8654
  focus: 'auto',
8257
8655
  scroll: 'auto',
@@ -8264,7 +8662,7 @@ up.fragment = (function () {
8264
8662
  autoFocus: ['hash', 'autofocus', 'main-if-main', 'keep', 'target-if-lost'],
8265
8663
  autoScroll: ['hash', 'layer-if-main'],
8266
8664
  autoRevalidate: (response) => response.expired,
8267
- skipResponse: defaultSkipResponse
8665
+ skipResponse: defaultSkipResponse,
8268
8666
  }));
8269
8667
  u.delegate(config, ['mainTargets'], () => up.layer.config.any);
8270
8668
  function defaultSkipResponse({ response, expiredResponse }) {
@@ -8323,14 +8721,12 @@ up.fragment = (function () {
8323
8721
  return fragment.isConnected && isNotDestroying(fragment);
8324
8722
  }
8325
8723
  function getSmart(...args) {
8326
- const options = u.extractOptions(args);
8327
- const selector = args.pop();
8328
- const root = args[0];
8329
- if (u.isElementish(selector)) {
8724
+ let [root, selector, options] = parseGetArgs(args);
8725
+ if (u.isElementLike(selector)) {
8330
8726
  return e.get(selector);
8331
8727
  }
8332
8728
  if (root) {
8333
- return getDumb(root, selector, options);
8729
+ return getFirstDescendant(root, selector, options);
8334
8730
  }
8335
8731
  return new up.FragmentFinder({
8336
8732
  selector,
@@ -8339,13 +8735,16 @@ up.fragment = (function () {
8339
8735
  match: options.match,
8340
8736
  }).find();
8341
8737
  }
8342
- function getDumb(...args) {
8343
- return getAll(...args)[0];
8738
+ function getFirstDescendant(...args) {
8739
+ let [root, selectorString, options] = parseGetArgs(args);
8740
+ let selector = new up.Selector(selectorString, root, options);
8741
+ return selector.firstDescendant(root);
8742
+ }
8743
+ function parseGetArgs(args) {
8744
+ return u.args(args, 'val', 'val', 'options');
8344
8745
  }
8345
8746
  function getAll(...args) {
8346
- const options = u.extractOptions(args);
8347
- let selectorString = args.pop();
8348
- const root = args[0];
8747
+ let [root, selectorString, options] = parseGetArgs(args);
8349
8748
  if (u.isElement(selectorString)) {
8350
8749
  return [selectorString];
8351
8750
  }
@@ -8451,8 +8850,9 @@ up.fragment = (function () {
8451
8850
  function cannotTarget(element) {
8452
8851
  throw new up.CannotTarget(untargetableMessage(element));
8453
8852
  }
8454
- function tryToTarget(element, options) {
8455
- return u.findResult(config.targetDerivers, function (deriver) {
8853
+ function tryToTarget(element, options = {}) {
8854
+ let derivers = options.strong ? config.strongTargetDerivers : config.targetDerivers;
8855
+ return u.findResult(derivers, function (deriver) {
8456
8856
  let target = deriveTarget(element, deriver);
8457
8857
  if (target && isGoodTarget(target, element, options)) {
8458
8858
  return target;
@@ -8478,7 +8878,7 @@ up.fragment = (function () {
8478
8878
  }
8479
8879
  }
8480
8880
  function deriveTargetFromPattern(element, deriver) {
8481
- let { includePath, excludeRaw } = up.element.parseSelector(deriver);
8881
+ let { includePath, excludeRaw } = e.parseSelector(deriver);
8482
8882
  if (includePath.length !== 1) {
8483
8883
  throw new up.CannotParse(deriver);
8484
8884
  }
@@ -8516,7 +8916,8 @@ up.fragment = (function () {
8516
8916
  return result;
8517
8917
  }
8518
8918
  function isGoodTarget(target, element, options = {}) {
8519
- return !isAlive(element) || !config.verifyDerivedTarget || up.fragment.get(target, { layer: element, ...options }) === element;
8919
+ let verify = options.verify ?? config.verifyDerivedTarget;
8920
+ return !isAlive(element) || !verify || up.fragment.get(target, { layer: element, ...options }) === element;
8520
8921
  }
8521
8922
  function matchesPattern(pattern, str) {
8522
8923
  if (u.isRegExp(pattern)) {
@@ -8558,7 +8959,7 @@ up.fragment = (function () {
8558
8959
  let firstSwappableTarget = toTarget(layer.getFirstSwappableElement(), options);
8559
8960
  targets.unshift(target.replace(LAYER_PSEUDO, firstSwappableTarget));
8560
8961
  }
8561
- else if (u.isElementish(target)) {
8962
+ else if (u.isElementLike(target)) {
8562
8963
  expanded.push(toTarget(target, options));
8563
8964
  }
8564
8965
  else if (u.isString(target)) {
@@ -8585,11 +8986,13 @@ up.fragment = (function () {
8585
8986
  }
8586
8987
  });
8587
8988
  }
8588
- function resolveOrigin(...args) {
8589
- return (up.migrate.resolveOrigin || modernResolveOrigin)(...args);
8989
+ function resolveOrigin(target, options) {
8990
+ if (!u.isString(target))
8991
+ return target;
8992
+ return (up.migrate.resolveOrigin || modernResolveOrigin)(target, options);
8590
8993
  }
8591
8994
  function splitTarget(target) {
8592
- return u.parseTokens(target, { separator: 'comma' });
8995
+ return u.getComplexTokens(target);
8593
8996
  }
8594
8997
  function parseTargetSteps(target, options = {}) {
8595
8998
  let defaultPlacement = options.defaultPlacement || 'swap';
@@ -8669,13 +9072,13 @@ up.fragment = (function () {
8669
9072
  let elements;
8670
9073
  if (options.target) {
8671
9074
  elements = getAll(options.target, options);
8672
- testFn = (request) => request.isPartOfSubtree(elements);
9075
+ testFn = (request) => request.isBoundToSubtrees(elements);
8673
9076
  reason ||= 'Aborting requests within fragment';
8674
9077
  }
8675
9078
  else {
8676
9079
  let layers = up.layer.getAll(options);
8677
9080
  elements = u.map(layers, 'element');
8678
- testFn = (request) => u.contains(layers, request.layer);
9081
+ testFn = (request) => request.isBoundToLayers(layers);
8679
9082
  reason ||= 'Aborting requests within ' + layers.join(', ');
8680
9083
  }
8681
9084
  let testFnWithAbortable = (request) => request.abortable && testFn(request);
@@ -8690,8 +9093,8 @@ up.fragment = (function () {
8690
9093
  up.destructor(fragment, unsubscribe);
8691
9094
  return unsubscribe;
8692
9095
  }
8693
- function onFirstIntersect(origin, callback, { margin = 0 } = {}) {
8694
- if (e.isIntersectingWindow(origin, { margin })) {
9096
+ function onFirstIntersect(element, callback, { margin = 0 } = {}) {
9097
+ if (e.isIntersectingWindow(element, { margin })) {
8695
9098
  callback();
8696
9099
  return;
8697
9100
  }
@@ -8706,15 +9109,62 @@ up.fragment = (function () {
8706
9109
  }
8707
9110
  let observer = new IntersectionObserver(processIntersectEntries, { rootMargin: `${margin}px` });
8708
9111
  let disconnect = () => observer.disconnect();
8709
- observer.observe(origin);
8710
- onAborted(origin, disconnect);
9112
+ observer.observe(element);
9113
+ up.destructor(element, disconnect);
9114
+ }
9115
+ const STARTS_WITH_SELECTOR = /^([\w-]+|\*)?(#|\.|[:[][a-z-]{3,})/;
9116
+ function provideNodes(value, { origin, originLayer, data, htmlParser = e.createNodesFromHTML } = {}) {
9117
+ if (u.isString(value) && STARTS_WITH_SELECTOR.test(value)) {
9118
+ let [parsedValue, parsedData] = u.parseScalarJSONPairs(value)[0];
9119
+ data = { ...data, ...parsedData };
9120
+ value = up.fragment.get(parsedValue, { layer: 'closest', origin, originLayer }) || up.fail(`Cannot find template "%s"`, value);
9121
+ }
9122
+ if (u.isString(value)) {
9123
+ value = htmlParser(value);
9124
+ }
9125
+ if (isTemplate(value)) {
9126
+ value = cloneTemplate(value, data, { htmlParser });
9127
+ }
9128
+ return u.wrapList(value);
9129
+ }
9130
+ function isTemplate(value) {
9131
+ return u.isElement(value) && value.matches('template, script[type]') && !up.script.isScript(value);
9132
+ }
9133
+ function cloneTemplate(templateOrSelector, data = {}, { origin, htmlParser } = {}) {
9134
+ let template = getSmart(templateOrSelector, { origin }) || up.fail('Template not found: %o', templateOrSelector);
9135
+ let event = up.emit(template, 'up:template:clone', { data, nodes: null, log: ["Using template %o", templateOrSelector] });
9136
+ let nodes = event.nodes ?? defaultTemplateNodes(template, htmlParser);
9137
+ for (let node of nodes) {
9138
+ node.upTemplateData = data;
9139
+ }
9140
+ return nodes;
9141
+ }
9142
+ function defaultTemplateNodes(template, htmlParser = e.createNodesFromHTML) {
9143
+ let templateText = template.innerHTML;
9144
+ return htmlParser(templateText);
9145
+ }
9146
+ function insertTemp(...args) {
9147
+ let [reference, position = 'beforeend', tempValue] = u.args(args, 'val', u.isAdjacentPosition, 'val');
9148
+ let tempNodes = provideNodes(tempValue, { origin: reference });
9149
+ let tempElement = e.wrapIfRequired(tempNodes);
9150
+ let oldPosition = document.contains(tempElement) && e.documentPosition(tempElement);
9151
+ reference.insertAdjacentElement(position, tempElement);
9152
+ if (oldPosition) {
9153
+ return () => {
9154
+ oldPosition[0].insertAdjacentElement(oldPosition[1], tempElement);
9155
+ };
9156
+ }
9157
+ else {
9158
+ up.hello(tempElement);
9159
+ return () => up.destroy(tempElement);
9160
+ }
8711
9161
  }
8712
9162
  up.on('up:framework:boot', function () {
8713
9163
  const { documentElement } = document;
8714
9164
  documentElement.setAttribute('up-source', normalizeSource(location.href));
8715
9165
  up.hello(documentElement);
8716
9166
  if (!up.browser.canPushState()) {
8717
- return up.warn('Cannot push history changes. Next fragment update will load in a new page.');
9167
+ return up.warn('Cannot push history changes. Next render pass with history will load a full page.');
8718
9168
  }
8719
9169
  });
8720
9170
  return {
@@ -8724,7 +9174,7 @@ up.fragment = (function () {
8724
9174
  render,
8725
9175
  navigate,
8726
9176
  get: getSmart,
8727
- getDumb,
9177
+ getFirstDescendant,
8728
9178
  all: getAll,
8729
9179
  subtree: getSubtree,
8730
9180
  contains,
@@ -8758,6 +9208,9 @@ up.fragment = (function () {
8758
9208
  targetForSteps,
8759
9209
  compressNestedSteps,
8760
9210
  containsMainPseudo,
9211
+ insertTemp,
9212
+ provideNodes,
9213
+ cloneTemplate,
8761
9214
  };
8762
9215
  })();
8763
9216
  up.reload = up.fragment.reload;
@@ -8765,6 +9218,7 @@ up.destroy = up.fragment.destroy;
8765
9218
  up.render = up.fragment.render;
8766
9219
  up.navigate = up.fragment.navigate;
8767
9220
  up.visit = up.fragment.visit;
9221
+ up.template = { clone: up.fragment.cloneTemplate };
8768
9222
  u.delegate(up, ['context'], () => up.layer.current);
8769
9223
 
8770
9224
 
@@ -8801,7 +9255,7 @@ up.viewport = (function () {
8801
9255
  up.compiler(config.selectorFn('anchoredRightSelectors'), function (element) {
8802
9256
  return bodyShifter.onAnchoredElementInserted(element);
8803
9257
  });
8804
- function reveal(element, options) {
9258
+ const reveal = up.mockable(function (element, options) {
8805
9259
  options = u.options(options);
8806
9260
  element = f.get(element, options);
8807
9261
  if (!(options.layer = up.layer.get(element))) {
@@ -8813,7 +9267,7 @@ up.viewport = (function () {
8813
9267
  const motion = new up.RevealMotion(element, options);
8814
9268
  motion.start();
8815
9269
  return up.migrate.formerlyAsync?.('up.reveal()') || true;
8816
- }
9270
+ });
8817
9271
  function doFocus(element, { preventScroll, force, inputDevice, focusVisible } = {}) {
8818
9272
  if (force) {
8819
9273
  if (!element.hasAttribute('tabindex') && element.tabIndex === -1) {
@@ -8846,7 +9300,7 @@ up.viewport = (function () {
8846
9300
  function revealHash(hash = location.hash, options) {
8847
9301
  let match = firstHashTarget(hash, options);
8848
9302
  if (match) {
8849
- return up.reveal(match, { top: true });
9303
+ return reveal(match, { top: true });
8850
9304
  }
8851
9305
  }
8852
9306
  function allSelector() {
@@ -8950,11 +9404,11 @@ up.viewport = (function () {
8950
9404
  return new up.FIFOCache({ capacity: 30, normalizeKey: u.matchableURL });
8951
9405
  }
8952
9406
  function parseOptions(args) {
8953
- const options = u.copy(u.extractOptions(args));
9407
+ const [reference, options] = u.args(args, 'val', 'options');
8954
9408
  options.layer = up.layer.get(options);
8955
9409
  let viewports;
8956
- if (args[0]) {
8957
- viewports = [closest(args[0], options)];
9410
+ if (reference) {
9411
+ viewports = [closest(reference, options)];
8958
9412
  }
8959
9413
  else if (options.around) {
8960
9414
  viewports = getAround(options.around, options);
@@ -9040,16 +9494,19 @@ up.viewport = (function () {
9040
9494
  }
9041
9495
  return to;
9042
9496
  }
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
- });
9497
+ document.addEventListener('DOMContentLoaded', function () {
9498
+ revealHash();
9499
+ u.task(revealHash);
9051
9500
  });
9052
9501
  up.on(window, 'hashchange', () => revealHash());
9502
+ up.on('up:click', 'a[href^="#"]', function (event, link) {
9503
+ if (link.hash !== location.hash)
9504
+ return;
9505
+ if (up.link.isFollowable(link))
9506
+ return;
9507
+ if (revealHash(link.hash))
9508
+ up.event.halt(event);
9509
+ });
9053
9510
  return {
9054
9511
  reveal,
9055
9512
  revealHash,
@@ -9374,7 +9831,7 @@ up.network = (function () {
9374
9831
  cacheSize: 70,
9375
9832
  cacheExpireAge: 15 * 1000,
9376
9833
  cacheEvictAge: 90 * 60 * 1000,
9377
- badResponseTime: 400,
9834
+ lateDelay: 400,
9378
9835
  fail(response) { return (response.status < 200 || response.status > 299) && response.status !== 304; },
9379
9836
  autoCache(request) { return request.isSafe(); },
9380
9837
  expireCache(request, _response) { return !request.isSafe(); },
@@ -9399,10 +9856,7 @@ up.network = (function () {
9399
9856
  return request;
9400
9857
  }
9401
9858
  function parseRequestOptions(args) {
9402
- const options = u.extractOptions(args);
9403
- if (!options.url) {
9404
- options.url = args[0];
9405
- }
9859
+ let options = u.parseArgIntoOptions(args, 'url');
9406
9860
  up.migrate.handleRequestOptions?.(options);
9407
9861
  return options;
9408
9862
  }
@@ -9550,7 +10004,7 @@ up.layer = (function () {
9550
10004
  openAnimation: 'fade-in',
9551
10005
  closeAnimation: 'fade-out',
9552
10006
  dismissLabel: '×',
9553
- dismissAriaLabel: 'Dismiss dialog',
10007
+ dismissARIALabel: 'Dismiss dialog',
9554
10008
  dismissable: true,
9555
10009
  history: 'auto',
9556
10010
  trapFocus: true,
@@ -9630,10 +10084,7 @@ up.layer = (function () {
9630
10084
  }
9631
10085
  }
9632
10086
  }
9633
- else if (options.mode) {
9634
- options.layer = 'new';
9635
- }
9636
- else if (u.isElementish(options.target)) {
10087
+ else if (u.isElementLike(options.target)) {
9637
10088
  options.layer = stack.get(options.target, { normalizeLayerOptions: false });
9638
10089
  }
9639
10090
  else if (options.origin) {
@@ -9834,7 +10285,7 @@ up.link = (function () {
9834
10285
  parser.boolean('abortable');
9835
10286
  parser.boolean('background');
9836
10287
  parser.string('contentType');
9837
- parser.number('badResponseTime');
10288
+ parser.booleanOrNumber('lateDelay');
9838
10289
  parser.number('timeout');
9839
10290
  return options;
9840
10291
  }
@@ -9843,7 +10294,6 @@ up.link = (function () {
9843
10294
  options = u.options(options);
9844
10295
  const parser = new up.OptionsParser(link, options, { fail: true, ...parserOptions });
9845
10296
  parser.include(parseRequestOptions);
9846
- parser.boolean('feedback');
9847
10297
  options.origin ||= link;
9848
10298
  parser.boolean('fail');
9849
10299
  parser.boolean('navigate', { default: true });
@@ -9851,11 +10301,12 @@ up.link = (function () {
9851
10301
  parser.string('target');
9852
10302
  parser.booleanOrString('fallback');
9853
10303
  parser.string('match');
9854
- parser.string('content');
9855
- parser.string('fragment');
9856
10304
  parser.string('document');
9857
- parser.boolean('useKeep');
9858
- parser.boolean('useHungry');
10305
+ parser.string('fragment');
10306
+ parser.string('content');
10307
+ parser.boolean('keep', { attr: 'up-use-keep' });
10308
+ parser.boolean('hungry', { attr: 'up-use-hungry' });
10309
+ parser.json('data', { attr: 'up-use-data' });
9859
10310
  parser.callback('onLoaded');
9860
10311
  parser.callback('onRendered', { mainKey: 'result' });
9861
10312
  parser.callback('onFinished', { mainKey: 'result' });
@@ -9879,6 +10330,7 @@ up.link = (function () {
9879
10330
  parser.string('acceptLocation');
9880
10331
  parser.string('dismissLocation');
9881
10332
  parser.booleanOrString('history');
10333
+ parser.include(up.status.statusOptions);
9882
10334
  parser.booleanOrString('focus');
9883
10335
  parser.boolean('saveScroll');
9884
10336
  parser.boolean('saveFocus');
@@ -9905,10 +10357,15 @@ up.link = (function () {
9905
10357
  }
9906
10358
  const guardEvent = up.event.build('up:link:preload', { log: ['Preloading link %o', link] });
9907
10359
  return follow(link, {
10360
+ abort: false,
9908
10361
  abortable: false,
10362
+ background: true,
10363
+ cache: true,
10364
+ ...up.RenderOptions.NO_INPUT_INTERFERENCE,
10365
+ ...up.RenderOptions.NO_PREVIEWS,
9909
10366
  ...options,
9910
10367
  guardEvent,
9911
- preload: true
10368
+ preload: true,
9912
10369
  });
9913
10370
  }
9914
10371
  function preloadIssue(link) {
@@ -10048,14 +10505,16 @@ up.link = (function () {
10048
10505
  'up-href': e.attr(childLink, 'href'),
10049
10506
  ...e.upAttrs(childLink)
10050
10507
  });
10051
- area.classList.add(...e.upClasses(childLink));
10508
+ e.addClasses(area, e.upClasses(childLink));
10052
10509
  makeFollowable(area);
10053
10510
  }
10054
10511
  });
10055
10512
  up.compiler(config.selectorFn('preloadSelectors'), function (link) {
10056
10513
  if (!isPreloadDisabled(link)) {
10057
10514
  let doPreload = () => up.error.muteUncriticalRejection(preload(link));
10058
- let condition = e.booleanOrStringAttr(link, 'up-preload', null) ?? 'hover';
10515
+ let condition = e.booleanOrStringAttr(link, 'up-preload');
10516
+ if (condition === true || u.isUndefined(condition))
10517
+ condition = 'hover';
10059
10518
  onLoadCondition(condition, link, doPreload);
10060
10519
  }
10061
10520
  });
@@ -10096,10 +10555,11 @@ up.form = (function () {
10096
10555
  const e = up.element;
10097
10556
  const config = new up.Config(() => ({
10098
10557
  groupSelectors: ['[up-form-group]', 'fieldset', 'label', 'form'],
10099
- fieldSelectors: ['select', 'input:not([type=submit]):not([type=image])', 'button[type]:not([type=submit])', 'textarea'],
10558
+ fieldSelectors: ['select', 'input:not([type=submit], [type=image], [type=button])', 'button[type]:not([type=submit], [type=button])', 'textarea'],
10100
10559
  submitSelectors: ['form:is([up-submit], [up-target], [up-layer], [up-transition])'],
10101
10560
  noSubmitSelectors: ['[up-submit=false]', '[target]', e.crossOriginSelector('action')],
10102
10561
  submitButtonSelectors: ['input[type=submit]', 'input[type=image]', 'button[type=submit]', 'button:not([type])'],
10562
+ genericButtonSelectors: ['input[type=button]', 'button[type=button]'],
10103
10563
  watchInputEvents: ['input', 'change'],
10104
10564
  watchInputDelay: 0,
10105
10565
  watchChangeEvents: ['change'],
@@ -10124,6 +10584,9 @@ up.form = (function () {
10124
10584
  function findSubmitButtons(root) {
10125
10585
  return e.subtree(root, submitButtonSelector());
10126
10586
  }
10587
+ function findGenericButtons(root) {
10588
+ return e.subtree(root, config.selector('genericButtonSelectors'));
10589
+ }
10127
10590
  function isSubmitButton(element) {
10128
10591
  return element?.matches(submitButtonSelector());
10129
10592
  }
@@ -10139,7 +10602,6 @@ up.form = (function () {
10139
10602
  let parser = new up.OptionsParser(form, options, parserOptions);
10140
10603
  parser.include(destinationOptions);
10141
10604
  parser.string('failTarget', { default: up.fragment.tryToTarget(form) });
10142
- parser.booleanOrString('disable');
10143
10605
  options.guardEvent ||= up.event.build('up:form:submit', {
10144
10606
  submitButton: options.submitButton,
10145
10607
  log: 'Submitting form',
@@ -10147,14 +10609,14 @@ up.form = (function () {
10147
10609
  form,
10148
10610
  });
10149
10611
  options.origin ||= up.viewport.focusedElementWithin(form) || options.submitButton || form;
10612
+ options.activeElements = u.uniq([options.origin, options.submitButton, form].filter(u.isElement));
10150
10613
  parser.include(up.link.followOptions);
10151
10614
  return options;
10152
10615
  }
10153
10616
  function watchOptions(field, options, parserOptions = {}) {
10154
10617
  options = u.options(options);
10155
10618
  let parser = new up.OptionsParser(field, options, { ...parserOptions, closest: true, attrPrefix: 'up-watch-' });
10156
- parser.boolean('feedback');
10157
- parser.booleanOrString('disable');
10619
+ parser.include(up.status.statusOptions);
10158
10620
  parser.string('event');
10159
10621
  parser.number('delay');
10160
10622
  let config = up.form.config;
@@ -10169,61 +10631,58 @@ up.form = (function () {
10169
10631
  return options;
10170
10632
  }
10171
10633
  function disableContainer(container) {
10172
- let focusedElement = document.activeElement;
10634
+ let controls = [
10635
+ ...findFields(container),
10636
+ ...findSubmitButtons(container),
10637
+ ...findGenericButtons(container),
10638
+ ];
10639
+ return u.sequence(u.map(controls, disableControl));
10640
+ }
10641
+ function disableControl(control) {
10642
+ if (control.disabled)
10643
+ return;
10173
10644
  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) {
10645
+ if (document.activeElement === control) {
10646
+ focusFallback = findGroup(control);
10647
+ control.disabled = true;
10182
10648
  up.focus(focusFallback, { force: true, preventScroll: true });
10183
10649
  }
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;
10650
+ else {
10651
+ control.disabled = true;
10192
10652
  }
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
- }
10653
+ return () => {
10654
+ control.disabled = false;
10655
+ if (focusFallback && document.activeElement === focusFallback && control.isConnected) {
10656
+ up.focus(control, { preventScroll: true });
10206
10657
  }
10207
- }
10208
- }
10209
- function disableWhile(promise, options) {
10210
- let undoDisable = handleDisableOption(options);
10211
- u.always(promise, undoDisable);
10658
+ };
10212
10659
  }
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;
10660
+ function getDisableContainers(disable, origin) {
10661
+ let givenOrigin = () => origin || up.fail('Missing { origin }');
10662
+ let originScope = () => getScope(givenOrigin());
10220
10663
  if (disable === true) {
10221
- containers = [getOriginForm()];
10664
+ return [originScope()];
10665
+ }
10666
+ else if (u.isElement(disable)) {
10667
+ return [disable];
10222
10668
  }
10223
10669
  else if (u.isString(disable)) {
10224
- containers = up.fragment.subtree(getOriginForm(), disable, { origin });
10670
+ return up.fragment.subtree(originScope(), disable, { origin });
10671
+ }
10672
+ else if (u.isArray(disable)) {
10673
+ return u.flatMap(disable, (d) => getDisableContainers(d, origin));
10674
+ }
10675
+ else {
10676
+ return [];
10225
10677
  }
10226
- return u.sequence(containers.map(disableContainer));
10678
+ }
10679
+ function getDisablePreviewFn(disable, origin) {
10680
+ return function (preview) {
10681
+ let containers = getDisableContainers(disable, origin);
10682
+ for (let container of containers) {
10683
+ preview.disable(container);
10684
+ }
10685
+ };
10227
10686
  }
10228
10687
  function destinationOptions(form, options, parserOptions) {
10229
10688
  options = u.options(options);
@@ -10251,10 +10710,10 @@ up.form = (function () {
10251
10710
  }
10252
10711
  return options;
10253
10712
  }
10254
- function watch(root, ...args) {
10713
+ function watch(...args) {
10714
+ let [root, options, callback] = u.args(args, 'val', 'options', 'callback');
10255
10715
  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);
10716
+ callback ||= watchCallbackFromElement(root) || up.fail('No callback given for up.watch()');
10258
10717
  const watcher = new up.FieldWatcher(root, options, callback);
10259
10718
  watcher.start();
10260
10719
  return () => watcher.stop();
@@ -10262,12 +10721,12 @@ up.form = (function () {
10262
10721
  function watchCallbackFromElement(element) {
10263
10722
  let rawCallback = element.getAttribute('up-watch');
10264
10723
  if (rawCallback) {
10265
- return up.NonceableCallback.fromString(rawCallback).toFunction('value', 'name').bind(element);
10724
+ return up.NonceableCallback.fromString(rawCallback).toFunction('value', 'name', 'options').bind(element);
10266
10725
  }
10267
10726
  }
10268
10727
  function autosubmit(target, options = {}) {
10269
10728
  const onChange = (_diff, renderOptions) => submit(target, renderOptions);
10270
- return watch(target, { options, batch: true }, onChange);
10729
+ return watch(target, { ...options, batch: true }, onChange);
10271
10730
  }
10272
10731
  function getGroupSelectors() {
10273
10732
  return up.migrate.migratedFormGroupSelectors?.() || config.groupSelectors;
@@ -10279,10 +10738,10 @@ up.form = (function () {
10279
10738
  return u.findResult(getGroupSelectors(), function (groupSelector) {
10280
10739
  let group = field.closest(groupSelector);
10281
10740
  if (group) {
10282
- let goodDerivedGroupTarget = up.fragment.tryToTarget(group);
10741
+ let strongDerivedGroupTarget = up.fragment.tryToTarget(group, { strong: true });
10283
10742
  let goodDerivedFieldTarget = up.fragment.tryToTarget(field);
10284
10743
  let groupHasFieldTarget = goodDerivedFieldTarget && (group !== field) && `${groupSelector}:has(${goodDerivedFieldTarget})`;
10285
- let target = goodDerivedGroupTarget || groupHasFieldTarget;
10744
+ let target = strongDerivedGroupTarget || groupHasFieldTarget;
10286
10745
  if (target) {
10287
10746
  return {
10288
10747
  target,
@@ -10374,7 +10833,7 @@ up.form = (function () {
10374
10833
  target.classList.add('up-switched');
10375
10834
  });
10376
10835
  function parseSwitchTokens(str) {
10377
- return u.parseTokens(str, { json: true });
10836
+ return u.getSimpleTokens(str, { json: true });
10378
10837
  }
10379
10838
  function findSwitcherForTarget(target) {
10380
10839
  const form = getScope(target);
@@ -10442,8 +10901,8 @@ up.form = (function () {
10442
10901
  submitButtons: findSubmitButtons,
10443
10902
  focusedField,
10444
10903
  switchTarget,
10445
- disableWhile,
10446
10904
  disable: disableContainer,
10905
+ getDisablePreviewFn,
10447
10906
  group: findGroup,
10448
10907
  groupSolution: findGroupSolution,
10449
10908
  groupSelectors: getGroupSelectors,
@@ -10461,22 +10920,24 @@ up.validate = up.form.validate;
10461
10920
  /* 98 */
10462
10921
  /***/ (() => {
10463
10922
 
10464
- up.feedback = (function () {
10923
+ up.status = (function () {
10465
10924
  const u = up.util;
10466
10925
  const e = up.element;
10926
+ let namedPreviewFns = {};
10467
10927
  const config = new up.Config(() => ({
10468
10928
  currentClasses: ['up-current'],
10929
+ activeClasses: ['up-active'],
10930
+ loadingClasses: ['up-loading'],
10469
10931
  navSelectors: ['[up-nav]', 'nav'],
10470
10932
  noNavSelectors: ['[up-nav=false]'],
10471
10933
  }));
10472
10934
  function reset() {
10473
10935
  up.layer.root.feedbackLocation = null;
10936
+ namedPreviewFns = u.pickBy(namedPreviewFns, 'isDefault');
10474
10937
  }
10475
- const CLASS_ACTIVE = 'up-active';
10476
- const CLASS_LOADING = 'up-loading';
10477
10938
  const SELECTOR_LINK = 'a, [up-href]';
10478
- function linkURLs(link) {
10479
- return link.upFeedbackURLs ||= new up.LinkFeedbackURLs(link);
10939
+ function linkCurrentURLs(link) {
10940
+ return link.upCurrentURLs ||= new up.LinkCurrentURLs(link);
10480
10941
  }
10481
10942
  function updateFragment(fragment, { layer } = {}) {
10482
10943
  layer ||= up.layer.get(fragment);
@@ -10485,11 +10946,11 @@ up.feedback = (function () {
10485
10946
  const navLinkSelector = `${navSelector} :is(${SELECTOR_LINK}), ${navSelector}:is(${SELECTOR_LINK})`;
10486
10947
  const links = up.fragment.all(navLinkSelector, { layer });
10487
10948
  for (let link of links) {
10488
- const isCurrent = linkURLs(link).isCurrent(layerLocation);
10949
+ const isCurrent = linkCurrentURLs(link).isCurrent(layerLocation);
10489
10950
  for (let currentClass of config.currentClasses) {
10490
10951
  link.classList.toggle(currentClass, isCurrent);
10491
10952
  }
10492
- e.toggleAttr(link, 'aria-current', 'page', isCurrent);
10953
+ e.setAttrPresence(link, 'aria-current', 'page', isCurrent);
10493
10954
  }
10494
10955
  }
10495
10956
  function getMatchableLayerLocation(layer) {
@@ -10498,24 +10959,88 @@ up.feedback = (function () {
10498
10959
  function findActivatableArea(element) {
10499
10960
  return e.ancestor(element, SELECTOR_LINK) || element;
10500
10961
  }
10501
- function showAroundRequest(request, options) {
10502
- if (!options.feedback) {
10962
+ function runPreviews(request, renderOptions) {
10963
+ let { bindLayer } = request;
10964
+ let focusCapsule = up.FocusCapsule.preserve(bindLayer);
10965
+ let applyPreviews = () => doRunPreviews(request, renderOptions);
10966
+ let revertPreviews = bindLayer.asCurrent(applyPreviews);
10967
+ up.on('focusin', { once: true }, () => focusCapsule = null);
10968
+ return () => {
10969
+ bindLayer.asCurrent(revertPreviews);
10970
+ focusCapsule?.restore(bindLayer, { preventScroll: true });
10971
+ };
10972
+ }
10973
+ function doRunPreviews(request, renderOptions) {
10974
+ let { fragment, fragments, origin } = request;
10975
+ let cleaner = u.cleaner();
10976
+ let previewForFragment = (fragment) => new up.Preview({ fragment, request, renderOptions, cleaner });
10977
+ let singlePreview = previewForFragment(fragment);
10978
+ singlePreview.run(resolvePreviewFns(renderOptions.preview));
10979
+ singlePreview.run(getPlaceholderPreviewFn(renderOptions.placeholder));
10980
+ singlePreview.run(getFeedbackClassesPreviewFn(renderOptions.feedback, fragments));
10981
+ singlePreview.run(up.form.getDisablePreviewFn(renderOptions.disable, origin));
10982
+ for (let fragment of fragments) {
10983
+ let eachPreview = previewForFragment(fragment);
10984
+ eachPreview.run(e.matchSelectorMap(renderOptions.previewMap, fragment));
10985
+ eachPreview.run(e.matchSelectorMap(renderOptions.placeholderMap, fragment).flatMap(getPlaceholderPreviewFn));
10986
+ }
10987
+ return cleaner.clean;
10988
+ }
10989
+ function getPlaceholderPreviewFn(placeholder) {
10990
+ if (!placeholder)
10503
10991
  return;
10992
+ return function (preview) {
10993
+ preview.showPlaceholder(placeholder);
10994
+ };
10995
+ }
10996
+ function resolvePreviewFns(value) {
10997
+ if (u.isFunction(value)) {
10998
+ return [value];
10999
+ }
11000
+ else if (u.isString(value)) {
11001
+ return resolvePreviewString(value);
10504
11002
  }
10505
- let clean = (fn) => u.always(request, fn);
10506
- let activeElement = getActiveElementFromRenderOptions(request);
10507
- if (activeElement) {
10508
- clean(e.addTemporaryClass(activeElement, CLASS_ACTIVE));
11003
+ else if (u.isArray(value)) {
11004
+ return value.flatMap(resolvePreviewFns);
10509
11005
  }
10510
- for (let fragment of request.fragments) {
10511
- clean(e.addTemporaryClass(fragment, CLASS_LOADING));
11006
+ else {
11007
+ return [];
10512
11008
  }
10513
11009
  }
10514
- function getActiveElementFromRenderOptions(request) {
10515
- let activeElement = request.origin;
10516
- if (activeElement) {
10517
- return findActivatableArea(activeElement);
10518
- }
11010
+ function resolvePreviewString(str) {
11011
+ return u.map(u.parseScalarJSONPairs(str), ([name, parsedOptions]) => {
11012
+ let previewFn = namedPreviewFns[name] || up.fail('Unknown preview "%s"', name);
11013
+ return function (preview, runOptions) {
11014
+ up.puts('[up-preview]', 'Showing preview %o', name);
11015
+ return previewFn(preview, parsedOptions || runOptions);
11016
+ };
11017
+ });
11018
+ }
11019
+ function getActiveElements({ origin, activeElements }) {
11020
+ activeElements ||= u.wrapList(origin);
11021
+ return activeElements.map(findActivatableArea);
11022
+ }
11023
+ function registerPreview(name, previewFn) {
11024
+ previewFn.isDefault = up.framework.evaling;
11025
+ namedPreviewFns[name] = previewFn;
11026
+ }
11027
+ function getFeedbackClassesPreviewFn(feedbackOption, fragments) {
11028
+ if (!feedbackOption)
11029
+ return;
11030
+ return function (preview) {
11031
+ preview.addClassBatch(getActiveElements(preview.renderOptions), config.activeClasses);
11032
+ preview.addClassBatch(fragments, config.loadingClasses);
11033
+ };
11034
+ }
11035
+ function statusOptions(element, options, parserOptions) {
11036
+ options = u.options(options);
11037
+ const parser = new up.OptionsParser(element, options, parserOptions);
11038
+ parser.booleanOrString('disable');
11039
+ parser.boolean('feedback');
11040
+ parser.string('preview');
11041
+ parser.booleanOrString('revalidatePreview');
11042
+ parser.string('placeholder');
11043
+ return options;
10519
11044
  }
10520
11045
  function updateLayerIfLocationChanged(layer) {
10521
11046
  const processedLocation = layer.feedbackLocation;
@@ -10543,9 +11068,13 @@ up.feedback = (function () {
10543
11068
  up.on('up:framework:reset', reset);
10544
11069
  return {
10545
11070
  config,
10546
- showAroundRequest,
11071
+ preview: registerPreview,
11072
+ resolvePreviewFns,
11073
+ runPreviews,
11074
+ statusOptions,
10547
11075
  };
10548
11076
  })();
11077
+ up.preview = up.status.preview;
10549
11078
 
10550
11079
 
10551
11080
  /***/ }),
@@ -10560,9 +11089,9 @@ up.radio = (function () {
10560
11089
  pollInterval: 30000,
10561
11090
  }));
10562
11091
  function hungrySteps(renderOptions) {
10563
- let { useHungry, origin, layer: renderLayer } = renderOptions;
11092
+ let { hungry, origin, layer: renderLayer, meta } = renderOptions;
10564
11093
  let steps = { current: [], other: [] };
10565
- if (!useHungry)
11094
+ if (!hungry)
10566
11095
  return steps;
10567
11096
  let hungrySelector = config.selector('hungrySelectors');
10568
11097
  const layerPreference = [renderLayer, ...renderLayer.ancestors, ...renderLayer.descendants];
@@ -10586,8 +11115,9 @@ up.radio = (function () {
10586
11115
  origin,
10587
11116
  ...motionOptions,
10588
11117
  placement: 'swap',
10589
- useKeep: true,
11118
+ keep: true,
10590
11119
  maybe: true,
11120
+ meta,
10591
11121
  selectEvent,
10592
11122
  selectCallback,
10593
11123
  originalRenderOptions: renderOptions,
@@ -10613,6 +11143,7 @@ up.radio = (function () {
10613
11143
  parser.number('interval', { default: config.pollInterval });
10614
11144
  parser.string('ifLayer', { default: 'front' });
10615
11145
  parser.include(up.link.requestOptions);
11146
+ parser.include(up.status.statusOptions);
10616
11147
  return options;
10617
11148
  }
10618
11149
  up.attribute('up-poll', function (fragment) {