@jsenv/navi 0.29.152 → 0.29.153

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.
@@ -5354,6 +5354,26 @@ const extractMessageAndRemainingProps = (props) => {
5354
5354
  return [ownMessages, remaining];
5355
5355
  };
5356
5356
 
5357
+ /**
5358
+ * The one-line form of a constraint message, or `undefined` when it has none.
5359
+ *
5360
+ * A message is not always a sentence: it can be an `Error`, or a whole element
5361
+ * (an `errorMapping` returning JSX to put a link inside the callout). Those
5362
+ * still render fine in the callout, but they have no one-line form, and
5363
+ * anything that needs one — a `title` attribute, a caller drawing its own
5364
+ * summary — must be given nothing rather than `String(message)`, which writes
5365
+ * "[object Object]" on the screen.
5366
+ */
5367
+ const getMessageString = (message) => {
5368
+ if (typeof message === "string") {
5369
+ return message;
5370
+ }
5371
+ if (Error.isError(message)) {
5372
+ return message.message;
5373
+ }
5374
+ return undefined;
5375
+ };
5376
+
5357
5377
  const getConstraintMessage = (
5358
5378
  controller,
5359
5379
  constraint,
@@ -12147,7 +12167,9 @@ const createControlValidation = (
12147
12167
  typeof checkResult === "string"
12148
12168
  ? { message: checkResult }
12149
12169
  : checkResult;
12150
- constraintValidityInfo.messageString = constraintValidityInfo.message;
12170
+ constraintValidityInfo.messageString = getMessageString(
12171
+ constraintValidityInfo.message,
12172
+ );
12151
12173
  debugUIState(
12152
12174
  `${elementSig} constraint "${constraint.name}" failed -> ${constraintValidityInfo.message}`,
12153
12175
  );
@@ -12189,10 +12211,15 @@ const createControlValidation = (
12189
12211
  if (titleLess) {
12190
12212
  const element = controller.ref.current;
12191
12213
  if (element) {
12192
- element.setAttribute(
12193
- "title",
12194
- activeFailedConstraintInfo.messageString,
12195
- );
12214
+ const { messageString } = activeFailedConstraintInfo;
12215
+ if (messageString) {
12216
+ element.setAttribute("title", messageString);
12217
+ } else {
12218
+ // The message has no one-line form (an element, typically): the
12219
+ // callout shows it whole, and the tooltip stays empty rather than
12220
+ // saying "[object Object]".
12221
+ element.removeAttribute("title");
12222
+ }
12196
12223
  }
12197
12224
  }
12198
12225
  } else {
@@ -12589,6 +12616,13 @@ const useExecuteAction = (
12589
12616
  let message;
12590
12617
  if (errorMapping) {
12591
12618
  const errorMappingResult = errorMapping(error);
12619
+ // Anything the chain below does not recognize — nothing returned, above
12620
+ // all — leaves `message` undefined and the control displays nothing. That
12621
+ // is the contract, and both halves of it are useful:
12622
+ // - returning nothing says "don't show this one", per error, where
12623
+ // actionErrorEffect="none" says it once for the whole control;
12624
+ // - not handling an error means returning it untouched (`return error`),
12625
+ // and it is then shown exactly as if there were no mapping at all.
12592
12626
  if (typeof errorMappingResult === "string") {
12593
12627
  message = errorMappingResult;
12594
12628
  } else if (Error.isError(errorMappingResult)) {