@jsenv/navi 0.20.14 → 0.20.16

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.
@@ -1,4 +1,4 @@
1
- import { installImportMetaCss } from "./jsenv_navi_side_effects.js";
1
+ import { installImportMetaCssBuild } from "./jsenv_navi_side_effects.js";
2
2
  import { isValidElement, h, createContext, toChildArray, render, createRef, cloneElement } from "preact";
3
3
  import { useErrorBoundary, useLayoutEffect, useEffect, useMemo, useRef, useState, useCallback, useContext, useImperativeHandle, useId } from "preact/hooks";
4
4
  import { jsxs, jsx, Fragment } from "preact/jsx-runtime";
@@ -71,7 +71,7 @@ const useActionStatus = (action) => {
71
71
  };
72
72
  };
73
73
 
74
- installImportMetaCss(import.meta);import.meta.css = /* css */`
74
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
75
75
  .action_error {
76
76
  margin-top: 0;
77
77
  margin-bottom: 20px;
@@ -79,7 +79,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
79
79
  background: #fdd;
80
80
  border: 1px solid red;
81
81
  }
82
- `;
82
+ `, "/src/action/action_renderer.jsx"];
83
83
  const renderIdleDefault = () => null;
84
84
  const renderLoadingDefault = () => null;
85
85
  const renderAbortedDefault = () => null;
@@ -7449,7 +7449,32 @@ const updateStyle = (element, style, preventInitialTransition) => {
7449
7449
  styleKeySetWeakMap.set(element, styleKeySet);
7450
7450
  };
7451
7451
 
7452
- installImportMetaCss(import.meta);import.meta.css = /* css */`
7452
+ installImportMetaCssBuild(import.meta);/**
7453
+ * Box - A Swiss Army Knife for Layout
7454
+ *
7455
+ * A regular div by default, enhanced with styling props for spacing, sizing,
7456
+ * and layout. The main value is a friendlier API over raw CSS Flexbox.
7457
+ *
7458
+ * ## Display & Layout
7459
+ *
7460
+ * - `flex` — horizontal flex container (items side by side)
7461
+ * - `flex="y"` — vertical flex container (items stacked). The prop name makes
7462
+ * the axis explicit, avoiding the classic CSS trap where `flex-direction: column`
7463
+ * actually stacks items vertically despite "column" feeling horizontal.
7464
+ * - `grid` — grid container
7465
+ * - `inline` — switches to inline display (works with flex and grid too)
7466
+ *
7467
+ * ## Alignment
7468
+ *
7469
+ * Instead of CSS's justify-content/align-items which swap meaning based on flex-direction:
7470
+ * - `alignX` — horizontal alignment, always
7471
+ * - `alignY` — vertical alignment, always
7472
+ *
7473
+ * ## Spacing & Sizing
7474
+ *
7475
+ * Props for margin, padding, gap, width, height, expand, shrink, and more.
7476
+ */
7477
+ import.meta.css = [/* css */`
7453
7478
  [navi-box-flow="inline"] {
7454
7479
  display: inline;
7455
7480
  }
@@ -7497,7 +7522,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
7497
7522
  grid-auto-flow: unset;
7498
7523
  }
7499
7524
  }
7500
- `;
7525
+ `, "/src/box/box.jsx"];
7501
7526
  const PSEUDO_CLASSES_DEFAULT = [];
7502
7527
  const PSEUDO_ELEMENTS_DEFAULT = [];
7503
7528
  const STYLE_CSS_VARS_DEFAULT = {};
@@ -8041,8 +8066,68 @@ const monitorItemsOverflow = (container) => {
8041
8066
  return destroy;
8042
8067
  };
8043
8068
 
8044
- installImportMetaCss(import.meta);
8045
- import.meta.css = /* css */ `
8069
+ installImportMetaCssBuild(import.meta);/**
8070
+ * UI Transition - Core Implementation
8071
+ * Provides smooth resize transitions with cross-fade effects between content states
8072
+ *
8073
+ * Content Types and Terminology:
8074
+ *
8075
+ * - ui: What the user currently sees rendered in the UI
8076
+ * - dom_nodes: The actual DOM elements that make up the visual representation
8077
+ * - content_id: Unique identifier for a content and its content_phase(s)
8078
+ * - content_phase: Intermediate states (loading spinners, error messages, empty states)
8079
+ * - content: The primary/final content we want to display (e.g., car details, user profile)
8080
+ *
8081
+ * Required HTML structure:
8082
+ *
8083
+ * <div class="ui_transition">
8084
+ * <div class="ui_transition_active_group">
8085
+ * <div class="ui_transition_target_slot"></div>
8086
+ * <div class="ui_transition_outgoing_slot"></div>
8087
+ * </div>
8088
+ * <div class="ui_transition_previous_group">
8089
+ * <div class="ui_transition_previous_target_slot"></div>
8090
+ * <div class="ui_transition_previous_outgoing_slot"></div>
8091
+ * </div>
8092
+ * </div>
8093
+ *
8094
+ * Architecture Overview:
8095
+ *
8096
+ * .ui_transition
8097
+ * The main container that handles dimensional transitions. Its width and height animate
8098
+ * smoothly from current to target dimensions. Has overflow:hidden to clip ui during transitions.
8099
+ *
8100
+ * .active_group
8101
+ * Contains the ui that should be active after the transition completes. Groups both the target
8102
+ * ui (.target_slot) and transitional ui (.outgoing_slot) as a single unit that can
8103
+ * be manipulated together (e.g., applying transforms or slides).
8104
+ *
8105
+ * .target_slot
8106
+ * Always contains the target ui - what should be displayed at the end of the transition.
8107
+ * Whether transitioning to content or content_phase, this slot receives the new dom_nodes.
8108
+ * Receives fade-in transitions (opacity 0 → 1) during all transition types.
8109
+ *
8110
+ * .outgoing_slot
8111
+ * Holds content_phase that's being replaced during content_phase transitions. When transitioning
8112
+ * from one content_phase to another, or from content_phase to content, the old content_phase moves
8113
+ * here for fade-out. Receives fade-out transitions (opacity 1 → 0).
8114
+ *
8115
+ * .previous_group
8116
+ * Used for content-to-content transitions. When switching between content (not phases),
8117
+ * the entire .active_group dom_nodes are cloned here to fade out while the new content fades in.
8118
+ * Can slide out when sliding transitions are enabled, otherwise fades out.
8119
+ *
8120
+ * Transition Scenarios:
8121
+ * - content → content: Car A details → Car B details (clone to previous_group)
8122
+ * - content_phase → content_phase: Loading state → Error state (move to outgoing_slot, same content_id)
8123
+ * - content → content_phase: Car A details → Loading Car B (use outgoing_slot for cross-fade)
8124
+ * - content_phase → content: Loading Car B → Car B details (use outgoing_slot for cross-fade)
8125
+ *
8126
+ * Size Transition Handling:
8127
+ * During dimensional transitions, both .target_slot and .outgoing_slot have their dimensions
8128
+ * explicitly set to prevent dom_nodes reflow and maintain visual consistency.
8129
+ */
8130
+ import.meta.css = [/* css */`
8046
8131
  * {
8047
8132
  box-sizing: border-box;
8048
8133
  }
@@ -8144,74 +8229,51 @@ import.meta.css = /* css */ `
8144
8229
  .ui_transition[data-transitioning] .ui_transition_target_slot_background {
8145
8230
  display: block;
8146
8231
  }
8147
- `;
8148
-
8232
+ `, "/src/ui_transition/ui_transition.js"];
8149
8233
  const CONTENT_ID_ATTRIBUTE = "data-content-id";
8150
8234
  const CONTENT_PHASE_ATTRIBUTE = "data-content-phase";
8151
8235
  const UNSET = {
8152
8236
  domNodes: [],
8153
8237
  domNodesClone: [],
8154
8238
  isEmpty: true,
8155
-
8156
8239
  type: "unset",
8157
8240
  contentId: "unset",
8158
8241
  contentPhase: undefined,
8159
8242
  isContentPhase: false,
8160
8243
  isContent: false,
8161
- toString: () => "unset",
8244
+ toString: () => "unset"
8162
8245
  };
8163
-
8164
8246
  const isSameConfiguration = (configA, configB) => {
8165
8247
  return configA.toString() === configB.toString();
8166
8248
  };
8167
-
8168
- const createUITransitionController = (
8169
- root,
8170
- {
8171
- duration = 300,
8172
- alignX = "center",
8173
- alignY = "center",
8174
- onStateChange = () => {},
8175
- pauseBreakpoints = [],
8176
- } = {},
8177
- ) => {
8249
+ const createUITransitionController = (root, {
8250
+ duration = 300,
8251
+ alignX = "center",
8252
+ alignY = "center",
8253
+ onStateChange = () => {},
8254
+ pauseBreakpoints = []
8255
+ } = {}) => {
8178
8256
  const debugConfig = {
8179
8257
  detection: root.hasAttribute("data-debug-detection"),
8180
- size: root.hasAttribute("data-debug-size"),
8258
+ size: root.hasAttribute("data-debug-size")
8181
8259
  };
8182
8260
  const hasDebugLogs = debugConfig.size;
8183
- const debugDetection = (message) => {
8261
+ const debugDetection = message => {
8184
8262
  if (!debugConfig.detection) return;
8185
8263
  console.debug(`[detection]`, message);
8186
8264
  };
8187
- const debugSize = (message) => {
8265
+ const debugSize = message => {
8188
8266
  if (!debugConfig.size) return;
8189
8267
  console.debug(`[size]`, message);
8190
8268
  };
8191
-
8192
8269
  const activeGroup = root.querySelector(".ui_transition_active_group");
8193
8270
  const targetSlot = root.querySelector(".ui_transition_target_slot");
8194
8271
  const outgoingSlot = root.querySelector(".ui_transition_outgoing_slot");
8195
8272
  const previousGroup = root.querySelector(".ui_transition_previous_group");
8196
- const previousTargetSlot = previousGroup?.querySelector(
8197
- ".ui_transition_previous_target_slot",
8198
- );
8199
- const previousOutgoingSlot = previousGroup?.querySelector(
8200
- ".ui_transition_previous_outgoing_slot",
8201
- );
8202
-
8203
- if (
8204
- !root ||
8205
- !activeGroup ||
8206
- !targetSlot ||
8207
- !outgoingSlot ||
8208
- !previousGroup ||
8209
- !previousTargetSlot ||
8210
- !previousOutgoingSlot
8211
- ) {
8212
- throw new Error(
8213
- "createUITransitionController requires element with .active_group, .target_slot, .outgoing_slot, .previous_group, .previous_target_slot, and .previous_outgoing_slot elements",
8214
- );
8273
+ const previousTargetSlot = previousGroup?.querySelector(".ui_transition_previous_target_slot");
8274
+ const previousOutgoingSlot = previousGroup?.querySelector(".ui_transition_previous_outgoing_slot");
8275
+ if (!root || !activeGroup || !targetSlot || !outgoingSlot || !previousGroup || !previousTargetSlot || !previousOutgoingSlot) {
8276
+ throw new Error("createUITransitionController requires element with .active_group, .target_slot, .outgoing_slot, .previous_group, .previous_target_slot, and .previous_outgoing_slot elements");
8215
8277
  }
8216
8278
 
8217
8279
  // we maintain a background copy behind target slot to avoid showing
@@ -8219,17 +8281,17 @@ const createUITransitionController = (
8219
8281
  const targetSlotBackground = document.createElement("div");
8220
8282
  targetSlotBackground.className = "ui_transition_target_slot_background";
8221
8283
  activeGroup.insertBefore(targetSlotBackground, targetSlot);
8222
-
8223
8284
  root.style.setProperty("--x-transition-duration", `${duration}ms`);
8224
8285
  outgoingSlot.setAttribute("inert", "");
8225
8286
  previousGroup.setAttribute("inert", "");
8226
-
8227
- const detectConfiguration = (slot, { contentId, contentPhase } = {}) => {
8287
+ const detectConfiguration = (slot, {
8288
+ contentId,
8289
+ contentPhase
8290
+ } = {}) => {
8228
8291
  const domNodes = Array.from(slot.childNodes);
8229
8292
  if (!domNodes) {
8230
8293
  return UNSET;
8231
8294
  }
8232
-
8233
8295
  const isEmpty = domNodes.length === 0;
8234
8296
  let textNodeCount = 0;
8235
8297
  let elementNodeCount = 0;
@@ -8250,7 +8312,6 @@ const createUITransitionController = (
8250
8312
  firstElementNode = domNode;
8251
8313
  }
8252
8314
  elementNodeCount++;
8253
-
8254
8315
  if (domNode.hasAttribute("data-content-phase")) {
8255
8316
  const contentPhaseAttr = domNode.getAttribute("data-content-phase");
8256
8317
  contentPhase = contentPhaseAttr || "attr";
@@ -8262,11 +8323,8 @@ const createUITransitionController = (
8262
8323
  const domNodeClone = domNode.cloneNode(true);
8263
8324
  domNodesClone.push(domNodeClone);
8264
8325
  }
8265
-
8266
8326
  if (contentIdSlotAttr && contentIdChildAttr) {
8267
- console.warn(
8268
- `Slot and slot child both have a [${CONTENT_ID_ATTRIBUTE}]. Slot is ${contentIdSlotAttr} and child is ${contentIdChildAttr}, using the child.`,
8269
- );
8327
+ console.warn(`Slot and slot child both have a [${CONTENT_ID_ATTRIBUTE}]. Slot is ${contentIdSlotAttr} and child is ${contentIdChildAttr}, using the child.`);
8270
8328
  }
8271
8329
  if (contentId === undefined) {
8272
8330
  contentId = contentIdChildAttr || contentIdSlotAttr || undefined;
@@ -8274,7 +8332,6 @@ const createUITransitionController = (
8274
8332
  }
8275
8333
  const isOnlyTextNodes = elementNodeCount === 0 && textNodeCount > 1;
8276
8334
  const singleElementNode = elementNodeCount === 1 ? firstElementNode : null;
8277
-
8278
8335
  contentId = contentId || getElementSignature(domNodes[0]);
8279
8336
  if (!contentPhase && isEmpty) {
8280
8337
  // Imagine code rendering null while switching to a new content
@@ -8285,22 +8342,16 @@ const createUITransitionController = (
8285
8342
  // intermediate states.
8286
8343
  contentPhase = "empty";
8287
8344
  }
8288
-
8289
8345
  let width;
8290
8346
  let height;
8291
8347
  let borderRadius;
8292
8348
  let border;
8293
8349
  let background;
8294
-
8295
8350
  if (isEmpty) {
8296
8351
  debugSize(`measureSlot(".${slot.className}") -> it is empty`);
8297
8352
  } else if (singleElementNode) {
8298
- const visualSelector = singleElementNode.getAttribute(
8299
- "data-visual-selector",
8300
- );
8301
- const visualElement = visualSelector
8302
- ? singleElementNode.querySelector(visualSelector) || singleElementNode
8303
- : singleElementNode;
8353
+ const visualSelector = singleElementNode.getAttribute("data-visual-selector");
8354
+ const visualElement = visualSelector ? singleElementNode.querySelector(visualSelector) || singleElementNode : singleElementNode;
8304
8355
  const rect = visualElement.getBoundingClientRect();
8305
8356
  width = rect.width;
8306
8357
  height = rect.height;
@@ -8315,23 +8366,19 @@ const createUITransitionController = (
8315
8366
  height = rect.height;
8316
8367
  debugSize(`measureSlot(".${slot.className}") -> [${width}x${height}]`);
8317
8368
  }
8318
-
8319
8369
  const commonProperties = {
8320
8370
  domNodes,
8321
8371
  domNodesClone,
8322
8372
  isEmpty,
8323
8373
  isOnlyTextNodes,
8324
8374
  singleElementNode,
8325
-
8326
8375
  width,
8327
8376
  height,
8328
8377
  borderRadius,
8329
8378
  border,
8330
8379
  background,
8331
-
8332
- contentId,
8380
+ contentId
8333
8381
  };
8334
-
8335
8382
  if (contentPhase) {
8336
8383
  return {
8337
8384
  ...commonProperties,
@@ -8339,7 +8386,7 @@ const createUITransitionController = (
8339
8386
  contentPhase,
8340
8387
  isContentPhase: true,
8341
8388
  isContent: false,
8342
- toString: () => `content(${contentId}).phase(${contentPhase})`,
8389
+ toString: () => `content(${contentId}).phase(${contentPhase})`
8343
8390
  };
8344
8391
  }
8345
8392
  return {
@@ -8348,18 +8395,16 @@ const createUITransitionController = (
8348
8395
  contentPhase: undefined,
8349
8396
  isContentPhase: false,
8350
8397
  isContent: true,
8351
- toString: () => `content(${contentId})`,
8398
+ toString: () => `content(${contentId})`
8352
8399
  };
8353
8400
  };
8354
-
8355
8401
  const targetSlotInitialConfiguration = detectConfiguration(targetSlot);
8356
8402
  const outgoingSlotInitialConfiguration = detectConfiguration(outgoingSlot, {
8357
- contentPhase: "true",
8403
+ contentPhase: "true"
8358
8404
  });
8359
8405
  let targetSlotConfiguration = targetSlotInitialConfiguration;
8360
8406
  let outgoingSlotConfiguration = outgoingSlotInitialConfiguration;
8361
8407
  let previousTargetSlotConfiguration = UNSET;
8362
-
8363
8408
  const updateSlotAttributes = () => {
8364
8409
  if (targetSlotConfiguration.isEmpty && outgoingSlotConfiguration.isEmpty) {
8365
8410
  root.setAttribute("data-only-previous-group", "");
@@ -8372,7 +8417,6 @@ const createUITransitionController = (
8372
8417
  root.setAttribute("data-align-x", alignX);
8373
8418
  root.setAttribute("data-align-y", alignY);
8374
8419
  };
8375
-
8376
8420
  const moveConfigurationIntoSlot = (configuration, slot) => {
8377
8421
  slot.innerHTML = "";
8378
8422
  for (const domNode of configuration.domNodesClone) {
@@ -8390,9 +8434,7 @@ const createUITransitionController = (
8390
8434
  throw new Error("Unknown slot for applyConfiguration");
8391
8435
  }
8392
8436
  };
8393
-
8394
8437
  updateAlignment();
8395
-
8396
8438
  let transitionType = "none";
8397
8439
  const groupTransitionOptions = {
8398
8440
  // debugBreakpoints: [0.25],
@@ -8401,21 +8443,22 @@ const createUITransitionController = (
8401
8443
  setup: () => {
8402
8444
  updateSlotAttributes();
8403
8445
  root.setAttribute("data-transitioning", "");
8404
- onStateChange({ isTransitioning: true });
8446
+ onStateChange({
8447
+ isTransitioning: true
8448
+ });
8405
8449
  return {
8406
8450
  teardown: () => {
8407
8451
  root.removeAttribute("data-transitioning");
8408
8452
  updateSlotAttributes(); // Update positioning after transition
8409
- onStateChange({ isTransitioning: false });
8410
- },
8453
+ onStateChange({
8454
+ isTransitioning: false
8455
+ });
8456
+ }
8411
8457
  };
8412
- },
8413
- },
8458
+ }
8459
+ }
8414
8460
  };
8415
- const transitionController = createGroupTransitionController(
8416
- groupTransitionOptions,
8417
- );
8418
-
8461
+ const transitionController = createGroupTransitionController(groupTransitionOptions);
8419
8462
  const elementToClip = root;
8420
8463
  const morphContainerIntoTarget = () => {
8421
8464
  const morphTransitions = [];
@@ -8429,31 +8472,28 @@ const createUITransitionController = (
8429
8472
  const fromHeight = previousTargetSlotConfiguration.height || 0;
8430
8473
  const toWidth = targetSlotConfiguration.width || 0;
8431
8474
  const toHeight = targetSlotConfiguration.height || 0;
8432
- debugSize(
8433
- `transition from [${fromWidth}x${fromHeight}] to [${toWidth}x${toHeight}]`,
8434
- );
8475
+ debugSize(`transition from [${fromWidth}x${fromHeight}] to [${toWidth}x${toHeight}]`);
8435
8476
  const restoreOverflow = preventIntermediateScrollbar(root, {
8436
8477
  fromWidth,
8437
8478
  fromHeight,
8438
8479
  toWidth,
8439
8480
  toHeight,
8440
- onPrevent: ({ x, y, scrollContainer }) => {
8481
+ onPrevent: ({
8482
+ x,
8483
+ y,
8484
+ scrollContainer
8485
+ }) => {
8441
8486
  if (x) {
8442
- debugSize(
8443
- `Temporarily hiding horizontal overflow during transition on ${getElementSignature(scrollContainer)}`,
8444
- );
8487
+ debugSize(`Temporarily hiding horizontal overflow during transition on ${getElementSignature(scrollContainer)}`);
8445
8488
  }
8446
8489
  if (y) {
8447
- debugSize(
8448
- `Temporarily hiding vertical overflow during transition on ${getElementSignature(scrollContainer)}`,
8449
- );
8490
+ debugSize(`Temporarily hiding vertical overflow during transition on ${getElementSignature(scrollContainer)}`);
8450
8491
  }
8451
8492
  },
8452
8493
  onRestore: () => {
8453
8494
  debugSize(`Restored overflow after transition`);
8454
- },
8495
+ }
8455
8496
  });
8456
-
8457
8497
  const onSizeTransitionFinished = () => {
8458
8498
  // Restore overflow when transition is complete
8459
8499
  restoreOverflow();
@@ -8476,95 +8516,63 @@ const createUITransitionController = (
8476
8516
  }
8477
8517
  };
8478
8518
  // Position of "from" content within large container
8479
- const fromLeft = getAlignedPosition(
8480
- elementToClipWidth,
8481
- fromWidth,
8482
- alignX,
8483
- );
8484
- const fromTop = getAlignedPosition(
8485
- elementToClipHeight,
8486
- fromHeight,
8487
- alignY,
8488
- );
8519
+ const fromLeft = getAlignedPosition(elementToClipWidth, fromWidth, alignX);
8520
+ const fromTop = getAlignedPosition(elementToClipHeight, fromHeight, alignY);
8489
8521
  // Position of target content within large container
8490
- const targetLeft = getAlignedPosition(
8491
- elementToClipWidth,
8492
- toWidth,
8493
- alignX,
8494
- );
8495
- const targetTop = getAlignedPosition(
8496
- elementToClipHeight,
8497
- toHeight,
8498
- alignY,
8499
- );
8500
- debugSize(
8501
- `Positions in container: from [${fromLeft},${fromTop}] ${fromWidth}x${fromHeight} to [${targetLeft},${targetTop}] ${toWidth}x${toHeight}`,
8502
- );
8522
+ const targetLeft = getAlignedPosition(elementToClipWidth, toWidth, alignX);
8523
+ const targetTop = getAlignedPosition(elementToClipHeight, toHeight, alignY);
8524
+ debugSize(`Positions in container: from [${fromLeft},${fromTop}] ${fromWidth}x${fromHeight} to [${targetLeft},${targetTop}] ${toWidth}x${toHeight}`);
8503
8525
  // Get border-radius values
8504
- const fromBorderRadius =
8505
- previousTargetSlotConfiguration.borderRadius || 0;
8526
+ const fromBorderRadius = previousTargetSlotConfiguration.borderRadius || 0;
8506
8527
  const toBorderRadius = targetSlotConfiguration.borderRadius || 0;
8507
8528
  const startInsetTop = fromTop;
8508
8529
  const startInsetRight = elementToClipWidth - (fromLeft + fromWidth);
8509
8530
  const startInsetBottom = elementToClipHeight - (fromTop + fromHeight);
8510
8531
  const startInsetLeft = fromLeft;
8511
-
8512
8532
  const endInsetTop = targetTop;
8513
8533
  const endInsetRight = elementToClipWidth - (targetLeft + toWidth);
8514
8534
  const endInsetBottom = elementToClipHeight - (targetTop + toHeight);
8515
8535
  const endInsetLeft = targetLeft;
8516
-
8517
8536
  const startClipPath = `inset(${startInsetTop}px ${startInsetRight}px ${startInsetBottom}px ${startInsetLeft}px round ${fromBorderRadius}px)`;
8518
8537
  const endClipPath = `inset(${endInsetTop}px ${endInsetRight}px ${endInsetBottom}px ${endInsetLeft}px round ${toBorderRadius}px)`;
8519
8538
  // Create clip-path animation using Web Animations API
8520
- const clipAnimation = elementToClip.animate(
8521
- [{ clipPath: startClipPath }, { clipPath: endClipPath }],
8522
- {
8523
- duration,
8524
- easing: "ease",
8525
- fill: "forwards",
8526
- },
8527
- );
8539
+ const clipAnimation = elementToClip.animate([{
8540
+ clipPath: startClipPath
8541
+ }, {
8542
+ clipPath: endClipPath
8543
+ }], {
8544
+ duration,
8545
+ easing: "ease",
8546
+ fill: "forwards"
8547
+ });
8528
8548
 
8529
8549
  // Handle finish
8530
- clipAnimation.finished
8531
- .then(() => {
8532
- // Clear clip-path to restore normal behavior
8533
- elementToClip.style.clipPath = "";
8534
- clipAnimation.cancel();
8535
- onSizeTransitionFinished();
8536
- })
8537
- .catch(() => {
8538
- // Animation was cancelled
8539
- });
8550
+ clipAnimation.finished.then(() => {
8551
+ // Clear clip-path to restore normal behavior
8552
+ elementToClip.style.clipPath = "";
8553
+ clipAnimation.cancel();
8554
+ onSizeTransitionFinished();
8555
+ }).catch(() => {
8556
+ // Animation was cancelled
8557
+ });
8540
8558
  clipAnimation.play();
8541
8559
  }
8542
-
8543
8560
  return morphTransitions;
8544
8561
  };
8545
8562
  const fadeInTargetSlot = () => {
8546
- targetSlotBackground.style.setProperty(
8547
- "--target-slot-background",
8548
- targetSlotConfiguration.background,
8549
- );
8550
- targetSlotBackground.style.setProperty(
8551
- "--target-slot-width",
8552
- `${targetSlotConfiguration.width || 0}px`,
8553
- );
8554
- targetSlotBackground.style.setProperty(
8555
- "--target-slot-height",
8556
- `${targetSlotConfiguration.height || 0}px`,
8557
- );
8563
+ targetSlotBackground.style.setProperty("--target-slot-background", targetSlotConfiguration.background);
8564
+ targetSlotBackground.style.setProperty("--target-slot-width", `${targetSlotConfiguration.width || 0}px`);
8565
+ targetSlotBackground.style.setProperty("--target-slot-height", `${targetSlotConfiguration.height || 0}px`);
8558
8566
  return createOpacityTransition(targetSlot, 1, {
8559
8567
  from: 0,
8560
8568
  duration,
8561
8569
  styleSynchronizer: "inline_style",
8562
- onFinish: (targetSlotOpacityTransition) => {
8570
+ onFinish: targetSlotOpacityTransition => {
8563
8571
  targetSlotBackground.style.removeProperty("--target-slot-background");
8564
8572
  targetSlotBackground.style.removeProperty("--target-slot-width");
8565
8573
  targetSlotBackground.style.removeProperty("--target-slot-height");
8566
8574
  targetSlotOpacityTransition.cancel();
8567
- },
8575
+ }
8568
8576
  });
8569
8577
  };
8570
8578
  const fadeOutPreviousGroup = () => {
@@ -8572,10 +8580,10 @@ const createUITransitionController = (
8572
8580
  from: 1,
8573
8581
  duration,
8574
8582
  styleSynchronizer: "inline_style",
8575
- onFinish: (previousGroupOpacityTransition) => {
8583
+ onFinish: previousGroupOpacityTransition => {
8576
8584
  previousGroupOpacityTransition.cancel();
8577
8585
  previousGroup.style.opacity = "0"; // keep previous group visually hidden
8578
- },
8586
+ }
8579
8587
  });
8580
8588
  };
8581
8589
  const fadeOutOutgoingSlot = () => {
@@ -8583,27 +8591,22 @@ const createUITransitionController = (
8583
8591
  duration,
8584
8592
  from: 1,
8585
8593
  styleSynchronizer: "inline_style",
8586
- onFinish: (outgoingSlotOpacityTransition) => {
8594
+ onFinish: outgoingSlotOpacityTransition => {
8587
8595
  outgoingSlotOpacityTransition.cancel();
8588
8596
  outgoingSlot.style.opacity = "0"; // keep outgoing slot visually hidden
8589
- },
8597
+ }
8590
8598
  });
8591
8599
  };
8592
8600
 
8593
8601
  // content_to_content transition (uses previous_group)
8594
- const applyContentToContentTransition = (toConfiguration) => {
8602
+ const applyContentToContentTransition = toConfiguration => {
8595
8603
  // 1. move target slot to previous
8596
8604
  moveConfigurationIntoSlot(targetSlotConfiguration, previousTargetSlot);
8597
8605
  targetSlotConfiguration = toConfiguration;
8598
8606
  // 2. move outgoing slot to previous
8599
8607
  moveConfigurationIntoSlot(outgoingSlotConfiguration, previousOutgoingSlot);
8600
8608
  moveConfigurationIntoSlot(UNSET, outgoingSlot);
8601
-
8602
- const transitions = [
8603
- ...morphContainerIntoTarget(),
8604
- fadeInTargetSlot(),
8605
- fadeOutPreviousGroup(),
8606
- ];
8609
+ const transitions = [...morphContainerIntoTarget(), fadeInTargetSlot(), fadeOutPreviousGroup()];
8607
8610
  const transition = transitionController.update(transitions, {
8608
8611
  onFinish: () => {
8609
8612
  moveConfigurationIntoSlot(UNSET, previousTargetSlot);
@@ -8611,29 +8614,23 @@ const createUITransitionController = (
8611
8614
  if (hasDebugLogs) {
8612
8615
  console.groupEnd();
8613
8616
  }
8614
- },
8617
+ }
8615
8618
  });
8616
8619
  transition.play();
8617
8620
  };
8618
8621
  // content_phase_to_content_phase transition (uses outgoing_slot)
8619
- const applyContentPhaseToContentPhaseTransition = (toConfiguration) => {
8622
+ const applyContentPhaseToContentPhaseTransition = toConfiguration => {
8620
8623
  // 1. Move target slot to outgoing
8621
8624
  moveConfigurationIntoSlot(targetSlotConfiguration, outgoingSlot);
8622
8625
  targetSlotConfiguration = toConfiguration;
8623
-
8624
- const transitions = [
8625
- ...morphContainerIntoTarget(),
8626
- fadeInTargetSlot(),
8627
- fadeOutOutgoingSlot(),
8628
- ];
8626
+ const transitions = [...morphContainerIntoTarget(), fadeInTargetSlot(), fadeOutOutgoingSlot()];
8629
8627
  const transition = transitionController.update(transitions, {
8630
8628
  onFinish: () => {
8631
8629
  moveConfigurationIntoSlot(UNSET, outgoingSlot);
8632
-
8633
8630
  if (hasDebugLogs) {
8634
8631
  console.groupEnd();
8635
8632
  }
8636
- },
8633
+ }
8637
8634
  });
8638
8635
  transition.play();
8639
8636
  };
@@ -8645,7 +8642,6 @@ const createUITransitionController = (
8645
8642
  // 2. move outgoing slot to previous
8646
8643
  moveConfigurationIntoSlot(outgoingSlotConfiguration, previousOutgoingSlot);
8647
8644
  outgoingSlotConfiguration = UNSET;
8648
-
8649
8645
  const transitions = [...morphContainerIntoTarget(), fadeOutPreviousGroup()];
8650
8646
  const transition = transitionController.update(transitions, {
8651
8647
  onFinish: () => {
@@ -8654,15 +8650,15 @@ const createUITransitionController = (
8654
8650
  if (hasDebugLogs) {
8655
8651
  console.groupEnd();
8656
8652
  }
8657
- },
8653
+ }
8658
8654
  });
8659
8655
  transition.play();
8660
8656
  };
8661
8657
  // Main transition method
8662
- const transitionTo = (
8663
- newContentElement,
8664
- { contentPhase, contentId } = {},
8665
- ) => {
8658
+ const transitionTo = (newContentElement, {
8659
+ contentPhase,
8660
+ contentId
8661
+ } = {}) => {
8666
8662
  if (contentId) {
8667
8663
  targetSlot.setAttribute(CONTENT_ID_ATTRIBUTE, contentId);
8668
8664
  } else {
@@ -8688,8 +8684,7 @@ const createUITransitionController = (
8688
8684
  moveConfigurationIntoSlot(UNSET, previousTargetSlot);
8689
8685
  moveConfigurationIntoSlot(UNSET, previousOutgoingSlot);
8690
8686
  };
8691
-
8692
- const targetSlotEffect = (reasons) => {
8687
+ const targetSlotEffect = reasons => {
8693
8688
  if (root.hasAttribute("data-disabled")) {
8694
8689
  return;
8695
8690
  }
@@ -8701,9 +8696,7 @@ const createUITransitionController = (
8701
8696
  console.debug(`- ${reasons.join("\n- ")}`);
8702
8697
  }
8703
8698
  if (isSameConfiguration(fromConfiguration, toConfiguration)) {
8704
- debugDetection(
8705
- `already in desired state (${toConfiguration}) -> early return`,
8706
- );
8699
+ debugDetection(`already in desired state (${toConfiguration}) -> early return`);
8707
8700
  if (hasDebugLogs) {
8708
8701
  console.groupEnd();
8709
8702
  }
@@ -8712,9 +8705,7 @@ const createUITransitionController = (
8712
8705
  const fromConfigType = fromConfiguration.type;
8713
8706
  const toConfigType = toConfiguration.type;
8714
8707
  transitionType = `${fromConfigType}_to_${toConfigType}`;
8715
- debugDetection(
8716
- `Prepare "${transitionType}" transition (${fromConfiguration} -> ${toConfiguration})`,
8717
- );
8708
+ debugDetection(`Prepare "${transitionType}" transition (${fromConfiguration} -> ${toConfiguration})`);
8718
8709
  // content_to_empty / content_phase_to_empty
8719
8710
  if (toConfiguration.isEmpty) {
8720
8711
  applyToEmptyTransition();
@@ -8738,10 +8729,9 @@ const createUITransitionController = (
8738
8729
  // content_to_content (default case)
8739
8730
  applyContentToContentTransition(toConfiguration);
8740
8731
  };
8741
-
8742
8732
  const [teardown, addTeardown] = createPubSub();
8743
8733
  {
8744
- const mutationObserver = new MutationObserver((mutations) => {
8734
+ const mutationObserver = new MutationObserver(mutations => {
8745
8735
  const reasonParts = [];
8746
8736
  for (const mutation of mutations) {
8747
8737
  if (mutation.type === "childList") {
@@ -8757,33 +8747,25 @@ const createUITransitionController = (
8757
8747
  continue;
8758
8748
  }
8759
8749
  if (mutation.type === "attributes") {
8760
- const { attributeName } = mutation;
8761
- if (
8762
- attributeName === CONTENT_ID_ATTRIBUTE ||
8763
- attributeName === CONTENT_PHASE_ATTRIBUTE
8764
- ) {
8765
- const { oldValue } = mutation;
8750
+ const {
8751
+ attributeName
8752
+ } = mutation;
8753
+ if (attributeName === CONTENT_ID_ATTRIBUTE || attributeName === CONTENT_PHASE_ATTRIBUTE) {
8754
+ const {
8755
+ oldValue
8756
+ } = mutation;
8766
8757
  if (oldValue === null) {
8767
8758
  const value = targetSlot.getAttribute(attributeName);
8768
- reasonParts.push(
8769
- value
8770
- ? `added [${attributeName}=${value}]`
8771
- : `added [${attributeName}]`,
8772
- );
8759
+ reasonParts.push(value ? `added [${attributeName}=${value}]` : `added [${attributeName}]`);
8773
8760
  } else if (targetSlot.hasAttribute(attributeName)) {
8774
8761
  const value = targetSlot.getAttribute(attributeName);
8775
8762
  reasonParts.push(`[${attributeName}] ${oldValue} -> ${value}`);
8776
8763
  } else {
8777
- reasonParts.push(
8778
- oldValue
8779
- ? `removed [${attributeName}=${oldValue}]`
8780
- : `removed [${attributeName}]`,
8781
- );
8764
+ reasonParts.push(oldValue ? `removed [${attributeName}=${oldValue}]` : `removed [${attributeName}]`);
8782
8765
  }
8783
8766
  }
8784
8767
  }
8785
8768
  }
8786
-
8787
8769
  if (reasonParts.length === 0) {
8788
8770
  return;
8789
8771
  }
@@ -8793,25 +8775,19 @@ const createUITransitionController = (
8793
8775
  childList: true,
8794
8776
  attributes: true,
8795
8777
  attributeFilter: [CONTENT_ID_ATTRIBUTE, CONTENT_PHASE_ATTRIBUTE],
8796
- characterData: false,
8778
+ characterData: false
8797
8779
  });
8798
8780
  addTeardown(() => {
8799
8781
  mutationObserver.disconnect();
8800
8782
  });
8801
8783
  }
8802
8784
  {
8803
- const slots = [
8804
- targetSlot,
8805
- outgoingSlot,
8806
- previousTargetSlot,
8807
- previousOutgoingSlot,
8808
- ];
8785
+ const slots = [targetSlot, outgoingSlot, previousTargetSlot, previousOutgoingSlot];
8809
8786
  for (const slot of slots) {
8810
8787
  addTeardown(monitorItemsOverflow(slot));
8811
8788
  }
8812
8789
  }
8813
-
8814
- const setDuration = (newDuration) => {
8790
+ const setDuration = newDuration => {
8815
8791
  duration = newDuration;
8816
8792
  // Update CSS variable immediately
8817
8793
  root.style.setProperty("--x-transition-duration", `${duration}ms`);
@@ -8821,27 +8797,25 @@ const createUITransitionController = (
8821
8797
  alignY = newAlignY;
8822
8798
  updateAlignment();
8823
8799
  };
8824
-
8825
8800
  return {
8826
- updateContentId: (value) => {
8801
+ updateContentId: value => {
8827
8802
  if (value) {
8828
8803
  targetSlot.setAttribute(CONTENT_ID_ATTRIBUTE, value);
8829
8804
  } else {
8830
8805
  targetSlot.removeAttribute(CONTENT_ID_ATTRIBUTE);
8831
8806
  }
8832
8807
  },
8833
-
8834
8808
  transitionTo,
8835
8809
  resetContent,
8836
8810
  setDuration,
8837
8811
  setAlignment,
8838
8812
  updateAlignment,
8839
- setPauseBreakpoints: (value) => {
8813
+ setPauseBreakpoints: value => {
8840
8814
  groupTransitionOptions.pauseBreakpoints = value;
8841
8815
  },
8842
8816
  cleanup: () => {
8843
8817
  teardown();
8844
- },
8818
+ }
8845
8819
  };
8846
8820
  };
8847
8821
 
@@ -15563,7 +15537,7 @@ const renderIntoCallout = (jsx$1, calloutMessageElement, {
15563
15537
  render(calloutJsx, calloutMessageElement);
15564
15538
  };
15565
15539
 
15566
- installImportMetaCss(import.meta);
15540
+ installImportMetaCssBuild(import.meta);
15567
15541
  /**
15568
15542
  * A callout component that mimics native browser validation messages.
15569
15543
  * Features:
@@ -15574,7 +15548,7 @@ installImportMetaCss(import.meta);
15574
15548
  * - Centers in viewport when no anchor element provided or anchor is too big
15575
15549
  */
15576
15550
 
15577
- import.meta.css = /* css */ `
15551
+ import.meta.css = [/* css */`
15578
15552
  @layer navi {
15579
15553
  .navi_callout {
15580
15554
  --callout-success-color: #4caf50;
@@ -15716,7 +15690,7 @@ import.meta.css = /* css */ `
15716
15690
  }
15717
15691
  }
15718
15692
  }
15719
- `;
15693
+ `, "/src/field/validation/callout/callout.js"];
15720
15694
 
15721
15695
  /**
15722
15696
  * Shows a callout attached to the specified element
@@ -15734,44 +15708,37 @@ import.meta.css = /* css */ `
15734
15708
  * - {HTMLElement} element - The callout DOM element
15735
15709
  * - {boolean} opened - Whether the callout is currently open
15736
15710
  */
15737
- const openCallout = (
15738
- message,
15739
- {
15740
- anchorElement,
15741
- // status determines visual styling and behavior:
15742
- // "info" - polite announcement (e.g., "This element cannot be modified")
15743
- // "warning" - expected failure requiring user action (e.g., "Field is required")
15744
- // "error" - unexpected failure, may not be actionable (e.g., "Server error")
15745
- // "success" - positive feedback (e.g., "Changes saved successfully")
15746
- // "" - neutral information
15747
- status = "",
15748
- onClose,
15749
- closeOnClickOutside = status === "info",
15750
- showErrorStack,
15751
- debug = false,
15752
- } = {},
15753
- ) => {
15711
+ const openCallout = (message, {
15712
+ anchorElement,
15713
+ // status determines visual styling and behavior:
15714
+ // "info" - polite announcement (e.g., "This element cannot be modified")
15715
+ // "warning" - expected failure requiring user action (e.g., "Field is required")
15716
+ // "error" - unexpected failure, may not be actionable (e.g., "Server error")
15717
+ // "success" - positive feedback (e.g., "Changes saved successfully")
15718
+ // "" - neutral information
15719
+ status = "",
15720
+ onClose,
15721
+ closeOnClickOutside = status === "info",
15722
+ showErrorStack,
15723
+ debug = false
15724
+ } = {}) => {
15754
15725
  const callout = {
15755
15726
  opened: true,
15756
15727
  close: null,
15757
15728
  status: undefined,
15758
-
15759
15729
  update: null,
15760
15730
  updatePosition: null,
15761
-
15762
- element: null,
15731
+ element: null
15763
15732
  };
15764
-
15765
15733
  if (debug) {
15766
15734
  console.debug("open callout", {
15767
15735
  anchorElement,
15768
15736
  message,
15769
- status,
15737
+ status
15770
15738
  });
15771
15739
  }
15772
-
15773
15740
  const [teardown, addTeardown] = createPubSub(true);
15774
- const close = (reason) => {
15741
+ const close = reason => {
15775
15742
  if (!callout.opened) {
15776
15743
  return;
15777
15744
  }
@@ -15784,39 +15751,35 @@ const openCallout = (
15784
15751
  if (onClose) {
15785
15752
  addTeardown(onClose);
15786
15753
  }
15787
-
15788
- const [updateStatus, addStatusEffect, cleanupStatusEffects] =
15789
- createValueEffect(undefined);
15754
+ const [updateStatus, addStatusEffect, cleanupStatusEffects] = createValueEffect(undefined);
15790
15755
  addTeardown(cleanupStatusEffects);
15791
15756
 
15792
15757
  // Create and add callout to document
15793
15758
  const calloutElement = createCalloutElement();
15794
- const calloutMessageElement = calloutElement.querySelector(
15795
- ".navi_callout_message",
15796
- );
15797
- const calloutCloseButton = calloutElement.querySelector(
15798
- ".navi_callout_close_button",
15799
- );
15759
+ const calloutMessageElement = calloutElement.querySelector(".navi_callout_message");
15760
+ const calloutCloseButton = calloutElement.querySelector(".navi_callout_close_button");
15800
15761
  calloutCloseButton.onclick = () => {
15801
15762
  close("click_close_button");
15802
15763
  };
15803
15764
  const calloutId = `navi_callout_${Date.now()}`;
15804
15765
  calloutElement.id = calloutId;
15805
- calloutStyleController.set(calloutElement, { opacity: 0 });
15766
+ calloutStyleController.set(calloutElement, {
15767
+ opacity: 0
15768
+ });
15806
15769
  const update = (newMessage, options = {}) => {
15807
15770
  // Connect callout with target element for accessibility
15808
15771
  if (options.status && options.status !== callout.status) {
15809
15772
  callout.status = status;
15810
15773
  updateStatus(status);
15811
15774
  }
15812
-
15813
15775
  if (options.closeOnClickOutside) {
15814
15776
  closeOnClickOutside = options.closeOnClickOutside;
15815
15777
  }
15816
-
15817
15778
  if (isValidElement(newMessage)) {
15818
15779
  calloutMessageElement.innerHTML = "";
15819
- renderIntoCallout(newMessage, calloutMessageElement, { close });
15780
+ renderIntoCallout(newMessage, calloutMessageElement, {
15781
+ close
15782
+ });
15820
15783
  } else if (newMessage instanceof Node) {
15821
15784
  // Handle DOM node (cloned from CSS selector)
15822
15785
  calloutMessageElement.innerHTML = "";
@@ -15824,9 +15787,10 @@ const openCallout = (
15824
15787
  } else if (typeof newMessage === "function") {
15825
15788
  calloutMessageElement.innerHTML = "";
15826
15789
  newMessage({
15827
- renderIntoCallout: (jsx) =>
15828
- renderIntoCallout(jsx, calloutMessageElement, { close }),
15829
- close,
15790
+ renderIntoCallout: jsx => renderIntoCallout(jsx, calloutMessageElement, {
15791
+ close
15792
+ }),
15793
+ close
15830
15794
  });
15831
15795
  } else {
15832
15796
  if (Error.isError(newMessage)) {
@@ -15855,16 +15819,12 @@ const openCallout = (
15855
15819
  }
15856
15820
  };
15857
15821
  {
15858
- const handleClickOutside = (event) => {
15822
+ const handleClickOutside = event => {
15859
15823
  if (!closeOnClickOutside) {
15860
15824
  return;
15861
15825
  }
15862
-
15863
15826
  const clickTarget = event.target;
15864
- if (
15865
- clickTarget === calloutElement ||
15866
- calloutElement.contains(clickTarget)
15867
- ) {
15827
+ if (clickTarget === calloutElement || calloutElement.contains(clickTarget)) {
15868
15828
  return;
15869
15829
  }
15870
15830
  // if (
@@ -15884,15 +15844,12 @@ const openCallout = (
15884
15844
  const handleCustomCloseEvent = () => {
15885
15845
  close("custom_event");
15886
15846
  };
15887
- calloutElement.addEventListener(
15888
- "navi_callout_close",
15889
- handleCustomCloseEvent,
15890
- );
15847
+ calloutElement.addEventListener("navi_callout_close", handleCustomCloseEvent);
15891
15848
  }
15892
15849
  Object.assign(callout, {
15893
15850
  element: calloutElement,
15894
15851
  update,
15895
- close,
15852
+ close
15896
15853
  });
15897
15854
  addStatusEffect(() => {
15898
15855
  if (status) {
@@ -15900,7 +15857,6 @@ const openCallout = (
15900
15857
  } else {
15901
15858
  calloutElement.removeAttribute("data-status");
15902
15859
  }
15903
-
15904
15860
  if (!status || status === "info" || status === "success") {
15905
15861
  calloutElement.setAttribute("role", "status");
15906
15862
  } else if (status) {
@@ -15911,39 +15867,31 @@ const openCallout = (
15911
15867
  addTeardown(() => {
15912
15868
  calloutElement.remove();
15913
15869
  });
15914
-
15915
15870
  if (anchorElement) {
15916
15871
  const anchorVisuallyVisibleInfo = getVisuallyVisibleInfo(anchorElement, {
15917
- countOffscreenAsVisible: true,
15872
+ countOffscreenAsVisible: true
15918
15873
  });
15919
15874
  if (!anchorVisuallyVisibleInfo.visible) {
15920
- console.warn(
15921
- `anchor element is not visually visible (${anchorVisuallyVisibleInfo.reason}) -> will be anchored to first visually visible ancestor`,
15922
- );
15875
+ console.warn(`anchor element is not visually visible (${anchorVisuallyVisibleInfo.reason}) -> will be anchored to first visually visible ancestor`);
15923
15876
  anchorElement = getFirstVisuallyVisibleAncestor(anchorElement);
15924
15877
  if (!anchorElement) {
15925
15878
  // anchorElement is not in the DOM anymore, fallback to body
15926
15879
  anchorElement = document.body;
15927
15880
  }
15928
15881
  }
15929
-
15930
15882
  allowWheelThrough(calloutElement, anchorElement);
15931
15883
  anchorElement.setAttribute("data-callout", calloutId);
15932
15884
  addTeardown(() => {
15933
15885
  anchorElement.removeAttribute("data-callout");
15934
15886
  });
15935
-
15936
- addStatusEffect((status) => {
15887
+ addStatusEffect(status => {
15937
15888
  if (!status) {
15938
15889
  return () => {};
15939
15890
  }
15940
15891
  // todo:
15941
15892
  // - dispatch something on the element to indicate the status
15942
15893
  // and that would in turn be used by pseudo styles system to eventually apply styles
15943
- const statusColor = resolveCSSColor(
15944
- `var(--callout-${status}-color)`,
15945
- calloutElement,
15946
- );
15894
+ const statusColor = resolveCSSColor(`var(--callout-${status}-color)`, calloutElement);
15947
15895
  anchorElement.setAttribute("data-callout-status", status);
15948
15896
  anchorElement.style.setProperty("--callout-color", statusColor);
15949
15897
  return () => {
@@ -15951,7 +15899,7 @@ const openCallout = (
15951
15899
  anchorElement.style.removeProperty("--callout-color");
15952
15900
  };
15953
15901
  });
15954
- addStatusEffect((status) => {
15902
+ addStatusEffect(status => {
15955
15903
  if (!status || status === "info" || status === "success") {
15956
15904
  anchorElement.setAttribute("aria-describedby", calloutId);
15957
15905
  return () => {
@@ -15965,7 +15913,6 @@ const openCallout = (
15965
15913
  anchorElement.removeAttribute("aria-invalid");
15966
15914
  };
15967
15915
  });
15968
-
15969
15916
  {
15970
15917
  const onfocus = () => {
15971
15918
  if (status === "error") {
@@ -15987,13 +15934,12 @@ const openCallout = (
15987
15934
  delete anchorElement.callout;
15988
15935
  });
15989
15936
  }
15990
-
15991
- update(message, { status });
15992
-
15937
+ update(message, {
15938
+ status
15939
+ });
15993
15940
  {
15994
15941
  const documentScrollLeftAtOpen = document.documentElement.scrollLeft;
15995
15942
  const documentScrollTopAtOpen = document.documentElement.scrollTop;
15996
-
15997
15943
  let positioner;
15998
15944
  let strategy;
15999
15945
  const determine = () => {
@@ -16018,7 +15964,7 @@ const openCallout = (
16018
15964
  if (newStrategy === "centered") {
16019
15965
  positioner = centerCalloutInViewport(calloutElement, {
16020
15966
  documentScrollLeftAtOpen,
16021
- documentScrollTopAtOpen,
15967
+ documentScrollTopAtOpen
16022
15968
  });
16023
15969
  } else {
16024
15970
  positioner = stickCalloutToAnchor(calloutElement, anchorElement);
@@ -16040,7 +15986,6 @@ const openCallout = (
16040
15986
  }
16041
15987
  callout.updatePosition = () => positioner.update();
16042
15988
  }
16043
-
16044
15989
  return callout;
16045
15990
  };
16046
15991
 
@@ -16052,7 +15997,7 @@ const ARROW_HEIGHT = 8;
16052
15997
  const ARROW_SPACING = 8;
16053
15998
 
16054
15999
  // HTML template for the callout
16055
- const calloutTemplate = /* html */ `
16000
+ const calloutTemplate = /* html */`
16056
16001
  <div class="navi_callout">
16057
16002
  <div class="navi_callout_box">
16058
16003
  <div class="navi_callout_frame"></div>
@@ -16087,7 +16032,6 @@ const calloutTemplate = /* html */ `
16087
16032
  </div>
16088
16033
  </div>
16089
16034
  `;
16090
-
16091
16035
  const calloutStyleController = createStyleController("callout");
16092
16036
 
16093
16037
  /**
@@ -16100,20 +16044,15 @@ const createCalloutElement = () => {
16100
16044
  const calloutElement = div.firstElementChild;
16101
16045
  return calloutElement;
16102
16046
  };
16103
-
16104
- const centerCalloutInViewport = (
16105
- calloutElement,
16106
- { documentScrollLeftAtOpen, documentScrollTopAtOpen },
16107
- ) => {
16047
+ const centerCalloutInViewport = (calloutElement, {
16048
+ documentScrollLeftAtOpen,
16049
+ documentScrollTopAtOpen
16050
+ }) => {
16108
16051
  // Set up initial styles for centered positioning
16109
16052
  const calloutBoxElement = calloutElement.querySelector(".navi_callout_box");
16110
- const calloutFrameElement = calloutElement.querySelector(
16111
- ".navi_callout_frame",
16112
- );
16053
+ const calloutFrameElement = calloutElement.querySelector(".navi_callout_frame");
16113
16054
  const calloutBodyElement = calloutElement.querySelector(".navi_callout_body");
16114
- const calloutMessageElement = calloutElement.querySelector(
16115
- ".navi_callout_message",
16116
- );
16055
+ const calloutMessageElement = calloutElement.querySelector(".navi_callout_message");
16117
16056
 
16118
16057
  // Remove any margins and set frame positioning for no arrow
16119
16058
  calloutBoxElement.style.marginTop = "";
@@ -16126,9 +16065,10 @@ const centerCalloutInViewport = (
16126
16065
 
16127
16066
  // Generate simple rectangle SVG without arrow and position in center
16128
16067
  const updateCenteredPosition = () => {
16129
- const calloutElementClone =
16130
- cloneCalloutToMeasureNaturalSize(calloutElement);
16131
- const { height } = calloutElementClone.getBoundingClientRect();
16068
+ const calloutElementClone = cloneCalloutToMeasureNaturalSize(calloutElement);
16069
+ const {
16070
+ height
16071
+ } = calloutElementClone.getBoundingClientRect();
16132
16072
  calloutElementClone.remove();
16133
16073
 
16134
16074
  // Handle content overflow when viewport is too small
@@ -16139,8 +16079,7 @@ const centerCalloutInViewport = (
16139
16079
  const paddingSizes = getPaddingSizes(calloutBodyElement);
16140
16080
  const paddingY = paddingSizes.top + paddingSizes.bottom;
16141
16081
  const spaceNeededAroundContent = BORDER_WIDTH * 2 + paddingY;
16142
- const spaceAvailableForContent =
16143
- maxAllowedHeight - spaceNeededAroundContent;
16082
+ const spaceAvailableForContent = maxAllowedHeight - spaceNeededAroundContent;
16144
16083
  calloutMessageElement.style.maxHeight = `${spaceAvailableForContent}px`;
16145
16084
  calloutMessageElement.style.overflowY = "scroll";
16146
16085
  } else {
@@ -16150,24 +16089,22 @@ const centerCalloutInViewport = (
16150
16089
  }
16151
16090
 
16152
16091
  // Get final dimensions after potential overflow adjustments
16153
- const { width: finalWidth, height: finalHeight } =
16154
- calloutElement.getBoundingClientRect();
16155
- calloutFrameElement.innerHTML = generateSvgWithoutArrow(
16156
- finalWidth,
16157
- finalHeight,
16158
- );
16092
+ const {
16093
+ width: finalWidth,
16094
+ height: finalHeight
16095
+ } = calloutElement.getBoundingClientRect();
16096
+ calloutFrameElement.innerHTML = generateSvgWithoutArrow(finalWidth, finalHeight);
16159
16097
 
16160
16098
  // Center in viewport (accounting for document scroll)
16161
16099
  const viewportWidth = window.innerWidth;
16162
16100
  const left = documentScrollLeftAtOpen + (viewportWidth - finalWidth) / 2;
16163
16101
  const top = documentScrollTopAtOpen + (viewportHeight - finalHeight) / 2;
16164
-
16165
16102
  calloutStyleController.set(calloutElement, {
16166
16103
  opacity: 1,
16167
16104
  transform: {
16168
16105
  translateX: left,
16169
- translateY: top,
16170
- },
16106
+ translateY: top
16107
+ }
16171
16108
  });
16172
16109
  };
16173
16110
 
@@ -16180,7 +16117,7 @@ const centerCalloutInViewport = (
16180
16117
  update: updateCenteredPosition,
16181
16118
  stop: () => {
16182
16119
  window.removeEventListener("resize", updateCenteredPosition);
16183
- },
16120
+ }
16184
16121
  };
16185
16122
  };
16186
16123
 
@@ -16193,156 +16130,127 @@ const centerCalloutInViewport = (
16193
16130
  const stickCalloutToAnchor = (calloutElement, anchorElement) => {
16194
16131
  // Get references to callout parts
16195
16132
  const calloutBoxElement = calloutElement.querySelector(".navi_callout_box");
16196
- const calloutFrameElement = calloutElement.querySelector(
16197
- ".navi_callout_frame",
16198
- );
16133
+ const calloutFrameElement = calloutElement.querySelector(".navi_callout_frame");
16199
16134
  const calloutBodyElement = calloutElement.querySelector(".navi_callout_body");
16200
- const calloutMessageElement = calloutElement.querySelector(
16201
- ".navi_callout_message",
16202
- );
16135
+ const calloutMessageElement = calloutElement.querySelector(".navi_callout_message");
16203
16136
 
16204
16137
  // Set initial border styles
16205
16138
  calloutBoxElement.style.borderWidth = `${BORDER_WIDTH}px`;
16206
16139
  calloutFrameElement.style.left = `-${BORDER_WIDTH}px`;
16207
16140
  calloutFrameElement.style.right = `-${BORDER_WIDTH}px`;
16141
+ const anchorVisibleRectEffect = visibleRectEffect(anchorElement, ({
16142
+ left: anchorLeft,
16143
+ right: anchorRight,
16144
+ visibilityRatio
16145
+ }) => {
16146
+ const calloutElementClone = cloneCalloutToMeasureNaturalSize(calloutElement);
16147
+ // Check for preferred and forced position from anchor element
16148
+ const preferredPosition = anchorElement.getAttribute("data-callout-position");
16149
+ const forcedPosition = anchorElement.getAttribute("data-callout-position-force");
16150
+ const {
16151
+ position,
16152
+ left: calloutLeft,
16153
+ top: calloutTop,
16154
+ width: calloutWidth,
16155
+ height: calloutHeight,
16156
+ spaceAboveTarget,
16157
+ spaceBelowTarget
16158
+ } = pickPositionRelativeTo(calloutElementClone, anchorElement, {
16159
+ alignToViewportEdgeWhenTargetNearEdge: 20,
16160
+ // when fully to the left, the border color is collé to the browser window making it hard to see
16161
+ minLeft: 1,
16162
+ positionPreference:
16163
+ // we want to avoid the callout to switch position when it can still fit so
16164
+ // we start with preferredPosition if given but once a position is picked we stick to it
16165
+ // This is implemented by favoring the data attribute of the callout then of the anchor
16166
+ calloutElement.getAttribute("data-position") || preferredPosition,
16167
+ forcePosition: forcedPosition
16168
+ });
16169
+ calloutElementClone.remove();
16208
16170
 
16209
- const anchorVisibleRectEffect = visibleRectEffect(
16210
- anchorElement,
16211
- ({ left: anchorLeft, right: anchorRight, visibilityRatio }) => {
16212
- const calloutElementClone =
16213
- cloneCalloutToMeasureNaturalSize(calloutElement);
16214
- // Check for preferred and forced position from anchor element
16215
- const preferredPosition = anchorElement.getAttribute(
16216
- "data-callout-position",
16217
- );
16218
- const forcedPosition = anchorElement.getAttribute(
16219
- "data-callout-position-force",
16220
- );
16221
-
16222
- const {
16223
- position,
16224
- left: calloutLeft,
16225
- top: calloutTop,
16226
- width: calloutWidth,
16227
- height: calloutHeight,
16228
- spaceAboveTarget,
16229
- spaceBelowTarget,
16230
- } = pickPositionRelativeTo(calloutElementClone, anchorElement, {
16231
- alignToViewportEdgeWhenTargetNearEdge: 20,
16232
- // when fully to the left, the border color is collé to the browser window making it hard to see
16233
- minLeft: 1,
16234
- positionPreference:
16235
- // we want to avoid the callout to switch position when it can still fit so
16236
- // we start with preferredPosition if given but once a position is picked we stick to it
16237
- // This is implemented by favoring the data attribute of the callout then of the anchor
16238
- calloutElement.getAttribute("data-position") || preferredPosition,
16239
- forcePosition: forcedPosition,
16240
- });
16241
- calloutElementClone.remove();
16242
-
16243
- // Calculate arrow position to point at anchorElement element
16244
- let arrowLeftPosOnCallout;
16245
- // Determine arrow target position based on attribute
16246
- const arrowPositionAttribute = anchorElement.getAttribute(
16247
- "data-callout-arrow-x",
16248
- );
16249
- let arrowAnchorLeft;
16250
- if (arrowPositionAttribute === "center") {
16251
- // Target the center of the anchorElement element
16252
- arrowAnchorLeft = (anchorLeft + anchorRight) / 2;
16253
- } else if (arrowPositionAttribute === "end") {
16254
- const anchorBorderSizes = getBorderSizes(anchorElement);
16255
- // Target the right edge of the anchorElement element (before borders)
16256
- arrowAnchorLeft = anchorRight - anchorBorderSizes.right;
16257
- } else {
16258
- const anchorBorderSizes = getBorderSizes(anchorElement);
16259
- // Default behavior: target the left edge of the anchorElement element (after borders)
16260
- arrowAnchorLeft = anchorLeft + anchorBorderSizes.left;
16261
- }
16262
-
16263
- // Calculate arrow position within the callout
16264
- if (calloutLeft < arrowAnchorLeft) {
16265
- // Callout is left of the target point, move arrow right
16266
- const diff = arrowAnchorLeft - calloutLeft;
16267
- arrowLeftPosOnCallout = diff;
16268
- } else if (calloutLeft + calloutWidth < arrowAnchorLeft) {
16269
- // Edge case: target point is beyond right edge of callout
16270
- arrowLeftPosOnCallout = calloutWidth - ARROW_WIDTH;
16271
- } else {
16272
- // Target point is within callout width
16273
- arrowLeftPosOnCallout = arrowAnchorLeft - calloutLeft;
16274
- }
16275
-
16276
- // Ensure arrow stays within callout bounds with some padding
16277
- const minArrowPos = CORNER_RADIUS + ARROW_WIDTH / 2 + ARROW_SPACING;
16278
- const maxArrowPos = calloutWidth - minArrowPos;
16279
- arrowLeftPosOnCallout = Math.max(
16280
- minArrowPos,
16281
- Math.min(arrowLeftPosOnCallout, maxArrowPos),
16282
- );
16283
-
16284
- // Force content overflow when there is not enough space to display
16285
- // the entirety of the callout
16286
- const spaceAvailable =
16287
- position === "below" ? spaceBelowTarget : spaceAboveTarget;
16288
- const paddingSizes = getPaddingSizes(calloutBodyElement);
16289
- const paddingY = paddingSizes.top + paddingSizes.bottom;
16290
- const spaceNeededAroundContent =
16291
- ARROW_HEIGHT + BORDER_WIDTH * 2 + paddingY;
16292
- const spaceAvailableForContent =
16293
- spaceAvailable - spaceNeededAroundContent;
16294
- const contentHeight = calloutHeight - spaceNeededAroundContent;
16295
- const spaceRemainingAfterContent =
16296
- spaceAvailableForContent - contentHeight;
16297
- if (spaceRemainingAfterContent < 2) {
16298
- const maxHeight = spaceAvailableForContent;
16299
- calloutMessageElement.style.maxHeight = `${maxHeight}px`;
16300
- calloutMessageElement.style.overflowY = "scroll";
16301
- } else {
16302
- calloutMessageElement.style.maxHeight = "";
16303
- calloutMessageElement.style.overflowY = "";
16304
- }
16305
-
16306
- const { width, height } = calloutElement.getBoundingClientRect();
16307
- if (position === "above") {
16308
- // Position above target element
16309
- calloutBoxElement.style.marginTop = "";
16310
- calloutBoxElement.style.marginBottom = `${ARROW_HEIGHT}px`;
16311
- calloutFrameElement.style.top = `-${BORDER_WIDTH}px`;
16312
- calloutFrameElement.style.bottom = `-${BORDER_WIDTH + ARROW_HEIGHT - 0.5}px`;
16313
- calloutFrameElement.innerHTML = generateSvgWithBottomArrow(
16314
- width,
16315
- height,
16316
- arrowLeftPosOnCallout,
16317
- );
16318
- } else {
16319
- calloutBoxElement.style.marginTop = `${ARROW_HEIGHT}px`;
16320
- calloutBoxElement.style.marginBottom = "";
16321
- calloutFrameElement.style.top = `-${BORDER_WIDTH + ARROW_HEIGHT - 0.5}px`;
16322
- calloutFrameElement.style.bottom = `-${BORDER_WIDTH}px`;
16323
- calloutFrameElement.innerHTML = generateSvgWithTopArrow(
16324
- width,
16325
- height,
16326
- arrowLeftPosOnCallout,
16327
- );
16171
+ // Calculate arrow position to point at anchorElement element
16172
+ let arrowLeftPosOnCallout;
16173
+ // Determine arrow target position based on attribute
16174
+ const arrowPositionAttribute = anchorElement.getAttribute("data-callout-arrow-x");
16175
+ let arrowAnchorLeft;
16176
+ if (arrowPositionAttribute === "center") {
16177
+ // Target the center of the anchorElement element
16178
+ arrowAnchorLeft = (anchorLeft + anchorRight) / 2;
16179
+ } else if (arrowPositionAttribute === "end") {
16180
+ const anchorBorderSizes = getBorderSizes(anchorElement);
16181
+ // Target the right edge of the anchorElement element (before borders)
16182
+ arrowAnchorLeft = anchorRight - anchorBorderSizes.right;
16183
+ } else {
16184
+ const anchorBorderSizes = getBorderSizes(anchorElement);
16185
+ // Default behavior: target the left edge of the anchorElement element (after borders)
16186
+ arrowAnchorLeft = anchorLeft + anchorBorderSizes.left;
16187
+ }
16188
+
16189
+ // Calculate arrow position within the callout
16190
+ if (calloutLeft < arrowAnchorLeft) {
16191
+ // Callout is left of the target point, move arrow right
16192
+ const diff = arrowAnchorLeft - calloutLeft;
16193
+ arrowLeftPosOnCallout = diff;
16194
+ } else if (calloutLeft + calloutWidth < arrowAnchorLeft) {
16195
+ // Edge case: target point is beyond right edge of callout
16196
+ arrowLeftPosOnCallout = calloutWidth - ARROW_WIDTH;
16197
+ } else {
16198
+ // Target point is within callout width
16199
+ arrowLeftPosOnCallout = arrowAnchorLeft - calloutLeft;
16200
+ }
16201
+
16202
+ // Ensure arrow stays within callout bounds with some padding
16203
+ const minArrowPos = CORNER_RADIUS + ARROW_WIDTH / 2 + ARROW_SPACING;
16204
+ const maxArrowPos = calloutWidth - minArrowPos;
16205
+ arrowLeftPosOnCallout = Math.max(minArrowPos, Math.min(arrowLeftPosOnCallout, maxArrowPos));
16206
+
16207
+ // Force content overflow when there is not enough space to display
16208
+ // the entirety of the callout
16209
+ const spaceAvailable = position === "below" ? spaceBelowTarget : spaceAboveTarget;
16210
+ const paddingSizes = getPaddingSizes(calloutBodyElement);
16211
+ const paddingY = paddingSizes.top + paddingSizes.bottom;
16212
+ const spaceNeededAroundContent = ARROW_HEIGHT + BORDER_WIDTH * 2 + paddingY;
16213
+ const spaceAvailableForContent = spaceAvailable - spaceNeededAroundContent;
16214
+ const contentHeight = calloutHeight - spaceNeededAroundContent;
16215
+ const spaceRemainingAfterContent = spaceAvailableForContent - contentHeight;
16216
+ if (spaceRemainingAfterContent < 2) {
16217
+ const maxHeight = spaceAvailableForContent;
16218
+ calloutMessageElement.style.maxHeight = `${maxHeight}px`;
16219
+ calloutMessageElement.style.overflowY = "scroll";
16220
+ } else {
16221
+ calloutMessageElement.style.maxHeight = "";
16222
+ calloutMessageElement.style.overflowY = "";
16223
+ }
16224
+ const {
16225
+ width,
16226
+ height
16227
+ } = calloutElement.getBoundingClientRect();
16228
+ if (position === "above") {
16229
+ // Position above target element
16230
+ calloutBoxElement.style.marginTop = "";
16231
+ calloutBoxElement.style.marginBottom = `${ARROW_HEIGHT}px`;
16232
+ calloutFrameElement.style.top = `-${BORDER_WIDTH}px`;
16233
+ calloutFrameElement.style.bottom = `-${BORDER_WIDTH + ARROW_HEIGHT - 0.5}px`;
16234
+ calloutFrameElement.innerHTML = generateSvgWithBottomArrow(width, height, arrowLeftPosOnCallout);
16235
+ } else {
16236
+ calloutBoxElement.style.marginTop = `${ARROW_HEIGHT}px`;
16237
+ calloutBoxElement.style.marginBottom = "";
16238
+ calloutFrameElement.style.top = `-${BORDER_WIDTH + ARROW_HEIGHT - 0.5}px`;
16239
+ calloutFrameElement.style.bottom = `-${BORDER_WIDTH}px`;
16240
+ calloutFrameElement.innerHTML = generateSvgWithTopArrow(width, height, arrowLeftPosOnCallout);
16241
+ }
16242
+ calloutElement.setAttribute("data-position", position);
16243
+ calloutStyleController.set(calloutElement, {
16244
+ opacity: visibilityRatio ? 1 : 0,
16245
+ transform: {
16246
+ translateX: calloutLeft,
16247
+ translateY: calloutTop
16328
16248
  }
16329
-
16330
- calloutElement.setAttribute("data-position", position);
16331
- calloutStyleController.set(calloutElement, {
16332
- opacity: visibilityRatio ? 1 : 0,
16333
- transform: {
16334
- translateX: calloutLeft,
16335
- translateY: calloutTop,
16336
- },
16337
- });
16338
- },
16339
- );
16340
- const calloutSizeChangeObserver = observeCalloutSizeChange(
16341
- calloutMessageElement,
16342
- (width, height) => {
16343
- anchorVisibleRectEffect.check(`callout_size_change (${width}x${height})`);
16344
- },
16345
- );
16249
+ });
16250
+ });
16251
+ const calloutSizeChangeObserver = observeCalloutSizeChange(calloutMessageElement, (width, height) => {
16252
+ anchorVisibleRectEffect.check(`callout_size_change (${width}x${height})`);
16253
+ });
16346
16254
  anchorVisibleRectEffect.onBeforeAutoCheck(() => {
16347
16255
  // prevent feedback loop because check triggers size change which triggers check...
16348
16256
  calloutSizeChangeObserver.disable();
@@ -16350,22 +16258,23 @@ const stickCalloutToAnchor = (calloutElement, anchorElement) => {
16350
16258
  calloutSizeChangeObserver.enable();
16351
16259
  };
16352
16260
  });
16353
-
16354
16261
  return {
16355
16262
  update: anchorVisibleRectEffect.check,
16356
16263
  stop: () => {
16357
16264
  calloutSizeChangeObserver.disconnect();
16358
16265
  anchorVisibleRectEffect.disconnect();
16359
- },
16266
+ }
16360
16267
  };
16361
16268
  };
16362
-
16363
16269
  const observeCalloutSizeChange = (elementSizeToObserve, callback) => {
16364
16270
  let lastContentWidth;
16365
16271
  let lastContentHeight;
16366
- const resizeObserver = new ResizeObserver((entries) => {
16272
+ const resizeObserver = new ResizeObserver(entries => {
16367
16273
  const [entry] = entries;
16368
- const { width, height } = entry.contentRect;
16274
+ const {
16275
+ width,
16276
+ height
16277
+ } = entry.contentRect;
16369
16278
  // Debounce tiny changes that are likely sub-pixel rounding
16370
16279
  if (lastContentWidth !== undefined) {
16371
16280
  const widthDiff = Math.abs(width - lastContentWidth);
@@ -16380,7 +16289,6 @@ const observeCalloutSizeChange = (elementSizeToObserve, callback) => {
16380
16289
  callback(width, height);
16381
16290
  });
16382
16291
  resizeObserver.observe(elementSizeToObserve);
16383
-
16384
16292
  return {
16385
16293
  disable: () => {
16386
16294
  resizeObserver.unobserve(elementSizeToObserve);
@@ -16390,17 +16298,11 @@ const observeCalloutSizeChange = (elementSizeToObserve, callback) => {
16390
16298
  },
16391
16299
  disconnect: () => {
16392
16300
  resizeObserver.disconnect();
16393
- },
16301
+ }
16394
16302
  };
16395
16303
  };
16396
-
16397
- const escapeHtml = (string) => {
16398
- return string
16399
- .replace(/&/g, "&amp;")
16400
- .replace(/</g, "&lt;")
16401
- .replace(/>/g, "&gt;")
16402
- .replace(/"/g, "&quot;")
16403
- .replace(/'/g, "&#039;");
16304
+ const escapeHtml = string => {
16305
+ return string.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
16404
16306
  };
16405
16307
 
16406
16308
  /**
@@ -16408,7 +16310,7 @@ const escapeHtml = (string) => {
16408
16310
  * @param {string} content - The content to check
16409
16311
  * @returns {boolean} - True if it looks like a complete HTML document
16410
16312
  */
16411
- const isHtmlDocument = (content) => {
16313
+ const isHtmlDocument = content => {
16412
16314
  if (typeof content !== "string") {
16413
16315
  return false;
16414
16316
  }
@@ -16418,20 +16320,17 @@ const isHtmlDocument = (content) => {
16418
16320
  };
16419
16321
 
16420
16322
  // It's ok to do this because the element is absolutely positioned
16421
- const cloneCalloutToMeasureNaturalSize = (calloutElement) => {
16323
+ const cloneCalloutToMeasureNaturalSize = calloutElement => {
16422
16324
  // Create invisible clone to measure natural size
16423
16325
  const calloutElementClone = calloutElement.cloneNode(true);
16424
16326
  calloutElementClone.style.visibility = "hidden";
16425
- const calloutMessageElementClone = calloutElementClone.querySelector(
16426
- ".navi_callout_message",
16427
- );
16327
+ const calloutMessageElementClone = calloutElementClone.querySelector(".navi_callout_message");
16428
16328
  // Reset any overflow constraints on the clone
16429
16329
  calloutMessageElementClone.style.maxHeight = "";
16430
16330
  calloutMessageElementClone.style.overflowY = "";
16431
16331
 
16432
16332
  // Add clone to DOM to measure
16433
16333
  calloutElement.parentNode.appendChild(calloutElementClone);
16434
-
16435
16334
  return calloutElementClone;
16436
16335
  };
16437
16336
 
@@ -16444,14 +16343,10 @@ const cloneCalloutToMeasureNaturalSize = (calloutElement) => {
16444
16343
  */
16445
16344
  const generateSvgWithTopArrow = (width, height, arrowPosition) => {
16446
16345
  // Calculate valid arrow position range
16447
- const arrowLeft =
16448
- ARROW_WIDTH / 2 + CORNER_RADIUS + BORDER_WIDTH + ARROW_SPACING;
16346
+ const arrowLeft = ARROW_WIDTH / 2 + CORNER_RADIUS + BORDER_WIDTH + ARROW_SPACING;
16449
16347
  const minArrowPos = arrowLeft;
16450
16348
  const maxArrowPos = width - arrowLeft;
16451
- const constrainedArrowPos = Math.max(
16452
- minArrowPos,
16453
- Math.min(arrowPosition, maxArrowPos),
16454
- );
16349
+ const constrainedArrowPos = Math.max(minArrowPos, Math.min(arrowPosition, maxArrowPos));
16455
16350
 
16456
16351
  // Calculate content height
16457
16352
  const contentHeight = height - ARROW_HEIGHT;
@@ -16495,8 +16390,7 @@ const generateSvgWithTopArrow = (width, height, arrowPosition) => {
16495
16390
  V${ARROW_HEIGHT + innerRadius + BORDER_WIDTH}
16496
16391
  Q${BORDER_WIDTH},${ARROW_HEIGHT + BORDER_WIDTH} ${innerRadius + BORDER_WIDTH},${ARROW_HEIGHT + BORDER_WIDTH}
16497
16392
  `;
16498
-
16499
- return /* html */ `
16393
+ return /* html */`
16500
16394
  <svg
16501
16395
  width="${adjustedWidth}"
16502
16396
  height="${adjustedHeight}"
@@ -16520,14 +16414,10 @@ const generateSvgWithTopArrow = (width, height, arrowPosition) => {
16520
16414
  */
16521
16415
  const generateSvgWithBottomArrow = (width, height, arrowPosition) => {
16522
16416
  // Calculate valid arrow position range
16523
- const arrowLeft =
16524
- ARROW_WIDTH / 2 + CORNER_RADIUS + BORDER_WIDTH + ARROW_SPACING;
16417
+ const arrowLeft = ARROW_WIDTH / 2 + CORNER_RADIUS + BORDER_WIDTH + ARROW_SPACING;
16525
16418
  const minArrowPos = arrowLeft;
16526
16419
  const maxArrowPos = width - arrowLeft;
16527
- const constrainedArrowPos = Math.max(
16528
- minArrowPos,
16529
- Math.min(arrowPosition, maxArrowPos),
16530
- );
16420
+ const constrainedArrowPos = Math.max(minArrowPos, Math.min(arrowPosition, maxArrowPos));
16531
16421
 
16532
16422
  // Calculate content height
16533
16423
  const contentHeight = height - ARROW_HEIGHT;
@@ -16571,8 +16461,7 @@ const generateSvgWithBottomArrow = (width, height, arrowPosition) => {
16571
16461
  V${innerRadius + BORDER_WIDTH}
16572
16462
  Q${BORDER_WIDTH},${BORDER_WIDTH} ${innerRadius + BORDER_WIDTH},${BORDER_WIDTH}
16573
16463
  `;
16574
-
16575
- return /* html */ `
16464
+ return /* html */`
16576
16465
  <svg
16577
16466
  width="${adjustedWidth}"
16578
16467
  height="${adjustedHeight}"
@@ -16594,7 +16483,7 @@ const generateSvgWithBottomArrow = (width, height, arrowPosition) => {
16594
16483
  * @returns {string} - SVG markup
16595
16484
  */
16596
16485
  const generateSvgWithoutArrow = (width, height) => {
16597
- return /* html */ `
16486
+ return /* html */`
16598
16487
  <svg
16599
16488
  width="${width}"
16600
16489
  height="${height}"
@@ -18894,7 +18783,8 @@ const selectByTextStrings = (element, range, startText, endText) => {
18894
18783
  }
18895
18784
  };
18896
18785
 
18897
- installImportMetaCss(import.meta);import.meta.css = /* css */`
18786
+ installImportMetaCssBuild(import.meta);/* eslint-disable jsenv/no-unknown-params */
18787
+ import.meta.css = [/* css */`
18898
18788
  *[data-navi-space] {
18899
18789
  /* user-select: none; */
18900
18790
  padding-left: 0.25em;
@@ -19003,7 +18893,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
19003
18893
  transition-timing-function: ease;
19004
18894
  }
19005
18895
  }
19006
- `;
18896
+ `, "/src/text/text.jsx"];
19007
18897
 
19008
18898
  // We could use <span data-navi-space=""> </span>
19009
18899
  // but we prefer to use zero width space as it has the nice side effects of
@@ -19150,6 +19040,7 @@ const TextOverflow = ({
19150
19040
  pre: !noWrap
19151
19041
  // For paragraph we prefer to keep lines and only hide unbreakable long sections
19152
19042
  ,
19043
+
19153
19044
  preLine: rest.as === "p",
19154
19045
  ...rest,
19155
19046
  "data-text-overflow": true,
@@ -19268,7 +19159,7 @@ const TextBasic = ({
19268
19159
  });
19269
19160
  };
19270
19161
 
19271
- installImportMetaCss(import.meta);import.meta.css = /* css */`
19162
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
19272
19163
  @layer navi {
19273
19164
  /* Ensure data attributes from box.jsx can win to update display */
19274
19165
  .navi_icon {
@@ -19343,7 +19234,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
19343
19234
  width: 100%;
19344
19235
  height: 100%;
19345
19236
  }
19346
- `;
19237
+ `, "/src/graphic/icon.jsx"];
19347
19238
  const Icon = ({
19348
19239
  href,
19349
19240
  children,
@@ -19637,7 +19528,23 @@ const setupNetworkMonitoring = () => {
19637
19528
  };
19638
19529
  setupNetworkMonitoring();
19639
19530
 
19640
- installImportMetaCss(import.meta);import.meta.css = /* css */`
19531
+ installImportMetaCssBuild(import.meta);/**
19532
+ * RectangleLoading Component
19533
+ *
19534
+ * A responsive loading indicator that dynamically adjusts to fit its container.
19535
+ * Displays an animated outline with a traveling dot that follows the container's shape.
19536
+ *
19537
+ * Features:
19538
+ * - Adapts to any container dimensions using ResizeObserver
19539
+ * - Scales stroke width, margins and corner radius proportionally
19540
+ * - Animates using native SVG animations for smooth performance
19541
+ * - High-quality SVG rendering with proper path calculations
19542
+ *
19543
+ * @param {Object} props - Component props
19544
+ * @param {string} [props.color="#383a36"] - Color of the loading indicator
19545
+ * @param {number} [props.radius=0] - Corner radius of the rectangle (px)
19546
+ */
19547
+ import.meta.css = [/* css */`
19641
19548
  .navi_rectangle_loading {
19642
19549
  position: relative;
19643
19550
  display: flex;
@@ -19649,7 +19556,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
19649
19556
  .navi_rectangle_loading[data-visible] {
19650
19557
  opacity: 1;
19651
19558
  }
19652
- `;
19559
+ `, "/src/graphic/loader/rectangle_loading.jsx"];
19653
19560
  const RectangleLoading = ({
19654
19561
  shouldShowSpinner,
19655
19562
  color = "currentColor",
@@ -19836,7 +19743,7 @@ const RectangleLoadingSvg = ({
19836
19743
  });
19837
19744
  };
19838
19745
 
19839
- installImportMetaCss(import.meta);import.meta.css = /* css */`
19746
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
19840
19747
  .navi_loading_rectangle_wrapper {
19841
19748
  position: absolute;
19842
19749
  top: var(--rectangle-top, 0);
@@ -19851,7 +19758,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
19851
19758
  opacity: 1;
19852
19759
  }
19853
19760
  }
19854
- `;
19761
+ `, "/src/graphic/loader/loader_background.jsx"];
19855
19762
  const LoaderBackground = ({
19856
19763
  loading,
19857
19764
  containerRef,
@@ -21213,7 +21120,7 @@ const useUIState = (uiStateController) => {
21213
21120
  return trackedUIState;
21214
21121
  };
21215
21122
 
21216
- installImportMetaCss(import.meta);import.meta.css = /* css */`
21123
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
21217
21124
  @layer navi {
21218
21125
  .navi_button {
21219
21126
  --button-outline-width: 1px;
@@ -21448,7 +21355,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
21448
21355
  --x-button-border-color: var(--callout-color);
21449
21356
  }
21450
21357
  }
21451
- `;
21358
+ `, "/src/field/button.jsx"];
21452
21359
  const Button = props => {
21453
21360
  return renderActionableComponent(props, {
21454
21361
  Basic: ButtonBasic,
@@ -21537,6 +21444,7 @@ const ButtonBasic = props => {
21537
21444
  "aria-busy": innerLoading
21538
21445
  // style management
21539
21446
  ,
21447
+
21540
21448
  baseClassName: "navi_button",
21541
21449
  styleCSSVars: ButtonStyleCSSVars,
21542
21450
  pseudoClasses: ButtonPseudoClasses,
@@ -21714,7 +21622,7 @@ const WarningSvg = () => {
21714
21622
  });
21715
21623
  };
21716
21624
 
21717
- installImportMetaCss(import.meta);import.meta.css = /* css */`
21625
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
21718
21626
  @layer navi {
21719
21627
  .navi_message_box {
21720
21628
  --background-color-info: var(--navi-info-color-light);
@@ -21757,7 +21665,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
21757
21665
  border-top-left-radius: 6px;
21758
21666
  border-bottom-left-radius: 6px;
21759
21667
  }
21760
- `;
21668
+ `, "/src/text/message_box.jsx"];
21761
21669
  const MessageBoxPseudoClasses = [":-navi-status-info", ":-navi-status-success", ":-navi-status-warning", ":-navi-status-error"];
21762
21670
  const MessageBoxStatusContext = createContext();
21763
21671
  const MessageBoxReportTitleChildContext = createContext();
@@ -21825,7 +21733,7 @@ const MessageBox = ({
21825
21733
  });
21826
21734
  };
21827
21735
 
21828
- installImportMetaCss(import.meta);import.meta.css = /* css */`
21736
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
21829
21737
  .navi_message_box {
21830
21738
  .navi_title {
21831
21739
  margin-top: 0;
@@ -21833,7 +21741,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
21833
21741
  color: var(--x-message-color);
21834
21742
  }
21835
21743
  }
21836
- `;
21744
+ `, "/src/text/title.jsx"];
21837
21745
  const TitleLevelContext = createContext();
21838
21746
  const useTitleLevel = () => {
21839
21747
  return useContext(TitleLevelContext);
@@ -22010,7 +21918,8 @@ const useDimColorWhen = (elementRef, shouldDim) => {
22010
21918
  });
22011
21919
  };
22012
21920
 
22013
- installImportMetaCss(import.meta);import.meta.css = /* css */`
21921
+ installImportMetaCssBuild(import.meta);/* eslint-disable jsenv/no-unknown-params */
21922
+ import.meta.css = [/* css */`
22014
21923
  @layer navi {
22015
21924
  .navi_link {
22016
21925
  --link-border-radius: unset;
@@ -22282,7 +22191,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
22282
22191
  .navi_title .navi_link[data-reveal-on-interaction] {
22283
22192
  top: 0.25em;
22284
22193
  }
22285
- `;
22194
+ `, "/src/nav/link/link.jsx"];
22286
22195
  const LinkStyleCSSVars = {
22287
22196
  "outlineColor": "--link-outline-color",
22288
22197
  "borderRadius": "--link-border-radius",
@@ -22482,6 +22391,7 @@ const LinkPlain = props => {
22482
22391
  overflowEllipsis: overflowEllipsis
22483
22392
  // Visual
22484
22393
  ,
22394
+
22485
22395
  "data-appearance": appearance,
22486
22396
  "data-current-effect-bold": currentEffectBold ? "" : undefined,
22487
22397
  "data-current-effect-shadow": currentEffectShadow ? "" : undefined,
@@ -22586,7 +22496,11 @@ const LinkWithAction = props => {
22586
22496
  const NavContext = createContext();
22587
22497
  createContext();
22588
22498
 
22589
- installImportMetaCss(import.meta);import.meta.css = /* css */`
22499
+ installImportMetaCssBuild(import.meta);/**
22500
+ * TabList component with support for horizontal and vertical layouts
22501
+ * https://dribbble.com/search/tabs
22502
+ */
22503
+ import.meta.css = [/* css */`
22590
22504
  @layer navi {
22591
22505
  .navi_nav {
22592
22506
  --nav-border: none;
@@ -22695,7 +22609,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
22695
22609
  }
22696
22610
  }
22697
22611
  }
22698
- `;
22612
+ `, "/src/nav/link/nav.jsx"];
22699
22613
  const NavStyleCSSVars = {
22700
22614
  border: "--nav-border",
22701
22615
  borderRadius: "--nav-border-radius",
@@ -22765,9 +22679,9 @@ const useFocusGroup = (
22765
22679
  }, [direction, skipTab, loop, name]);
22766
22680
  };
22767
22681
 
22768
- installImportMetaCss(import.meta);const rightArrowPath = "M680-480L360-160l-80-80 240-240-240-240 80-80 320 320z";
22682
+ installImportMetaCssBuild(import.meta);const rightArrowPath = "M680-480L360-160l-80-80 240-240-240-240 80-80 320 320z";
22769
22683
  const downArrowPath = "M480-280L160-600l80-80 240 240 240-240 80 80-320 320z";
22770
- import.meta.css = /* css */`
22684
+ import.meta.css = [/* css */`
22771
22685
  .navi_summary_marker {
22772
22686
  width: 1em;
22773
22687
  height: 1em;
@@ -22847,7 +22761,7 @@ import.meta.css = /* css */`
22847
22761
  d: path("${rightArrowPath}");
22848
22762
  }
22849
22763
  }
22850
- `;
22764
+ `, "/src/field/details/summary_marker.jsx"];
22851
22765
  const SummaryMarker = ({
22852
22766
  open,
22853
22767
  loading
@@ -22905,7 +22819,7 @@ const SummaryMarker = ({
22905
22819
  });
22906
22820
  };
22907
22821
 
22908
- installImportMetaCss(import.meta);import.meta.css = /* css */`
22822
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
22909
22823
  .navi_details {
22910
22824
  position: relative;
22911
22825
  z-index: 1;
@@ -22940,7 +22854,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
22940
22854
  }
22941
22855
  }
22942
22856
  }
22943
- `;
22857
+ `, "/src/field/details/details.jsx"];
22944
22858
  const Details = props => {
22945
22859
  const {
22946
22860
  value = "on",
@@ -23256,7 +23170,7 @@ const fieldPropSet = new Set([
23256
23170
  "data-testid",
23257
23171
  ]);
23258
23172
 
23259
- installImportMetaCss(import.meta);import.meta.css = /* css */`
23173
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
23260
23174
  @layer navi {
23261
23175
  label {
23262
23176
  &[data-interactive] {
@@ -23270,7 +23184,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
23270
23184
  }
23271
23185
  }
23272
23186
  }
23273
- `;
23187
+ `, "/src/field/label.jsx"];
23274
23188
  const ReportReadOnlyOnLabelContext = createContext();
23275
23189
  const ReportDisabledOnLabelContext = createContext();
23276
23190
  const ReportInteractiveOnLabelContext = createContext();
@@ -23321,7 +23235,7 @@ const Label = props => {
23321
23235
  });
23322
23236
  };
23323
23237
 
23324
- installImportMetaCss(import.meta);import.meta.css = /* css */`
23238
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
23325
23239
  @layer navi {
23326
23240
  .navi_checkbox {
23327
23241
  --margin: 3px 3px 3px 4px;
@@ -23646,7 +23560,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
23646
23560
  }
23647
23561
  }
23648
23562
  }
23649
- `;
23563
+ `, "/src/field/input_checkbox.jsx"];
23650
23564
  const InputCheckbox = props => {
23651
23565
  const {
23652
23566
  value = "on"
@@ -23916,14 +23830,15 @@ const InputCheckboxWithAction = props => {
23916
23830
  });
23917
23831
  };
23918
23832
 
23919
- installImportMetaCss(import.meta);import.meta.css = /* css */`
23833
+ installImportMetaCssBuild(import.meta);// TOFIX: select in data then reset, it reset to red/blue instead of red/blue/green
23834
+ import.meta.css = [/* css */`
23920
23835
  @layer navi {
23921
23836
  .navi_checkbox_list {
23922
23837
  display: flex;
23923
23838
  flex-direction: column;
23924
23839
  }
23925
23840
  }
23926
- `;
23841
+ `, "/src/field/checkbox_list.jsx"];
23927
23842
  const CheckboxList = forwardRef((props, ref) => {
23928
23843
  const uiStateController = useUIGroupStateController(props, "checkbox_list", {
23929
23844
  childComponentType: "checkbox",
@@ -23975,6 +23890,7 @@ const CheckboxListBasic = forwardRef((props, ref) => {
23975
23890
  "data-checkbox-list": true
23976
23891
  // eslint-disable-next-line react/no-unknown-property
23977
23892
  ,
23893
+
23978
23894
  onresetuistate: e => {
23979
23895
  uiStateController.resetUIState(e);
23980
23896
  },
@@ -24068,7 +23984,7 @@ forwardRef((props, ref) => {
24068
23984
  });
24069
23985
  });
24070
23986
 
24071
- installImportMetaCss(import.meta);import.meta.css = /* css */`
23987
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
24072
23988
  @layer navi {
24073
23989
  .navi_radio {
24074
23990
  --margin: 3px 3px 0 5px;
@@ -24359,7 +24275,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
24359
24275
  }
24360
24276
  }
24361
24277
  }
24362
- `;
24278
+ `, "/src/field/input_radio.jsx"];
24363
24279
  const InputRadio = props => {
24364
24280
  const {
24365
24281
  value = "on"
@@ -24606,7 +24522,7 @@ const InputRadioWithAction = () => {
24606
24522
  throw new Error(`<Input type="radio" /> with an action make no sense. Use <RadioList action={something} /> instead`);
24607
24523
  };
24608
24524
 
24609
- installImportMetaCss(import.meta);import.meta.css = /* css */`
24525
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
24610
24526
  @layer navi {
24611
24527
  .navi_input_range {
24612
24528
  --border-radius: 6px;
@@ -24813,7 +24729,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
24813
24729
  .navi_input_range[data-callout] {
24814
24730
  /* What can we do? */
24815
24731
  }
24816
- `;
24732
+ `, "/src/field/input_range.jsx"];
24817
24733
  const InputRange = props => {
24818
24734
  const uiStateController = useUIStateController(props, "input");
24819
24735
  const uiState = useUIState(uiStateController);
@@ -24965,6 +24881,7 @@ const InputRangeBasic = props => {
24965
24881
  }
24966
24882
  // style management
24967
24883
  ,
24884
+
24968
24885
  baseClassName: "navi_native_input"
24969
24886
  });
24970
24887
  };
@@ -25083,7 +25000,24 @@ const SearchSvg = () => jsx("svg", {
25083
25000
  })
25084
25001
  });
25085
25002
 
25086
- installImportMetaCss(import.meta);import.meta.css = /* css */`
25003
+ installImportMetaCssBuild(import.meta);/**
25004
+ * Input component for all textual input types.
25005
+ *
25006
+ * Supports:
25007
+ * - text (default)
25008
+ * - password
25009
+ * - hidden
25010
+ * - email
25011
+ * - url
25012
+ * - search
25013
+ * - tel
25014
+ * - etc.
25015
+ *
25016
+ * For non-textual inputs, specialized components will be used:
25017
+ * - <InputCheckbox /> for type="checkbox"
25018
+ * - <InputRadio /> for type="radio"
25019
+ */
25020
+ import.meta.css = [/* css */`
25087
25021
  @layer navi {
25088
25022
  .navi_input {
25089
25023
  --border-radius: 2px;
@@ -25293,7 +25227,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
25293
25227
  /* Fortunately we can override it as follow */
25294
25228
  -webkit-text-fill-color: var(--x-color) !important;
25295
25229
  }
25296
- `;
25230
+ `, "/src/field/input_textual.jsx"];
25297
25231
  const InputTextual = props => {
25298
25232
  const uiStateController = useUIStateController(props, "input");
25299
25233
  const uiState = useUIState(uiStateController);
@@ -25436,6 +25370,7 @@ const InputTextualBasic = props => {
25436
25370
  }
25437
25371
  // style management
25438
25372
  ,
25373
+
25439
25374
  baseClassName: "navi_native_input",
25440
25375
  "data-rendered-by": ".navi_input"
25441
25376
  });
@@ -25654,7 +25589,16 @@ const Input = props => {
25654
25589
  });
25655
25590
  };
25656
25591
 
25657
- installImportMetaCss(import.meta);import.meta.css = /* css */`
25592
+ installImportMetaCssBuild(import.meta);/**
25593
+ * - We must keep the edited element in the DOM so that
25594
+ * the layout remains the same (especially important for table cells)
25595
+ * And the editable part is in absolute so that it takes the original content dimensions
25596
+ * AND for table cells it can actually take the table cell dimensions
25597
+ *
25598
+ * This means an editable thing MUST have a parent with position relative that wraps the content and the eventual editable input
25599
+ *
25600
+ */
25601
+ import.meta.css = [/* css */`
25658
25602
  .navi_editable_wrapper {
25659
25603
  --inset-top: 0px;
25660
25604
  --inset-right: 0px;
@@ -25679,7 +25623,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
25679
25623
  pointer-events: auto;
25680
25624
  }
25681
25625
  }
25682
- `;
25626
+ `, "/src/field/edition/editable.jsx"];
25683
25627
  const useEditionController = () => {
25684
25628
  const [editing, editingSetter] = useState(null);
25685
25629
  const startEditing = useCallback(event => {
@@ -26113,7 +26057,7 @@ const FormWithAction = props => {
26113
26057
  // form.dispatchEvent(customEvent);
26114
26058
  // };
26115
26059
 
26116
- installImportMetaCss(import.meta);import.meta.css = /* css */`
26060
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
26117
26061
  .navi_group {
26118
26062
  --border-width: 1px;
26119
26063
 
@@ -26202,7 +26146,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
26202
26146
  }
26203
26147
  }
26204
26148
  }
26205
- `;
26149
+ `, "/src/field/group.jsx"];
26206
26150
  const Group = ({
26207
26151
  children,
26208
26152
  borderWidth = 1,
@@ -26227,7 +26171,7 @@ const Group = ({
26227
26171
  });
26228
26172
  };
26229
26173
 
26230
- installImportMetaCss(import.meta);import.meta.css = /* css */``;
26174
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */``, "/src/field/radio_list.jsx"];
26231
26175
  const RadioList = props => {
26232
26176
  const uiStateController = useUIGroupStateController(props, "radio_list", {
26233
26177
  childComponentType: "radio",
@@ -26408,12 +26352,12 @@ const useRefArray = (items, keyFromItem) => {
26408
26352
  }, [items]);
26409
26353
  };
26410
26354
 
26411
- installImportMetaCss(import.meta);const useNavState = () => {};
26412
- import.meta.css = /* css */`
26355
+ installImportMetaCssBuild(import.meta);const useNavState = () => {};
26356
+ import.meta.css = [/* css */`
26413
26357
  .navi_select[data-readonly] {
26414
26358
  pointer-events: none;
26415
26359
  }
26416
- `;
26360
+ `, "/src/field/select.jsx"];
26417
26361
  const Select = forwardRef((props, ref) => {
26418
26362
  const select = renderActionableComponent(props, ref);
26419
26363
  return select;
@@ -26718,7 +26662,7 @@ const Z_INDEX_DROP_PREVIEW = Z_INDEX_STICKY_CORNER + 1;
26718
26662
 
26719
26663
  const Z_INDEX_TABLE_UI = Z_INDEX_STICKY_CORNER + 1;
26720
26664
 
26721
- installImportMetaCss(import.meta);import.meta.css = /* css */`
26665
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
26722
26666
  .navi_table_drag_clone_container {
26723
26667
  position: absolute;
26724
26668
  top: var(--table-visual-top);
@@ -26837,7 +26781,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
26837
26781
  width: 10px;
26838
26782
  height: 10px;
26839
26783
  }
26840
- `;
26784
+ `, "/src/field/table/drag/table_drag.jsx"];
26841
26785
  const TableDragContext = createContext();
26842
26786
  const useTableDragContextValue = ({
26843
26787
  tableDragCloneContainerRef,
@@ -27378,11 +27322,11 @@ const useTableSizeContextValue = ({
27378
27322
  return tableSizeContextValue;
27379
27323
  };
27380
27324
 
27381
- installImportMetaCss(import.meta);const ROW_MIN_HEIGHT = 30;
27325
+ installImportMetaCssBuild(import.meta);const ROW_MIN_HEIGHT = 30;
27382
27326
  const ROW_MAX_HEIGHT = 100;
27383
27327
  const COLUMN_MIN_WIDTH = 50;
27384
27328
  const COLUMN_MAX_WIDTH = 500;
27385
- import.meta.css = /* css */`
27329
+ import.meta.css = [/* css */`
27386
27330
  @layer navi {
27387
27331
  .navi_table {
27388
27332
  --table-resizer-handle-color: #063b7c;
@@ -27538,7 +27482,7 @@ import.meta.css = /* css */`
27538
27482
  .navi_table_row_resizer[data-grabbed] .navi_table_row_resizer_line {
27539
27483
  opacity: 1;
27540
27484
  }
27541
- `;
27485
+ `, "/src/field/table/resize/table_resize.jsx"];
27542
27486
 
27543
27487
  // Column resize components
27544
27488
  const TableColumnResizer = forwardRef((props, ref) => {
@@ -28004,7 +27948,7 @@ const findPreviousTableRow = currentRow => {
28004
27948
  return currentIndex > 0 ? allRows[currentIndex - 1] : null;
28005
27949
  };
28006
27950
 
28007
- installImportMetaCss(import.meta);import.meta.css = /* css */`
27951
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
28008
27952
  @layer navi {
28009
27953
  .navi_table {
28010
27954
  --selection-border-color: var(--navi-selection-border-color, #0078d4);
@@ -28099,7 +28043,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
28099
28043
  inset 0 -1px 0 0 var(--selection-border-color),
28100
28044
  inset 1px 0 0 0 var(--selection-border-color);
28101
28045
  }
28102
- `;
28046
+ `, "/src/field/table/selection/table_selection.jsx"];
28103
28047
  const useTableSelectionController = ({
28104
28048
  tableRef,
28105
28049
  selection,
@@ -28575,7 +28519,8 @@ const useTableStickyContextValue = ({
28575
28519
  }, [stickyLeftFrontierColumnIndex, stickyTopFrontierRowIndex]);
28576
28520
  };
28577
28521
 
28578
- installImportMetaCss(import.meta);import.meta.css = /* css */`
28522
+ installImportMetaCssBuild(import.meta);// TODO: sticky left/top frontier should likely use "followPosition"
28523
+ import.meta.css = [/* css */`
28579
28524
  @layer navi {
28580
28525
  .navi_table {
28581
28526
  --sticky-frontier-color: #c0c0c0;
@@ -28814,7 +28759,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
28814
28759
  inset -1px 0 0 0 var(--border-color),
28815
28760
  inset 0 -1px 0 0 var(--border-color);
28816
28761
  }
28817
- `;
28762
+ `, "/src/field/table/sticky/table_sticky.jsx"];
28818
28763
  const TableStickyFrontier = ({
28819
28764
  tableRef
28820
28765
  }) => {
@@ -29036,7 +28981,7 @@ const initMoveStickyFrontierViaPointer = (pointerdownEvent, {
29036
28981
  });
29037
28982
  };
29038
28983
 
29039
- installImportMetaCss(import.meta);import.meta.css = /* css */`
28984
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
29040
28985
  .navi_table_ui {
29041
28986
  position: fixed;
29042
28987
  inset: 0;
@@ -29045,7 +28990,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
29045
28990
  overflow: hidden; /* Ensure UI elements cannot impact scrollbars of the document */
29046
28991
  /* background: rgba(0, 255, 0, 0.2); */
29047
28992
  }
29048
- `;
28993
+ `, "/src/field/table/table_ui.jsx"];
29049
28994
  const TableUI = forwardRef((props, ref) => {
29050
28995
  const {
29051
28996
  tableRef,
@@ -29960,7 +29905,7 @@ const normalizeKey = (key) => {
29960
29905
  return key;
29961
29906
  };
29962
29907
 
29963
- installImportMetaCss(import.meta);import.meta.css = /* css */`
29908
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
29964
29909
  .navi_shortcut_container[data-visually-hidden] {
29965
29910
  /* Visually hidden container - doesn't affect layout */
29966
29911
  position: absolute;
@@ -29994,7 +29939,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
29994
29939
  opacity: 0;
29995
29940
  pointer-events: none;
29996
29941
  }
29997
- `;
29942
+ `, "/src/keyboard/active_keyboard_shortcuts.jsx"];
29998
29943
  const ActiveKeyboardShortcuts = ({
29999
29944
  visible
30000
29945
  }) => {
@@ -30036,7 +29981,7 @@ const KeyboardShortcutAriaElement = ({
30036
29981
  });
30037
29982
  };
30038
29983
 
30039
- installImportMetaCss(import.meta);import.meta.css = /* css */`
29984
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
30040
29985
  @layer navi {
30041
29986
  .navi_clipboard_container {
30042
29987
  --height: 1.5em;
@@ -30063,7 +30008,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
30063
30008
  transform: translateY(-100%);
30064
30009
  }
30065
30010
  }
30066
- `;
30011
+ `, "/src/field/button_copy_to_clipboard.jsx"];
30067
30012
  const ButtonCopyToClipboard = ({
30068
30013
  children,
30069
30014
  ...props
@@ -30148,7 +30093,7 @@ const Address = ({
30148
30093
  });
30149
30094
  };
30150
30095
 
30151
- installImportMetaCss(import.meta);import.meta.css = /* css */`
30096
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
30152
30097
  @layer navi {
30153
30098
  }
30154
30099
  .navi_badge {
@@ -30176,7 +30121,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
30176
30121
  --x-color-contrasting: var(--navi-color-white);
30177
30122
  }
30178
30123
  }
30179
- `;
30124
+ `, "/src/text/badge.jsx"];
30180
30125
  const BadgeStyleCSSVars$1 = {
30181
30126
  borderWidth: "--border-width",
30182
30127
  borderRadius: "--border-radius",
@@ -30271,7 +30216,7 @@ const formatNumber = (value, { lang } = {}) => {
30271
30216
  return new Intl.NumberFormat(lang).format(value);
30272
30217
  };
30273
30218
 
30274
- installImportMetaCss(import.meta);import.meta.css = /* css */`
30219
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
30275
30220
  @layer navi {
30276
30221
  }
30277
30222
  .navi_badge_count {
@@ -30360,7 +30305,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
30360
30305
  }
30361
30306
  }
30362
30307
  }
30363
- `;
30308
+ `, "/src/text/badge_count.jsx"];
30364
30309
  const BadgeStyleCSSVars = {
30365
30310
  borderWidth: "--border-width",
30366
30311
  borderRadius: "--border-radius",
@@ -30519,7 +30464,7 @@ const BadgeCountCircle = ({
30519
30464
  });
30520
30465
  };
30521
30466
 
30522
- installImportMetaCss(import.meta);import.meta.css = /* css */`
30467
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
30523
30468
  @layer navi {
30524
30469
  .navi_caption {
30525
30470
  --color: #6b7280;
@@ -30535,7 +30480,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
30535
30480
  .navi_caption {
30536
30481
  color: var(--color);
30537
30482
  }
30538
- `;
30483
+ `, "/src/text/caption.jsx"];
30539
30484
  const CaptionStyleCSSVars = {
30540
30485
  color: "--color"
30541
30486
  };
@@ -30547,6 +30492,7 @@ const Caption = ({
30547
30492
  as: "small",
30548
30493
  size: "0.8em" // We use em to be relative to the parent (we want to be smaller than the surrounding text)
30549
30494
  ,
30495
+
30550
30496
  className: withPropsClassName("navi_caption", className),
30551
30497
  ...rest,
30552
30498
  styleCSSVars: CaptionStyleCSSVars
@@ -30919,7 +30865,7 @@ const interpolate = (template, values) => {
30919
30865
  });
30920
30866
  };
30921
30867
 
30922
- installImportMetaCss(import.meta);import.meta.css = /* css */`
30868
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
30923
30869
  @layer navi {
30924
30870
  .navi_quantity {
30925
30871
  --unit-color: color-mix(in srgb, currentColor 50%, white);
@@ -30975,7 +30921,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
30975
30921
  }
30976
30922
  }
30977
30923
  }
30978
- `;
30924
+ `, "/src/text/quantity.jsx"];
30979
30925
  const QuantityIntl = createIntl();
30980
30926
  const wellKnownUnitMap = new Map();
30981
30927
  /**
@@ -31112,7 +31058,7 @@ const parseQuantityValue = children => {
31112
31058
  return Number.isNaN(parsed) ? children : parsed;
31113
31059
  };
31114
31060
 
31115
- installImportMetaCss(import.meta);import.meta.css = /* css */`
31061
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
31116
31062
  @layer navi {
31117
31063
  .navi_meter {
31118
31064
  --loader-color: var(--navi-loader-color);
@@ -31229,7 +31175,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
31229
31175
  }
31230
31176
  }
31231
31177
  }
31232
- `;
31178
+ `, "/src/text/meter.jsx"];
31233
31179
  const MeterStyleCSSVars = {
31234
31180
  trackColor: "--track-color",
31235
31181
  borderColor: "--border-color",
@@ -31376,7 +31322,7 @@ const Paragraph = props => {
31376
31322
  });
31377
31323
  };
31378
31324
 
31379
- installImportMetaCss(import.meta);import.meta.css = /* css */`
31325
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
31380
31326
  .navi_text_placeholder {
31381
31327
  display: inline-block;
31382
31328
  width: 100%;
@@ -31397,7 +31343,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
31397
31343
  background-position: -200% 0;
31398
31344
  }
31399
31345
  }
31400
- `;
31346
+ `, "/src/text/text_placeholder.jsx"];
31401
31347
  const TextPlaceholder = ({
31402
31348
  loading,
31403
31349
  ...props
@@ -31423,7 +31369,41 @@ const Svg = props => {
31423
31369
  });
31424
31370
  };
31425
31371
 
31426
- installImportMetaCss(import.meta);import.meta.css = /* css */`
31372
+ installImportMetaCssBuild(import.meta);/**
31373
+ * SVGComposition Component
31374
+ *
31375
+ * Creates composite SVGs by combining independent SVG elements with masking.
31376
+ *
31377
+ * This component solves the challenge of combining independently created SVGs into
31378
+ * a single visual composition. Each SVG can have its own coordinate system, viewBox,
31379
+ * and styling, allowing for maximum reusability of individual icons or graphics.
31380
+ *
31381
+ * When overlaying SVGs, each subsequent overlay "cuts out" its portion from the base SVG,
31382
+ * creating a seamless integration where SVGs appear to interact with each other visually.
31383
+ *
31384
+ * Key benefits:
31385
+ * - Maintains each SVG's independence - use them individually elsewhere
31386
+ * - Handles different viewBox dimensions automatically
31387
+ * - Works with any SVG components regardless of internal implementation
31388
+ * - Supports unlimited overlay elements
31389
+ * - Creates proper masking between elements for visual integration
31390
+ *
31391
+ * Usage example combining two independent icon components:
31392
+ * ```jsx
31393
+ * <SVGMaskOverlay viewBox="0 0 24 24">
31394
+ * <DatabaseSvg />
31395
+ * <svg x="12" y="12" width="16" height="16" overflow="visible">
31396
+ * <PlusSvg />
31397
+ * </svg>
31398
+ * </SVGMaskOverlay>
31399
+ * ```
31400
+ *
31401
+ * @param {Object} props - Component properties
31402
+ * @param {string} props.viewBox - The main viewBox for the composition (required)
31403
+ * @param {ReactNode[]} props.children - SVG elements (first is base, rest are overlays)
31404
+ * @returns {ReactElement} A composed SVG with all elements properly masked
31405
+ */
31406
+ import.meta.css = [/* css */`
31427
31407
  .svg_mask_content * {
31428
31408
  color: black !important;
31429
31409
  opacity: 1 !important;
@@ -31432,7 +31412,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
31432
31412
  stroke: black !important;
31433
31413
  stroke-opacity: 1 !important;
31434
31414
  }
31435
- `;
31415
+ `, "/src/graphic/svg_mask_overlay.jsx"];
31436
31416
  const SVGMaskOverlay = ({
31437
31417
  viewBox,
31438
31418
  children
@@ -31489,7 +31469,8 @@ const SVGMaskOverlay = ({
31489
31469
  });
31490
31470
  };
31491
31471
 
31492
- installImportMetaCss(import.meta);import.meta.css = /* css */`
31472
+ installImportMetaCssBuild(import.meta);// We HAVE TO put paddings around the dialog to ensure window resizing respects this space
31473
+ import.meta.css = [/* css */`
31493
31474
  @layer navi {
31494
31475
  .navi_dialog_layout {
31495
31476
  --layout-margin: 30px;
@@ -31547,7 +31528,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
31547
31528
  border-color: var(--layout-border-color);
31548
31529
  border-radius: var(--layout-border-radius);
31549
31530
  }
31550
- `;
31531
+ `, "/src/layout/dialog_layout.jsx"];
31551
31532
  const DialogLayoutStyleCSSVars = {
31552
31533
  margin: "--layout-margin",
31553
31534
  marginTop: "--layout-margin-top",
@@ -31588,7 +31569,7 @@ const DialogLayout = ({
31588
31569
  });
31589
31570
  };
31590
31571
 
31591
- installImportMetaCss(import.meta);import.meta.css = /* css */`
31572
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
31592
31573
  @layer navi {
31593
31574
  .navi_separator {
31594
31575
  --size: 1px;
@@ -31620,7 +31601,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
31620
31601
  vertical-align: bottom;
31621
31602
  }
31622
31603
  }
31623
- `;
31604
+ `, "/src/layout/separator.jsx"];
31624
31605
  const SeparatorStyleCSSVars = {
31625
31606
  color: "--color"
31626
31607
  };
@@ -31637,7 +31618,7 @@ const Separator = ({
31637
31618
  });
31638
31619
  };
31639
31620
 
31640
- installImportMetaCss(import.meta);import.meta.css = /* css */`
31621
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
31641
31622
  @layer navi {
31642
31623
  .navi_viewport_layout {
31643
31624
  --layout-padding: 40px;
@@ -31664,7 +31645,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
31664
31645
  );
31665
31646
  background: var(--layout-background);
31666
31647
  }
31667
- `;
31648
+ `, "/src/layout/viewport_layout.jsx"];
31668
31649
  const ViewportLayoutStyleCSSVars = {
31669
31650
  padding: "--layout-padding",
31670
31651
  paddingTop: "--layout-padding-top",
@@ -31684,7 +31665,7 @@ const ViewportLayout = props => {
31684
31665
  });
31685
31666
  };
31686
31667
 
31687
- installImportMetaCss(import.meta);import.meta.css = /* css */`
31668
+ installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
31688
31669
  @layer navi {
31689
31670
  .navi_side_panel {
31690
31671
  --side-panel-width: 400px;
@@ -31781,7 +31762,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
31781
31762
  transform: translateX(100%);
31782
31763
  }
31783
31764
  }
31784
- `;
31765
+ `, "/src/popover/side_panel.jsx"];
31785
31766
  const SidePanelCloseContext = createContext(null);
31786
31767
  const useSidePanelClose = () => useContext(SidePanelCloseContext);
31787
31768
  const SidePanelStyleCSSVars = {