unpoly-rails 3.9.5 → 3.10.0.rc1

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