unpoly-rails 3.9.5 → 3.10.0

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