@jsenv/navi 0.16.57 → 0.16.59
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.
- package/dist/jsenv_navi.js +1545 -1313
- package/dist/jsenv_navi.js.map +151 -138
- package/package.json +2 -2
package/dist/jsenv_navi.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { installImportMetaCss } from "./jsenv_navi_side_effects.js";
|
|
2
2
|
import { useErrorBoundary, useLayoutEffect, useEffect, useCallback, useRef, useState, useContext, useMemo, useImperativeHandle, useId } from "preact/hooks";
|
|
3
3
|
import { jsxs, jsx, Fragment } from "preact/jsx-runtime";
|
|
4
|
-
import { createIterableWeakSet, mergeOneStyle, stringifyStyle, createPubSub, mergeTwoStyles, normalizeStyles, createGroupTransitionController, getElementSignature, getBorderRadius, preventIntermediateScrollbar, createOpacityTransition,
|
|
4
|
+
import { createIterableWeakSet, mergeOneStyle, stringifyStyle, createPubSub, mergeTwoStyles, normalizeStyles, createGroupTransitionController, getElementSignature, getBorderRadius, preventIntermediateScrollbar, createOpacityTransition, findBefore, findAfter, createValueEffect, getVisuallyVisibleInfo, getFirstVisuallyVisibleAncestor, allowWheelThrough, resolveCSSColor, createStyleController, visibleRectEffect, pickPositionRelativeTo, getBorderSizes, getPaddingSizes, hasCSSSizeUnit, resolveCSSSize, activeElementSignal, canInterceptKeys, pickLightOrDark, resolveColorLuminance, initFocusGroup, dragAfterThreshold, getScrollContainer, stickyAsRelativeCoords, createDragToMoveGestureController, getDropTargetInfo, setStyles, useActiveElement, elementIsFocusable } from "@jsenv/dom";
|
|
5
5
|
import { prefixFirstAndIndentRemainingLines } from "@jsenv/humanize";
|
|
6
6
|
import { effect, signal, computed, batch, useSignal } from "@preact/signals";
|
|
7
7
|
import { createValidity } from "@jsenv/validity";
|
|
@@ -1448,6 +1448,7 @@ const createAction = (callback, rootOptions = {}) => {
|
|
|
1448
1448
|
for (const key of keyArray) {
|
|
1449
1449
|
const signalForThisKey = signalMap.get(key);
|
|
1450
1450
|
if (signalForThisKey) {
|
|
1451
|
+
// eslint-disable-next-line signals/no-conditional-value-read
|
|
1451
1452
|
params[key] = signalForThisKey.value;
|
|
1452
1453
|
} else {
|
|
1453
1454
|
params[key] = staticParams[key];
|
|
@@ -6306,7 +6307,7 @@ const Box = props => {
|
|
|
6306
6307
|
// then we'll track ":hover" state changes even for basic elements like <div>
|
|
6307
6308
|
const pseudoClassesFromStyleSet = new Set();
|
|
6308
6309
|
boxPseudoNamedStyles = {};
|
|
6309
|
-
const
|
|
6310
|
+
const visitProp = (value, name, styleContext, boxStylesTarget, styleOrigin) => {
|
|
6310
6311
|
const isPseudoElement = name.startsWith("::");
|
|
6311
6312
|
const isPseudoClass = name.startsWith(":");
|
|
6312
6313
|
if (isPseudoElement || isPseudoClass) {
|
|
@@ -6324,14 +6325,14 @@ const Box = props => {
|
|
|
6324
6325
|
if (isPseudoElement) {
|
|
6325
6326
|
const pseudoElementStyles = {};
|
|
6326
6327
|
for (const key of pseudoStyleKeys) {
|
|
6327
|
-
|
|
6328
|
+
visitProp(value[key], key, pseudoStyleContext, pseudoElementStyles, "pseudo_style");
|
|
6328
6329
|
}
|
|
6329
6330
|
boxPseudoNamedStyles[name] = pseudoElementStyles;
|
|
6330
6331
|
return;
|
|
6331
6332
|
}
|
|
6332
6333
|
const pseudoClassStyles = {};
|
|
6333
6334
|
for (const key of pseudoStyleKeys) {
|
|
6334
|
-
|
|
6335
|
+
visitProp(value[key], key, pseudoStyleContext, pseudoClassStyles, "pseudo_style");
|
|
6335
6336
|
boxPseudoNamedStyles[name] = pseudoClassStyles;
|
|
6336
6337
|
}
|
|
6337
6338
|
return;
|
|
@@ -6395,23 +6396,28 @@ const Box = props => {
|
|
|
6395
6396
|
if (baseStyle) {
|
|
6396
6397
|
for (const key of baseStyle) {
|
|
6397
6398
|
const value = baseStyle[key];
|
|
6398
|
-
|
|
6399
|
+
visitProp(value, key, styleContext, boxStyles, "baseStyle");
|
|
6399
6400
|
}
|
|
6400
6401
|
}
|
|
6401
6402
|
for (const propName of remainingPropKeySet) {
|
|
6402
6403
|
const propValue = rest[propName];
|
|
6403
|
-
|
|
6404
|
+
const isDataAttribute = propName.startsWith("data-");
|
|
6405
|
+
if (isDataAttribute) {
|
|
6406
|
+
selfForwardedProps[propName] = propValue;
|
|
6407
|
+
continue;
|
|
6408
|
+
}
|
|
6409
|
+
visitProp(propValue, propName, styleContext, boxStyles, "prop");
|
|
6404
6410
|
}
|
|
6405
6411
|
if (typeof style === "string") {
|
|
6406
6412
|
const styleObject = normalizeStyles(style, "css");
|
|
6407
6413
|
for (const styleName of Object.keys(styleObject)) {
|
|
6408
6414
|
const styleValue = styleObject[styleName];
|
|
6409
|
-
|
|
6415
|
+
visitProp(styleValue, styleName, styleContext, boxStyles, "style");
|
|
6410
6416
|
}
|
|
6411
6417
|
} else if (style && typeof style === "object") {
|
|
6412
6418
|
for (const styleName of Object.keys(style)) {
|
|
6413
6419
|
const styleValue = style[styleName];
|
|
6414
|
-
|
|
6420
|
+
visitProp(styleValue, styleName, styleContext, boxStyles, "style");
|
|
6415
6421
|
}
|
|
6416
6422
|
}
|
|
6417
6423
|
const updateStyle = useCallback(state => {
|
|
@@ -12097,691 +12103,141 @@ const renderActionableComponent = (props, {
|
|
|
12097
12103
|
});
|
|
12098
12104
|
};
|
|
12099
12105
|
|
|
12100
|
-
|
|
12101
|
-
|
|
12102
|
-
|
|
12103
|
-
|
|
12104
|
-
|
|
12105
|
-
|
|
12106
|
-
|
|
12107
|
-
|
|
12108
|
-
|
|
12109
|
-
|
|
12110
|
-
|
|
12111
|
-
|
|
12112
|
-
|
|
12113
|
-
|
|
12114
|
-
|
|
12115
|
-
|
|
12116
|
-
|
|
12117
|
-
|
|
12118
|
-
|
|
12119
|
-
|
|
12120
|
-
|
|
12121
|
-
|
|
12122
|
-
|
|
12123
|
-
|
|
12124
|
-
|
|
12125
|
-
|
|
12126
|
-
|
|
12127
|
-
|
|
12128
|
-
}
|
|
12106
|
+
/**
|
|
12107
|
+
* Custom hook creating a stable callback that doesn't trigger re-renders.
|
|
12108
|
+
*
|
|
12109
|
+
* PROBLEM: Parent components often forget to use useCallback, causing library
|
|
12110
|
+
* components to re-render unnecessarily when receiving callback props.
|
|
12111
|
+
*
|
|
12112
|
+
* SOLUTION: Library components can use this hook to create stable callback
|
|
12113
|
+
* references internally, making them defensive against parents who don't
|
|
12114
|
+
* optimize their callbacks. This ensures library components don't force
|
|
12115
|
+
* consumers to think about useCallback.
|
|
12116
|
+
*
|
|
12117
|
+
* USAGE:
|
|
12118
|
+
* ```js
|
|
12119
|
+
* // Parent component (consumer) - no useCallback needed
|
|
12120
|
+
* const Parent = () => {
|
|
12121
|
+
* const [count, setCount] = useState(0);
|
|
12122
|
+
*
|
|
12123
|
+
* // Parent naturally creates new function reference each render
|
|
12124
|
+
* // (forgetting useCallback is common and shouldn't break performance)
|
|
12125
|
+
* return <LibraryButton onClick={(e) => setCount(count + 1)} />;
|
|
12126
|
+
* };
|
|
12127
|
+
*
|
|
12128
|
+
* // Library component - defensive against changing callbacks
|
|
12129
|
+
* const LibraryButton = ({ onClick }) => {
|
|
12130
|
+
* // ✅ Create stable reference from parent's potentially changing callback
|
|
12131
|
+
* const stableClick = useStableCallback(onClick);
|
|
12132
|
+
*
|
|
12133
|
+
* // Internal expensive components won't re-render when parent updates
|
|
12134
|
+
* return <ExpensiveInternalButton onClick={stableClick} />;
|
|
12135
|
+
* };
|
|
12136
|
+
*
|
|
12137
|
+
* // Deep internal component gets stable reference
|
|
12138
|
+
* const ExpensiveInternalButton = memo(({ onClick }) => {
|
|
12139
|
+
* // This won't re-render when Parent's count changes
|
|
12140
|
+
* // But onClick will always call the latest Parent callback
|
|
12141
|
+
* return <button onClick={onClick}>Click me</button>;
|
|
12142
|
+
* });
|
|
12143
|
+
* ```
|
|
12144
|
+
*
|
|
12145
|
+
* Perfect for library components that need performance without burdening consumers.
|
|
12146
|
+
*/
|
|
12129
12147
|
|
|
12130
|
-
const useNetworkSpeed = () => {
|
|
12131
|
-
return networkSpeedSignal.value;
|
|
12132
|
-
};
|
|
12133
12148
|
|
|
12134
|
-
const
|
|
12135
|
-
|
|
12136
|
-
|
|
12137
|
-
|
|
12149
|
+
const useStableCallback = (callback, mapper) => {
|
|
12150
|
+
const callbackRef = useRef();
|
|
12151
|
+
callbackRef.current = callback;
|
|
12152
|
+
const stableCallbackRef = useRef();
|
|
12138
12153
|
|
|
12139
|
-
|
|
12140
|
-
|
|
12141
|
-
|
|
12142
|
-
return "3g";
|
|
12143
|
-
}
|
|
12144
|
-
if (connection) {
|
|
12145
|
-
const effectiveType = connection.effectiveType;
|
|
12146
|
-
if (effectiveType) {
|
|
12147
|
-
return effectiveType; // "slow-2g", "2g", "3g", "4g", "5g"
|
|
12148
|
-
}
|
|
12149
|
-
const downlink = connection.downlink;
|
|
12150
|
-
if (downlink) {
|
|
12151
|
-
// downlink is in Mbps
|
|
12152
|
-
if (downlink < 1) return "slow-2g"; // < 1 Mbps
|
|
12153
|
-
if (downlink < 2.5) return "2g"; // 1-2.5 Mbps
|
|
12154
|
-
if (downlink < 10) return "3g"; // 2.5-10 Mbps
|
|
12155
|
-
return "4g"; // > 10 Mbps
|
|
12156
|
-
}
|
|
12154
|
+
// Return original falsy value directly when callback is not a function
|
|
12155
|
+
if (!callback) {
|
|
12156
|
+
return callback;
|
|
12157
12157
|
}
|
|
12158
|
-
return "3g";
|
|
12159
|
-
};
|
|
12160
|
-
|
|
12161
|
-
const updateNetworkSpeed = () => {
|
|
12162
|
-
networkSpeedSignal.value = getNetworkSpeed();
|
|
12163
|
-
};
|
|
12164
|
-
|
|
12165
|
-
const networkSpeedSignal = signal(getNetworkSpeed());
|
|
12166
12158
|
|
|
12167
|
-
const
|
|
12168
|
-
|
|
12169
|
-
|
|
12170
|
-
// ✅ 1. Écouter les changements natifs
|
|
12171
|
-
|
|
12172
|
-
if (connection) {
|
|
12173
|
-
connection.addEventListener("change", updateNetworkSpeed);
|
|
12174
|
-
cleanupFunctions.push(() => {
|
|
12175
|
-
connection.removeEventListener("change", updateNetworkSpeed);
|
|
12176
|
-
});
|
|
12159
|
+
const existingStableCallback = stableCallbackRef.current;
|
|
12160
|
+
if (existingStableCallback) {
|
|
12161
|
+
return existingStableCallback;
|
|
12177
12162
|
}
|
|
12178
|
-
|
|
12179
|
-
|
|
12180
|
-
|
|
12181
|
-
cleanupFunctions.push(() => clearInterval(pollInterval));
|
|
12182
|
-
|
|
12183
|
-
// ✅ 3. Vérifier lors de la reprise d'activité
|
|
12184
|
-
const handleVisibilityChange = () => {
|
|
12185
|
-
if (!document.hidden) {
|
|
12186
|
-
updateNetworkSpeed();
|
|
12187
|
-
}
|
|
12188
|
-
};
|
|
12189
|
-
|
|
12190
|
-
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
12191
|
-
cleanupFunctions.push(() => {
|
|
12192
|
-
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
12193
|
-
});
|
|
12194
|
-
|
|
12195
|
-
// ✅ 4. Vérifier lors de la reprise de connexion
|
|
12196
|
-
const handleOnline = () => {
|
|
12197
|
-
updateNetworkSpeed();
|
|
12198
|
-
};
|
|
12199
|
-
|
|
12200
|
-
window.addEventListener("online", handleOnline);
|
|
12201
|
-
cleanupFunctions.push(() => {
|
|
12202
|
-
window.removeEventListener("online", handleOnline);
|
|
12203
|
-
});
|
|
12204
|
-
|
|
12205
|
-
// Cleanup global
|
|
12206
|
-
return () => {
|
|
12207
|
-
cleanupFunctions.forEach((cleanup) => cleanup());
|
|
12163
|
+
const stableCallback = (...args) => {
|
|
12164
|
+
const currentCallback = callbackRef.current;
|
|
12165
|
+
return currentCallback(...args);
|
|
12208
12166
|
};
|
|
12167
|
+
stableCallbackRef.current = stableCallback;
|
|
12168
|
+
return stableCallback;
|
|
12209
12169
|
};
|
|
12210
|
-
setupNetworkMonitoring();
|
|
12211
|
-
|
|
12212
|
-
installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
12213
|
-
.navi_rectangle_loading {
|
|
12214
|
-
position: relative;
|
|
12215
|
-
display: flex;
|
|
12216
|
-
width: 100%;
|
|
12217
|
-
height: 100%;
|
|
12218
|
-
opacity: 0;
|
|
12219
|
-
}
|
|
12220
12170
|
|
|
12221
|
-
|
|
12222
|
-
|
|
12171
|
+
const DEBUG = {
|
|
12172
|
+
registration: false,
|
|
12173
|
+
// Element registration/unregistration
|
|
12174
|
+
interaction: false,
|
|
12175
|
+
// Click and keyboard interactions
|
|
12176
|
+
selection: false,
|
|
12177
|
+
// Selection state changes (set, add, remove, toggle)
|
|
12178
|
+
navigation: false,
|
|
12179
|
+
// Arrow key navigation and element finding
|
|
12180
|
+
valueExtraction: false // Value extraction from elements
|
|
12181
|
+
};
|
|
12182
|
+
const debug = (category, ...args) => {
|
|
12183
|
+
if (DEBUG[category]) {
|
|
12184
|
+
console.debug(`[selection:${category}]`, ...args);
|
|
12223
12185
|
}
|
|
12224
|
-
|
|
12225
|
-
const
|
|
12226
|
-
|
|
12227
|
-
|
|
12228
|
-
|
|
12229
|
-
|
|
12186
|
+
};
|
|
12187
|
+
const SelectionContext = createContext();
|
|
12188
|
+
const useSelectionController = ({
|
|
12189
|
+
elementRef,
|
|
12190
|
+
layout,
|
|
12191
|
+
value,
|
|
12192
|
+
onChange,
|
|
12193
|
+
multiple,
|
|
12194
|
+
selectAllName
|
|
12230
12195
|
}) => {
|
|
12231
|
-
|
|
12232
|
-
|
|
12233
|
-
|
|
12196
|
+
if (!elementRef) {
|
|
12197
|
+
throw new Error("useSelectionController: elementRef is required");
|
|
12198
|
+
}
|
|
12199
|
+
onChange = useStableCallback(onChange);
|
|
12200
|
+
const currentValueRef = useRef(value);
|
|
12201
|
+
currentValueRef.current = value;
|
|
12202
|
+
const lastInternalValueRef = useRef(null);
|
|
12203
|
+
const selectionController = useMemo(() => {
|
|
12204
|
+
const innerOnChange = (newValue, ...args) => {
|
|
12205
|
+
lastInternalValueRef.current = newValue;
|
|
12206
|
+
onChange?.(newValue, ...args);
|
|
12207
|
+
};
|
|
12208
|
+
const getCurrentValue = () => currentValueRef.current;
|
|
12209
|
+
if (layout === "grid") {
|
|
12210
|
+
return createGridSelectionController({
|
|
12211
|
+
getCurrentValue,
|
|
12212
|
+
onChange: innerOnChange,
|
|
12213
|
+
enabled: Boolean(onChange),
|
|
12214
|
+
multiple,
|
|
12215
|
+
selectAllName
|
|
12216
|
+
});
|
|
12217
|
+
}
|
|
12218
|
+
return createLinearSelectionController({
|
|
12219
|
+
getCurrentValue,
|
|
12220
|
+
onChange: innerOnChange,
|
|
12221
|
+
layout,
|
|
12222
|
+
elementRef,
|
|
12223
|
+
multiple,
|
|
12224
|
+
enabled: Boolean(onChange),
|
|
12225
|
+
selectAllName
|
|
12226
|
+
});
|
|
12227
|
+
}, [layout, multiple, elementRef]);
|
|
12228
|
+
useEffect(() => {
|
|
12229
|
+
selectionController.element = elementRef.current;
|
|
12230
|
+
}, [selectionController]);
|
|
12234
12231
|
useLayoutEffect(() => {
|
|
12235
|
-
|
|
12236
|
-
|
|
12237
|
-
|
|
12238
|
-
|
|
12239
|
-
|
|
12240
|
-
|
|
12241
|
-
|
|
12242
|
-
|
|
12243
|
-
|
|
12244
|
-
setContainerHeight(height);
|
|
12245
|
-
let animationFrameId = null;
|
|
12246
|
-
// Create a resize observer to detect changes in the container's dimensions
|
|
12247
|
-
const resizeObserver = new ResizeObserver(entries => {
|
|
12248
|
-
// Use requestAnimationFrame to debounce updates
|
|
12249
|
-
if (animationFrameId) {
|
|
12250
|
-
cancelAnimationFrame(animationFrameId);
|
|
12251
|
-
}
|
|
12252
|
-
animationFrameId = requestAnimationFrame(() => {
|
|
12253
|
-
const [containerEntry] = entries;
|
|
12254
|
-
const {
|
|
12255
|
-
width,
|
|
12256
|
-
height
|
|
12257
|
-
} = containerEntry.contentRect;
|
|
12258
|
-
setContainerWidth(width);
|
|
12259
|
-
setContainerHeight(height);
|
|
12260
|
-
});
|
|
12261
|
-
});
|
|
12262
|
-
resizeObserver.observe(container);
|
|
12263
|
-
return () => {
|
|
12264
|
-
if (animationFrameId) {
|
|
12265
|
-
cancelAnimationFrame(animationFrameId);
|
|
12266
|
-
}
|
|
12267
|
-
resizeObserver.disconnect();
|
|
12268
|
-
};
|
|
12269
|
-
}, []);
|
|
12270
|
-
return jsx("span", {
|
|
12271
|
-
ref: containerRef,
|
|
12272
|
-
className: "navi_rectangle_loading",
|
|
12273
|
-
"data-visible": shouldShowSpinner ? "" : undefined,
|
|
12274
|
-
children: containerWidth > 0 && containerHeight > 0 && jsx(RectangleLoadingSvg, {
|
|
12275
|
-
radius: radius,
|
|
12276
|
-
color: color,
|
|
12277
|
-
width: containerWidth,
|
|
12278
|
-
height: containerHeight,
|
|
12279
|
-
strokeWidth: size
|
|
12280
|
-
})
|
|
12281
|
-
});
|
|
12282
|
-
};
|
|
12283
|
-
const RectangleLoadingSvg = ({
|
|
12284
|
-
width,
|
|
12285
|
-
height,
|
|
12286
|
-
color,
|
|
12287
|
-
radius,
|
|
12288
|
-
trailColor = "transparent",
|
|
12289
|
-
strokeWidth
|
|
12290
|
-
}) => {
|
|
12291
|
-
const margin = Math.max(2, Math.min(width, height) * 0.03);
|
|
12292
|
-
|
|
12293
|
-
// Calculate the drawable area
|
|
12294
|
-
const drawableWidth = width - margin * 2;
|
|
12295
|
-
const drawableHeight = height - margin * 2;
|
|
12296
|
-
|
|
12297
|
-
// ✅ Check if this should be a circle - only if width and height are nearly equal
|
|
12298
|
-
const maxPossibleRadius = Math.min(drawableWidth, drawableHeight) / 2;
|
|
12299
|
-
const actualRadius = Math.min(radius || Math.min(drawableWidth, drawableHeight) * 0.05, maxPossibleRadius // ✅ Limité au radius maximum possible
|
|
12300
|
-
);
|
|
12301
|
-
const aspectRatio = Math.max(drawableWidth, drawableHeight) / Math.min(drawableWidth, drawableHeight);
|
|
12302
|
-
const isNearlySquare = aspectRatio <= 1.2; // Allow some tolerance for nearly square shapes
|
|
12303
|
-
const isCircle = isNearlySquare && actualRadius >= maxPossibleRadius * 0.95;
|
|
12304
|
-
let pathLength;
|
|
12305
|
-
let rectPath;
|
|
12306
|
-
if (isCircle) {
|
|
12307
|
-
// ✅ Circle: perimeter = 2πr
|
|
12308
|
-
pathLength = 2 * Math.PI * actualRadius;
|
|
12309
|
-
|
|
12310
|
-
// ✅ Circle path centered in the drawable area
|
|
12311
|
-
const centerX = margin + drawableWidth / 2;
|
|
12312
|
-
const centerY = margin + drawableHeight / 2;
|
|
12313
|
-
rectPath = `
|
|
12314
|
-
M ${centerX + actualRadius},${centerY}
|
|
12315
|
-
A ${actualRadius},${actualRadius} 0 1 1 ${centerX - actualRadius},${centerY}
|
|
12316
|
-
A ${actualRadius},${actualRadius} 0 1 1 ${centerX + actualRadius},${centerY}
|
|
12317
|
-
`;
|
|
12318
|
-
} else {
|
|
12319
|
-
// ✅ Rectangle: calculate perimeter properly
|
|
12320
|
-
const straightEdges = 2 * (drawableWidth - 2 * actualRadius) + 2 * (drawableHeight - 2 * actualRadius);
|
|
12321
|
-
const cornerArcs = actualRadius > 0 ? 2 * Math.PI * actualRadius : 0;
|
|
12322
|
-
pathLength = straightEdges + cornerArcs;
|
|
12323
|
-
rectPath = `
|
|
12324
|
-
M ${margin + actualRadius},${margin}
|
|
12325
|
-
L ${margin + drawableWidth - actualRadius},${margin}
|
|
12326
|
-
A ${actualRadius},${actualRadius} 0 0 1 ${margin + drawableWidth},${margin + actualRadius}
|
|
12327
|
-
L ${margin + drawableWidth},${margin + drawableHeight - actualRadius}
|
|
12328
|
-
A ${actualRadius},${actualRadius} 0 0 1 ${margin + drawableWidth - actualRadius},${margin + drawableHeight}
|
|
12329
|
-
L ${margin + actualRadius},${margin + drawableHeight}
|
|
12330
|
-
A ${actualRadius},${actualRadius} 0 0 1 ${margin},${margin + drawableHeight - actualRadius}
|
|
12331
|
-
L ${margin},${margin + actualRadius}
|
|
12332
|
-
A ${actualRadius},${actualRadius} 0 0 1 ${margin + actualRadius},${margin}
|
|
12333
|
-
`;
|
|
12334
|
-
}
|
|
12335
|
-
|
|
12336
|
-
// Fixed segment size in pixels
|
|
12337
|
-
const maxSegmentSize = 40;
|
|
12338
|
-
const segmentLength = Math.min(maxSegmentSize, pathLength * 0.25);
|
|
12339
|
-
const gapLength = pathLength - segmentLength;
|
|
12340
|
-
|
|
12341
|
-
// Vitesse constante en pixels par seconde
|
|
12342
|
-
const networkSpeed = useNetworkSpeed();
|
|
12343
|
-
const pixelsPerSecond = {
|
|
12344
|
-
"slow-2g": 40,
|
|
12345
|
-
"2g": 60,
|
|
12346
|
-
"3g": 80,
|
|
12347
|
-
"4g": 120
|
|
12348
|
-
}[networkSpeed] || 80;
|
|
12349
|
-
const animationDuration = Math.max(1.5, pathLength / pixelsPerSecond);
|
|
12350
|
-
|
|
12351
|
-
// ✅ Calculate correct offset based on actual segment size
|
|
12352
|
-
const segmentRatio = segmentLength / pathLength;
|
|
12353
|
-
const circleOffset = -animationDuration * segmentRatio;
|
|
12354
|
-
return jsxs("svg", {
|
|
12355
|
-
width: "100%",
|
|
12356
|
-
height: "100%",
|
|
12357
|
-
viewBox: `0 0 ${width} ${height}`,
|
|
12358
|
-
preserveAspectRatio: "none",
|
|
12359
|
-
style: "overflow: visible",
|
|
12360
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
12361
|
-
"shape-rendering": "geometricPrecision",
|
|
12362
|
-
children: [isCircle ? jsx("circle", {
|
|
12363
|
-
cx: margin + drawableWidth / 2,
|
|
12364
|
-
cy: margin + drawableHeight / 2,
|
|
12365
|
-
r: actualRadius,
|
|
12366
|
-
fill: "none",
|
|
12367
|
-
stroke: trailColor,
|
|
12368
|
-
strokeWidth: strokeWidth
|
|
12369
|
-
}) : jsx("rect", {
|
|
12370
|
-
x: margin,
|
|
12371
|
-
y: margin,
|
|
12372
|
-
width: drawableWidth,
|
|
12373
|
-
height: drawableHeight,
|
|
12374
|
-
fill: "none",
|
|
12375
|
-
stroke: trailColor,
|
|
12376
|
-
strokeWidth: strokeWidth,
|
|
12377
|
-
rx: actualRadius
|
|
12378
|
-
}), jsx("path", {
|
|
12379
|
-
d: rectPath,
|
|
12380
|
-
fill: "none",
|
|
12381
|
-
stroke: color,
|
|
12382
|
-
strokeWidth: strokeWidth,
|
|
12383
|
-
strokeLinecap: "round",
|
|
12384
|
-
strokeDasharray: `${segmentLength} ${gapLength}`,
|
|
12385
|
-
pathLength: pathLength,
|
|
12386
|
-
children: jsx("animate", {
|
|
12387
|
-
attributeName: "stroke-dashoffset",
|
|
12388
|
-
from: pathLength,
|
|
12389
|
-
to: "0",
|
|
12390
|
-
dur: `${animationDuration}s`,
|
|
12391
|
-
repeatCount: "indefinite",
|
|
12392
|
-
begin: "0s"
|
|
12393
|
-
})
|
|
12394
|
-
}), jsx("circle", {
|
|
12395
|
-
r: strokeWidth,
|
|
12396
|
-
fill: color,
|
|
12397
|
-
children: jsx("animateMotion", {
|
|
12398
|
-
path: rectPath,
|
|
12399
|
-
dur: `${animationDuration}s`,
|
|
12400
|
-
repeatCount: "indefinite",
|
|
12401
|
-
rotate: "auto",
|
|
12402
|
-
begin: `${circleOffset}s`
|
|
12403
|
-
})
|
|
12404
|
-
})]
|
|
12405
|
-
});
|
|
12406
|
-
};
|
|
12407
|
-
|
|
12408
|
-
installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
12409
|
-
.navi_loading_rectangle_wrapper {
|
|
12410
|
-
position: absolute;
|
|
12411
|
-
top: var(--rectangle-top, 0);
|
|
12412
|
-
right: var(--rectangle-right, 0);
|
|
12413
|
-
bottom: var(--rectangle-bottom, 0);
|
|
12414
|
-
left: var(--rectangle-left, 0);
|
|
12415
|
-
z-index: 1;
|
|
12416
|
-
opacity: 0;
|
|
12417
|
-
pointer-events: none;
|
|
12418
|
-
}
|
|
12419
|
-
.navi_loading_rectangle_wrapper[data-visible] {
|
|
12420
|
-
opacity: 1;
|
|
12421
|
-
}
|
|
12422
|
-
`;
|
|
12423
|
-
const LoaderBackground = ({
|
|
12424
|
-
loading,
|
|
12425
|
-
containerRef,
|
|
12426
|
-
targetSelector,
|
|
12427
|
-
color,
|
|
12428
|
-
inset = 0,
|
|
12429
|
-
spacingTop = 0,
|
|
12430
|
-
spacingLeft = 0,
|
|
12431
|
-
spacingBottom = 0,
|
|
12432
|
-
spacingRight = 0,
|
|
12433
|
-
children
|
|
12434
|
-
}) => {
|
|
12435
|
-
if (containerRef) {
|
|
12436
|
-
const container = containerRef.current;
|
|
12437
|
-
if (!container) {
|
|
12438
|
-
return children;
|
|
12439
|
-
}
|
|
12440
|
-
return createPortal(jsx(LoaderBackgroundWithPortal, {
|
|
12441
|
-
container: container,
|
|
12442
|
-
loading: loading,
|
|
12443
|
-
color: color,
|
|
12444
|
-
inset: inset,
|
|
12445
|
-
spacingTop: spacingTop,
|
|
12446
|
-
spacingLeft: spacingLeft,
|
|
12447
|
-
spacingBottom: spacingBottom,
|
|
12448
|
-
spacingRight: spacingRight,
|
|
12449
|
-
children: children
|
|
12450
|
-
}), container);
|
|
12451
|
-
}
|
|
12452
|
-
return jsx(LoaderBackgroundBasic, {
|
|
12453
|
-
targetSelector: targetSelector,
|
|
12454
|
-
loading: loading,
|
|
12455
|
-
color: color,
|
|
12456
|
-
inset: inset,
|
|
12457
|
-
spacingTop: spacingTop,
|
|
12458
|
-
spacingLeft: spacingLeft,
|
|
12459
|
-
spacingBottom: spacingBottom,
|
|
12460
|
-
spacingRight: spacingRight,
|
|
12461
|
-
children: children
|
|
12462
|
-
});
|
|
12463
|
-
};
|
|
12464
|
-
const LoaderBackgroundWithPortal = ({
|
|
12465
|
-
container,
|
|
12466
|
-
loading,
|
|
12467
|
-
color,
|
|
12468
|
-
inset,
|
|
12469
|
-
spacingTop,
|
|
12470
|
-
spacingLeft,
|
|
12471
|
-
spacingBottom,
|
|
12472
|
-
spacingRight,
|
|
12473
|
-
children
|
|
12474
|
-
}) => {
|
|
12475
|
-
const shouldShowSpinner = useDebounceTrue(loading, 300);
|
|
12476
|
-
if (!shouldShowSpinner) {
|
|
12477
|
-
return children;
|
|
12478
|
-
}
|
|
12479
|
-
container.style.position = "relative";
|
|
12480
|
-
let paddingTop = 0;
|
|
12481
|
-
if (container.nodeName === "DETAILS") {
|
|
12482
|
-
paddingTop = container.querySelector("summary").offsetHeight;
|
|
12483
|
-
}
|
|
12484
|
-
return jsxs(Fragment, {
|
|
12485
|
-
children: [jsx("div", {
|
|
12486
|
-
style: {
|
|
12487
|
-
position: "absolute",
|
|
12488
|
-
top: `${inset + paddingTop + spacingTop}px`,
|
|
12489
|
-
bottom: `${inset + spacingBottom}px`,
|
|
12490
|
-
left: `${inset + spacingLeft}px`,
|
|
12491
|
-
right: `${inset + spacingRight}px`
|
|
12492
|
-
},
|
|
12493
|
-
children: shouldShowSpinner && jsx(RectangleLoading, {
|
|
12494
|
-
color: color
|
|
12495
|
-
})
|
|
12496
|
-
}), children]
|
|
12497
|
-
});
|
|
12498
|
-
};
|
|
12499
|
-
const LoaderBackgroundBasic = ({
|
|
12500
|
-
loading,
|
|
12501
|
-
targetSelector,
|
|
12502
|
-
color,
|
|
12503
|
-
spacingTop,
|
|
12504
|
-
spacingLeft,
|
|
12505
|
-
spacingBottom,
|
|
12506
|
-
spacingRight,
|
|
12507
|
-
inset,
|
|
12508
|
-
children
|
|
12509
|
-
}) => {
|
|
12510
|
-
const shouldShowSpinner = useDebounceTrue(loading, 300);
|
|
12511
|
-
const rectangleRef = useRef(null);
|
|
12512
|
-
const [, setOutlineOffset] = useState(0);
|
|
12513
|
-
const [borderRadius, setBorderRadius] = useState(0);
|
|
12514
|
-
const [borderTopWidth, setBorderTopWidth] = useState(0);
|
|
12515
|
-
const [borderLeftWidth, setBorderLeftWidth] = useState(0);
|
|
12516
|
-
const [borderRightWidth, setBorderRightWidth] = useState(0);
|
|
12517
|
-
const [borderBottomWidth, setBorderBottomWidth] = useState(0);
|
|
12518
|
-
const [marginTop, setMarginTop] = useState(0);
|
|
12519
|
-
const [marginBottom, setMarginBottom] = useState(0);
|
|
12520
|
-
const [marginLeft, setMarginLeft] = useState(0);
|
|
12521
|
-
const [marginRight, setMarginRight] = useState(0);
|
|
12522
|
-
const [paddingTop, setPaddingTop] = useState(0);
|
|
12523
|
-
const [paddingLeft, setPaddingLeft] = useState(0);
|
|
12524
|
-
const [paddingRight, setPaddingRight] = useState(0);
|
|
12525
|
-
const [paddingBottom, setPaddingBottom] = useState(0);
|
|
12526
|
-
const [currentColor, setCurrentColor] = useState(color);
|
|
12527
|
-
useLayoutEffect(() => {
|
|
12528
|
-
let animationFrame;
|
|
12529
|
-
const updateStyles = () => {
|
|
12530
|
-
const rectangle = rectangleRef.current;
|
|
12531
|
-
if (!rectangle) {
|
|
12532
|
-
return;
|
|
12533
|
-
}
|
|
12534
|
-
const container = rectangle.parentElement;
|
|
12535
|
-
const containedElement = rectangle.nextElementSibling;
|
|
12536
|
-
const target = targetSelector ? container.querySelector(targetSelector) : containedElement;
|
|
12537
|
-
if (target) {
|
|
12538
|
-
const {
|
|
12539
|
-
width,
|
|
12540
|
-
height
|
|
12541
|
-
} = target.getBoundingClientRect();
|
|
12542
|
-
const containedComputedStyle = window.getComputedStyle(containedElement);
|
|
12543
|
-
const targetComputedStyle = window.getComputedStyle(target);
|
|
12544
|
-
const newBorderTopWidth = resolveCSSSize(targetComputedStyle.borderTopWidth);
|
|
12545
|
-
const newBorderLeftWidth = resolveCSSSize(targetComputedStyle.borderLeftWidth);
|
|
12546
|
-
const newBorderRightWidth = resolveCSSSize(targetComputedStyle.borderRightWidth);
|
|
12547
|
-
const newBorderBottomWidth = resolveCSSSize(targetComputedStyle.borderBottomWidth);
|
|
12548
|
-
const newBorderRadius = resolveCSSSize(targetComputedStyle.borderRadius, {
|
|
12549
|
-
availableSize: Math.min(width, height)
|
|
12550
|
-
});
|
|
12551
|
-
const newOutlineColor = targetComputedStyle.outlineColor;
|
|
12552
|
-
const newBorderColor = targetComputedStyle.borderColor;
|
|
12553
|
-
const newDetectedColor = targetComputedStyle.color;
|
|
12554
|
-
const newOutlineOffset = resolveCSSSize(targetComputedStyle.outlineOffset);
|
|
12555
|
-
const newMarginTop = resolveCSSSize(targetComputedStyle.marginTop);
|
|
12556
|
-
const newMarginBottom = resolveCSSSize(targetComputedStyle.marginBottom);
|
|
12557
|
-
const newMarginLeft = resolveCSSSize(targetComputedStyle.marginLeft);
|
|
12558
|
-
const newMarginRight = resolveCSSSize(targetComputedStyle.marginRight);
|
|
12559
|
-
const paddingTop = resolveCSSSize(containedComputedStyle.paddingTop);
|
|
12560
|
-
const paddingLeft = resolveCSSSize(containedComputedStyle.paddingLeft);
|
|
12561
|
-
const paddingRight = resolveCSSSize(containedComputedStyle.paddingRight);
|
|
12562
|
-
const paddingBottom = resolveCSSSize(containedComputedStyle.paddingBottom);
|
|
12563
|
-
setBorderTopWidth(newBorderTopWidth);
|
|
12564
|
-
setBorderLeftWidth(newBorderLeftWidth);
|
|
12565
|
-
setBorderRightWidth(newBorderRightWidth);
|
|
12566
|
-
setBorderBottomWidth(newBorderBottomWidth);
|
|
12567
|
-
setBorderRadius(newBorderRadius);
|
|
12568
|
-
setOutlineOffset(newOutlineOffset);
|
|
12569
|
-
setMarginTop(newMarginTop);
|
|
12570
|
-
setMarginBottom(newMarginBottom);
|
|
12571
|
-
setMarginLeft(newMarginLeft);
|
|
12572
|
-
setMarginRight(newMarginRight);
|
|
12573
|
-
setPaddingTop(paddingTop);
|
|
12574
|
-
setPaddingLeft(paddingLeft);
|
|
12575
|
-
setPaddingRight(paddingRight);
|
|
12576
|
-
setPaddingBottom(paddingBottom);
|
|
12577
|
-
if (color) {
|
|
12578
|
-
// const resolvedColor = resolveCSSColor(color, rectangle, "css");
|
|
12579
|
-
// console.log(resolvedColor);
|
|
12580
|
-
setCurrentColor(color);
|
|
12581
|
-
} else if (newOutlineColor && newOutlineColor !== "rgba(0, 0, 0, 0)" && (document.activeElement === containedElement || newBorderColor === "rgba(0, 0, 0, 0)")) {
|
|
12582
|
-
setCurrentColor(newOutlineColor);
|
|
12583
|
-
} else if (newBorderColor && newBorderColor !== "rgba(0, 0, 0, 0)") {
|
|
12584
|
-
setCurrentColor(newBorderColor);
|
|
12585
|
-
} else {
|
|
12586
|
-
setCurrentColor(newDetectedColor);
|
|
12587
|
-
}
|
|
12588
|
-
}
|
|
12589
|
-
// updateStyles is very cheap so we run it every frame
|
|
12590
|
-
animationFrame = requestAnimationFrame(updateStyles);
|
|
12591
|
-
};
|
|
12592
|
-
updateStyles();
|
|
12593
|
-
return () => {
|
|
12594
|
-
cancelAnimationFrame(animationFrame);
|
|
12595
|
-
};
|
|
12596
|
-
}, [color, targetSelector]);
|
|
12597
|
-
spacingTop += inset;
|
|
12598
|
-
// spacingTop += outlineOffset;
|
|
12599
|
-
// spacingTop -= borderTopWidth;
|
|
12600
|
-
spacingTop += marginTop;
|
|
12601
|
-
spacingLeft += inset;
|
|
12602
|
-
// spacingLeft += outlineOffset;
|
|
12603
|
-
// spacingLeft -= borderLeftWidth;
|
|
12604
|
-
spacingLeft += marginLeft;
|
|
12605
|
-
spacingRight += inset;
|
|
12606
|
-
// spacingRight += outlineOffset;
|
|
12607
|
-
// spacingRight -= borderRightWidth;
|
|
12608
|
-
spacingRight += marginRight;
|
|
12609
|
-
spacingBottom += inset;
|
|
12610
|
-
// spacingBottom += outlineOffset;
|
|
12611
|
-
// spacingBottom -= borderBottomWidth;
|
|
12612
|
-
spacingBottom += marginBottom;
|
|
12613
|
-
if (targetSelector) {
|
|
12614
|
-
// oversimplification that actually works
|
|
12615
|
-
// (simplified because it assumes the targeted element is a direct child of the contained element which may have padding)
|
|
12616
|
-
spacingTop += paddingTop;
|
|
12617
|
-
spacingLeft += paddingLeft;
|
|
12618
|
-
spacingRight += paddingRight;
|
|
12619
|
-
spacingBottom += paddingBottom;
|
|
12620
|
-
}
|
|
12621
|
-
const maxBorderWidth = Math.max(borderTopWidth, borderLeftWidth, borderRightWidth, borderBottomWidth);
|
|
12622
|
-
const halfMaxBorderSize = maxBorderWidth / 2;
|
|
12623
|
-
const size = halfMaxBorderSize < 2 ? 2 : halfMaxBorderSize;
|
|
12624
|
-
const lineHalfSize = size / 2;
|
|
12625
|
-
spacingTop -= lineHalfSize;
|
|
12626
|
-
spacingLeft -= lineHalfSize;
|
|
12627
|
-
spacingRight -= lineHalfSize;
|
|
12628
|
-
spacingBottom -= lineHalfSize;
|
|
12629
|
-
return jsxs(Fragment, {
|
|
12630
|
-
children: [jsx("span", {
|
|
12631
|
-
ref: rectangleRef,
|
|
12632
|
-
className: "navi_loading_rectangle_wrapper",
|
|
12633
|
-
"data-visible": shouldShowSpinner ? "" : undefined,
|
|
12634
|
-
style: {
|
|
12635
|
-
"--rectangle-top": `${spacingTop}px`,
|
|
12636
|
-
"--rectangle-left": `${spacingLeft}px`,
|
|
12637
|
-
"--rectangle-bottom": `${spacingBottom}px`,
|
|
12638
|
-
"--rectangle-right": `${spacingRight}px`
|
|
12639
|
-
},
|
|
12640
|
-
children: loading && jsx(RectangleLoading, {
|
|
12641
|
-
shouldShowSpinner: shouldShowSpinner,
|
|
12642
|
-
color: currentColor,
|
|
12643
|
-
radius: borderRadius,
|
|
12644
|
-
size: size
|
|
12645
|
-
})
|
|
12646
|
-
}), children]
|
|
12647
|
-
});
|
|
12648
|
-
};
|
|
12649
|
-
|
|
12650
|
-
/**
|
|
12651
|
-
* Custom hook creating a stable callback that doesn't trigger re-renders.
|
|
12652
|
-
*
|
|
12653
|
-
* PROBLEM: Parent components often forget to use useCallback, causing library
|
|
12654
|
-
* components to re-render unnecessarily when receiving callback props.
|
|
12655
|
-
*
|
|
12656
|
-
* SOLUTION: Library components can use this hook to create stable callback
|
|
12657
|
-
* references internally, making them defensive against parents who don't
|
|
12658
|
-
* optimize their callbacks. This ensures library components don't force
|
|
12659
|
-
* consumers to think about useCallback.
|
|
12660
|
-
*
|
|
12661
|
-
* USAGE:
|
|
12662
|
-
* ```js
|
|
12663
|
-
* // Parent component (consumer) - no useCallback needed
|
|
12664
|
-
* const Parent = () => {
|
|
12665
|
-
* const [count, setCount] = useState(0);
|
|
12666
|
-
*
|
|
12667
|
-
* // Parent naturally creates new function reference each render
|
|
12668
|
-
* // (forgetting useCallback is common and shouldn't break performance)
|
|
12669
|
-
* return <LibraryButton onClick={(e) => setCount(count + 1)} />;
|
|
12670
|
-
* };
|
|
12671
|
-
*
|
|
12672
|
-
* // Library component - defensive against changing callbacks
|
|
12673
|
-
* const LibraryButton = ({ onClick }) => {
|
|
12674
|
-
* // ✅ Create stable reference from parent's potentially changing callback
|
|
12675
|
-
* const stableClick = useStableCallback(onClick);
|
|
12676
|
-
*
|
|
12677
|
-
* // Internal expensive components won't re-render when parent updates
|
|
12678
|
-
* return <ExpensiveInternalButton onClick={stableClick} />;
|
|
12679
|
-
* };
|
|
12680
|
-
*
|
|
12681
|
-
* // Deep internal component gets stable reference
|
|
12682
|
-
* const ExpensiveInternalButton = memo(({ onClick }) => {
|
|
12683
|
-
* // This won't re-render when Parent's count changes
|
|
12684
|
-
* // But onClick will always call the latest Parent callback
|
|
12685
|
-
* return <button onClick={onClick}>Click me</button>;
|
|
12686
|
-
* });
|
|
12687
|
-
* ```
|
|
12688
|
-
*
|
|
12689
|
-
* Perfect for library components that need performance without burdening consumers.
|
|
12690
|
-
*/
|
|
12691
|
-
|
|
12692
|
-
|
|
12693
|
-
const useStableCallback = (callback, mapper) => {
|
|
12694
|
-
const callbackRef = useRef();
|
|
12695
|
-
callbackRef.current = callback;
|
|
12696
|
-
const stableCallbackRef = useRef();
|
|
12697
|
-
|
|
12698
|
-
// Return original falsy value directly when callback is not a function
|
|
12699
|
-
if (!callback) {
|
|
12700
|
-
return callback;
|
|
12701
|
-
}
|
|
12702
|
-
|
|
12703
|
-
const existingStableCallback = stableCallbackRef.current;
|
|
12704
|
-
if (existingStableCallback) {
|
|
12705
|
-
return existingStableCallback;
|
|
12706
|
-
}
|
|
12707
|
-
const stableCallback = (...args) => {
|
|
12708
|
-
const currentCallback = callbackRef.current;
|
|
12709
|
-
return currentCallback(...args);
|
|
12710
|
-
};
|
|
12711
|
-
stableCallbackRef.current = stableCallback;
|
|
12712
|
-
return stableCallback;
|
|
12713
|
-
};
|
|
12714
|
-
|
|
12715
|
-
const DEBUG = {
|
|
12716
|
-
registration: false,
|
|
12717
|
-
// Element registration/unregistration
|
|
12718
|
-
interaction: false,
|
|
12719
|
-
// Click and keyboard interactions
|
|
12720
|
-
selection: false,
|
|
12721
|
-
// Selection state changes (set, add, remove, toggle)
|
|
12722
|
-
navigation: false,
|
|
12723
|
-
// Arrow key navigation and element finding
|
|
12724
|
-
valueExtraction: false // Value extraction from elements
|
|
12725
|
-
};
|
|
12726
|
-
const debug = (category, ...args) => {
|
|
12727
|
-
if (DEBUG[category]) {
|
|
12728
|
-
console.debug(`[selection:${category}]`, ...args);
|
|
12729
|
-
}
|
|
12730
|
-
};
|
|
12731
|
-
const SelectionContext = createContext();
|
|
12732
|
-
const useSelectionController = ({
|
|
12733
|
-
elementRef,
|
|
12734
|
-
layout,
|
|
12735
|
-
value,
|
|
12736
|
-
onChange,
|
|
12737
|
-
multiple,
|
|
12738
|
-
selectAllName
|
|
12739
|
-
}) => {
|
|
12740
|
-
if (!elementRef) {
|
|
12741
|
-
throw new Error("useSelectionController: elementRef is required");
|
|
12742
|
-
}
|
|
12743
|
-
onChange = useStableCallback(onChange);
|
|
12744
|
-
const currentValueRef = useRef(value);
|
|
12745
|
-
currentValueRef.current = value;
|
|
12746
|
-
const lastInternalValueRef = useRef(null);
|
|
12747
|
-
const selectionController = useMemo(() => {
|
|
12748
|
-
const innerOnChange = (newValue, ...args) => {
|
|
12749
|
-
lastInternalValueRef.current = newValue;
|
|
12750
|
-
onChange?.(newValue, ...args);
|
|
12751
|
-
};
|
|
12752
|
-
const getCurrentValue = () => currentValueRef.current;
|
|
12753
|
-
if (layout === "grid") {
|
|
12754
|
-
return createGridSelectionController({
|
|
12755
|
-
getCurrentValue,
|
|
12756
|
-
onChange: innerOnChange,
|
|
12757
|
-
enabled: Boolean(onChange),
|
|
12758
|
-
multiple,
|
|
12759
|
-
selectAllName
|
|
12760
|
-
});
|
|
12761
|
-
}
|
|
12762
|
-
return createLinearSelectionController({
|
|
12763
|
-
getCurrentValue,
|
|
12764
|
-
onChange: innerOnChange,
|
|
12765
|
-
layout,
|
|
12766
|
-
elementRef,
|
|
12767
|
-
multiple,
|
|
12768
|
-
enabled: Boolean(onChange),
|
|
12769
|
-
selectAllName
|
|
12770
|
-
});
|
|
12771
|
-
}, [layout, multiple, elementRef]);
|
|
12772
|
-
useEffect(() => {
|
|
12773
|
-
selectionController.element = elementRef.current;
|
|
12774
|
-
}, [selectionController]);
|
|
12775
|
-
useLayoutEffect(() => {
|
|
12776
|
-
selectionController.enabled = Boolean(onChange);
|
|
12777
|
-
}, [selectionController, onChange]);
|
|
12778
|
-
|
|
12779
|
-
// Smart sync: only update selection when value changes externally
|
|
12780
|
-
useEffect(() => {
|
|
12781
|
-
// Check if this is an external change (not from our internal onChange)
|
|
12782
|
-
const isExternalChange = !compareTwoJsValues(value, lastInternalValueRef.current);
|
|
12783
|
-
if (isExternalChange) {
|
|
12784
|
-
selectionController.update(value);
|
|
12232
|
+
selectionController.enabled = Boolean(onChange);
|
|
12233
|
+
}, [selectionController, onChange]);
|
|
12234
|
+
|
|
12235
|
+
// Smart sync: only update selection when value changes externally
|
|
12236
|
+
useEffect(() => {
|
|
12237
|
+
// Check if this is an external change (not from our internal onChange)
|
|
12238
|
+
const isExternalChange = !compareTwoJsValues(value, lastInternalValueRef.current);
|
|
12239
|
+
if (isExternalChange) {
|
|
12240
|
+
selectionController.update(value);
|
|
12785
12241
|
}
|
|
12786
12242
|
}, [value, selectionController]);
|
|
12787
12243
|
return selectionController;
|
|
@@ -16761,24 +16217,58 @@ const installCustomConstraintValidation = (
|
|
|
16761
16217
|
if (keydownEvent.key !== "Enter") {
|
|
16762
16218
|
return;
|
|
16763
16219
|
}
|
|
16764
|
-
|
|
16765
|
-
|
|
16766
|
-
keydownEvent.preventDefault();
|
|
16767
|
-
}
|
|
16768
|
-
dispatchActionRequestedCustomEvent(element, {
|
|
16769
|
-
event: keydownEvent,
|
|
16770
|
-
requester: element,
|
|
16771
|
-
});
|
|
16220
|
+
const elementWithAction = closestElementWithAction(element);
|
|
16221
|
+
if (!elementWithAction) {
|
|
16772
16222
|
return;
|
|
16773
16223
|
}
|
|
16774
|
-
|
|
16775
|
-
|
|
16776
|
-
|
|
16224
|
+
|
|
16225
|
+
const determineClosestFormSubmitTargetForEnterKeyEvent = () => {
|
|
16226
|
+
if (keydownEvent.defaultPrevented) {
|
|
16227
|
+
return null;
|
|
16228
|
+
}
|
|
16229
|
+
const keydownTarget = keydownEvent.target;
|
|
16230
|
+
const { form } = keydownTarget;
|
|
16231
|
+
if (!form) {
|
|
16232
|
+
return null;
|
|
16233
|
+
}
|
|
16234
|
+
if (keydownTarget.tagName === "BUTTON") {
|
|
16235
|
+
if (
|
|
16236
|
+
keydownTarget.type !== "submit" &&
|
|
16237
|
+
keydownTarget.type !== "image"
|
|
16238
|
+
) {
|
|
16239
|
+
return null;
|
|
16240
|
+
}
|
|
16241
|
+
return keydownTarget;
|
|
16242
|
+
}
|
|
16243
|
+
if (keydownTarget.tagName === "INPUT") {
|
|
16244
|
+
if (
|
|
16245
|
+
![
|
|
16246
|
+
"text",
|
|
16247
|
+
"email",
|
|
16248
|
+
"password",
|
|
16249
|
+
"search",
|
|
16250
|
+
"number",
|
|
16251
|
+
"url",
|
|
16252
|
+
"tel",
|
|
16253
|
+
].includes(keydownTarget.type)
|
|
16254
|
+
) {
|
|
16255
|
+
return null;
|
|
16256
|
+
}
|
|
16257
|
+
// when present, we use first button submitting the form as the requester
|
|
16258
|
+
// not the input, it aligns with browser behavior where
|
|
16259
|
+
// hitting Enter in a text input triggers the first submit button of the form, not the input itself
|
|
16260
|
+
return getFirstButtonSubmittingForm(keydownTarget) || keydownTarget;
|
|
16261
|
+
}
|
|
16262
|
+
return null;
|
|
16263
|
+
};
|
|
16264
|
+
const formSubmitTarget =
|
|
16265
|
+
determineClosestFormSubmitTargetForEnterKeyEvent();
|
|
16266
|
+
if (formSubmitTarget) {
|
|
16267
|
+
keydownEvent.preventDefault();
|
|
16777
16268
|
}
|
|
16778
|
-
|
|
16779
|
-
dispatchActionRequestedCustomEvent(form, {
|
|
16269
|
+
dispatchActionRequestedCustomEvent(elementWithAction, {
|
|
16780
16270
|
event: keydownEvent,
|
|
16781
|
-
requester:
|
|
16271
|
+
requester: formSubmitTarget || element,
|
|
16782
16272
|
});
|
|
16783
16273
|
};
|
|
16784
16274
|
element.addEventListener("keydown", onkeydown);
|
|
@@ -16795,29 +16285,44 @@ const installCustomConstraintValidation = (
|
|
|
16795
16285
|
if (element.tagName !== "BUTTON") {
|
|
16796
16286
|
return;
|
|
16797
16287
|
}
|
|
16798
|
-
|
|
16799
|
-
|
|
16800
|
-
|
|
16801
|
-
}
|
|
16802
|
-
dispatchActionRequestedCustomEvent(element, {
|
|
16803
|
-
event: clickEvent,
|
|
16804
|
-
requester: element,
|
|
16805
|
-
});
|
|
16806
|
-
return;
|
|
16807
|
-
}
|
|
16808
|
-
const { form } = element;
|
|
16809
|
-
if (!form) {
|
|
16810
|
-
return;
|
|
16811
|
-
}
|
|
16812
|
-
if (element.type === "reset") {
|
|
16288
|
+
const button = element;
|
|
16289
|
+
const elementWithAction = closestElementWithAction(button);
|
|
16290
|
+
if (!elementWithAction) {
|
|
16813
16291
|
return;
|
|
16814
16292
|
}
|
|
16815
|
-
|
|
16293
|
+
const determineClosestFormSubmitTargetForClickEvent = () => {
|
|
16294
|
+
if (clickEvent.defaultPrevented) {
|
|
16295
|
+
return null;
|
|
16296
|
+
}
|
|
16297
|
+
const clickTarget = clickEvent.target;
|
|
16298
|
+
const { form } = clickTarget;
|
|
16299
|
+
if (!form) {
|
|
16300
|
+
return null;
|
|
16301
|
+
}
|
|
16302
|
+
const wouldSubmitFormByType =
|
|
16303
|
+
button.type === "submit" || button.type === "image";
|
|
16304
|
+
if (wouldSubmitFormByType) {
|
|
16305
|
+
return button;
|
|
16306
|
+
}
|
|
16307
|
+
if (button.type) {
|
|
16308
|
+
// "reset", "button" or any other non submit type, it won't submit the form
|
|
16309
|
+
return null;
|
|
16310
|
+
}
|
|
16311
|
+
const firstButtonSubmittingForm = getFirstButtonSubmittingForm(form);
|
|
16312
|
+
if (button !== firstButtonSubmittingForm) {
|
|
16313
|
+
// an other button is explicitly submitting the form, this one would not submit it
|
|
16314
|
+
return null;
|
|
16315
|
+
}
|
|
16316
|
+
// this is the only button inside the form without type attribute, so it defaults to type="submit"
|
|
16317
|
+
return button;
|
|
16318
|
+
};
|
|
16319
|
+
const formSubmitTarget = determineClosestFormSubmitTargetForClickEvent();
|
|
16320
|
+
if (formSubmitTarget) {
|
|
16816
16321
|
clickEvent.preventDefault();
|
|
16817
16322
|
}
|
|
16818
|
-
dispatchActionRequestedCustomEvent(
|
|
16323
|
+
dispatchActionRequestedCustomEvent(elementWithAction, {
|
|
16819
16324
|
event: clickEvent,
|
|
16820
|
-
requester:
|
|
16325
|
+
requester: formSubmitTarget || button,
|
|
16821
16326
|
});
|
|
16822
16327
|
};
|
|
16823
16328
|
element.addEventListener("click", onclick);
|
|
@@ -16833,13 +16338,14 @@ const installCustomConstraintValidation = (
|
|
|
16833
16338
|
break request_on_input_change;
|
|
16834
16339
|
}
|
|
16835
16340
|
const stop = listenInputChange(element, (e) => {
|
|
16836
|
-
|
|
16837
|
-
|
|
16838
|
-
event: e,
|
|
16839
|
-
requester: element,
|
|
16840
|
-
});
|
|
16341
|
+
const elementWithAction = closestElementWithAction(element);
|
|
16342
|
+
if (!elementWithAction) {
|
|
16841
16343
|
return;
|
|
16842
16344
|
}
|
|
16345
|
+
dispatchActionRequestedCustomEvent(elementWithAction, {
|
|
16346
|
+
event: e,
|
|
16347
|
+
requester: element,
|
|
16348
|
+
});
|
|
16843
16349
|
});
|
|
16844
16350
|
addTeardown(() => {
|
|
16845
16351
|
stop();
|
|
@@ -16937,6 +16443,31 @@ const installCustomConstraintValidation = (
|
|
|
16937
16443
|
return validationInterface;
|
|
16938
16444
|
};
|
|
16939
16445
|
|
|
16446
|
+
// When interacting with an element we want to find the closest element
|
|
16447
|
+
// eventually handling the action
|
|
16448
|
+
// 1. <button> itself has an action
|
|
16449
|
+
// 2. <button> is inside a <form> with an action
|
|
16450
|
+
// 3. <button> is inside a wrapper <div> with an action (data-action is not necessarly on the interactive element itself, it can be on a wrapper, we want to support that)
|
|
16451
|
+
// 4. <button> is inside a <fieldset> or any element that catches the action like a <form> would
|
|
16452
|
+
// In examples above <button> can also be <input> etc..
|
|
16453
|
+
const closestElementWithAction = (el) => {
|
|
16454
|
+
if (el.hasAttribute("data-action")) {
|
|
16455
|
+
return el;
|
|
16456
|
+
}
|
|
16457
|
+
const closestDataActionElement = el.closest("[data-action]");
|
|
16458
|
+
if (!closestDataActionElement) {
|
|
16459
|
+
return null;
|
|
16460
|
+
}
|
|
16461
|
+
const visualSelector = closestDataActionElement.getAttribute(
|
|
16462
|
+
"data-visual-selector",
|
|
16463
|
+
);
|
|
16464
|
+
if (!visualSelector) {
|
|
16465
|
+
return closestDataActionElement;
|
|
16466
|
+
}
|
|
16467
|
+
const visualElement = closestDataActionElement.querySelector(visualSelector);
|
|
16468
|
+
return visualElement;
|
|
16469
|
+
};
|
|
16470
|
+
|
|
16940
16471
|
const pickConstraint = (a, b) => {
|
|
16941
16472
|
const aPrio = getConstraintPriority(a);
|
|
16942
16473
|
const bPrio = getConstraintPriority(b);
|
|
@@ -16955,60 +16486,14 @@ const getConstraintPriority = (constraint) => {
|
|
|
16955
16486
|
return 1;
|
|
16956
16487
|
};
|
|
16957
16488
|
|
|
16958
|
-
const wouldButtonClickSubmitForm = (button, clickEvent) => {
|
|
16959
|
-
if (clickEvent.defaultPrevented) {
|
|
16960
|
-
return false;
|
|
16961
|
-
}
|
|
16962
|
-
const { form } = button;
|
|
16963
|
-
if (!form) {
|
|
16964
|
-
return false;
|
|
16965
|
-
}
|
|
16966
|
-
if (!button) {
|
|
16967
|
-
return false;
|
|
16968
|
-
}
|
|
16969
|
-
const wouldSubmitFormByType =
|
|
16970
|
-
button.type === "submit" || button.type === "image";
|
|
16971
|
-
if (wouldSubmitFormByType) {
|
|
16972
|
-
return true;
|
|
16973
|
-
}
|
|
16974
|
-
if (button.type) {
|
|
16975
|
-
return false;
|
|
16976
|
-
}
|
|
16977
|
-
if (getFirstButtonSubmittingForm(form)) {
|
|
16978
|
-
// an other button is explicitly submitting the form, this one would not submit it
|
|
16979
|
-
return false;
|
|
16980
|
-
}
|
|
16981
|
-
// this is the only button inside the form without type attribute, so it defaults to type="submit"
|
|
16982
|
-
return true;
|
|
16983
|
-
};
|
|
16984
16489
|
const getFirstButtonSubmittingForm = (form) => {
|
|
16985
16490
|
return form.querySelector(
|
|
16986
16491
|
`button[type="submit"], input[type="submit"], input[type="image"]`,
|
|
16987
16492
|
);
|
|
16988
16493
|
};
|
|
16989
16494
|
|
|
16990
|
-
const wouldKeydownSubmitForm = (keydownEvent) => {
|
|
16991
|
-
if (keydownEvent.defaultPrevented) {
|
|
16992
|
-
return false;
|
|
16993
|
-
}
|
|
16994
|
-
const keydownTarget = keydownEvent.target;
|
|
16995
|
-
const { form } = keydownTarget;
|
|
16996
|
-
if (!form) {
|
|
16997
|
-
return false;
|
|
16998
|
-
}
|
|
16999
|
-
if (keydownEvent.key !== "Enter") {
|
|
17000
|
-
return false;
|
|
17001
|
-
}
|
|
17002
|
-
const isTextInput =
|
|
17003
|
-
keydownTarget.tagName === "INPUT" || keydownTarget.tagName === "TEXTAREA";
|
|
17004
|
-
if (!isTextInput) {
|
|
17005
|
-
return false;
|
|
17006
|
-
}
|
|
17007
|
-
return true;
|
|
17008
|
-
};
|
|
17009
|
-
|
|
17010
16495
|
const dispatchActionRequestedCustomEvent = (
|
|
17011
|
-
|
|
16496
|
+
elementWithAction,
|
|
17012
16497
|
{ actionOrigin = "action_prop", event, requester },
|
|
17013
16498
|
) => {
|
|
17014
16499
|
const actionRequestedCustomEvent = new CustomEvent("actionrequested", {
|
|
@@ -17019,7 +16504,7 @@ const dispatchActionRequestedCustomEvent = (
|
|
|
17019
16504
|
requester,
|
|
17020
16505
|
},
|
|
17021
16506
|
});
|
|
17022
|
-
|
|
16507
|
+
elementWithAction.dispatchEvent(actionRequestedCustomEvent);
|
|
17023
16508
|
};
|
|
17024
16509
|
// https://developer.mozilla.org/en-US/docs/Web/HTML/Guides/Constraint_validation
|
|
17025
16510
|
const requestSubmit = HTMLFormElement.prototype.requestSubmit;
|
|
@@ -17321,553 +16806,1133 @@ const selectByCharacterIndices = (element, range, startIndex, endIndex) => {
|
|
|
17321
16806
|
startNode = walker.currentNode;
|
|
17322
16807
|
startOffset = startIndex - currentIndex;
|
|
17323
16808
|
}
|
|
17324
|
-
|
|
17325
|
-
// Check if end position is in this text node
|
|
17326
|
-
if (currentIndex + nodeLength >= endIndex) {
|
|
17327
|
-
endNode = walker.currentNode;
|
|
17328
|
-
endOffset = endIndex - currentIndex;
|
|
16809
|
+
|
|
16810
|
+
// Check if end position is in this text node
|
|
16811
|
+
if (currentIndex + nodeLength >= endIndex) {
|
|
16812
|
+
endNode = walker.currentNode;
|
|
16813
|
+
endOffset = endIndex - currentIndex;
|
|
16814
|
+
break;
|
|
16815
|
+
}
|
|
16816
|
+
currentIndex += nodeLength;
|
|
16817
|
+
}
|
|
16818
|
+
if (startNode && endNode) {
|
|
16819
|
+
range.setStart(startNode, startOffset);
|
|
16820
|
+
range.setEnd(endNode, endOffset);
|
|
16821
|
+
}
|
|
16822
|
+
};
|
|
16823
|
+
const selectSingleTextString = (element, range, text) => {
|
|
16824
|
+
const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT, null, false);
|
|
16825
|
+
while (walker.nextNode()) {
|
|
16826
|
+
const textContent = walker.currentNode.textContent;
|
|
16827
|
+
const index = textContent.indexOf(text);
|
|
16828
|
+
if (index !== -1) {
|
|
16829
|
+
range.setStart(walker.currentNode, index);
|
|
16830
|
+
range.setEnd(walker.currentNode, index + text.length);
|
|
16831
|
+
return;
|
|
16832
|
+
}
|
|
16833
|
+
}
|
|
16834
|
+
};
|
|
16835
|
+
const selectByTextStrings = (element, range, startText, endText) => {
|
|
16836
|
+
const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT, null, false);
|
|
16837
|
+
let startNode = null;
|
|
16838
|
+
let endNode = null;
|
|
16839
|
+
let foundStart = false;
|
|
16840
|
+
while (walker.nextNode()) {
|
|
16841
|
+
const textContent = walker.currentNode.textContent;
|
|
16842
|
+
if (!foundStart && textContent.includes(startText)) {
|
|
16843
|
+
startNode = walker.currentNode;
|
|
16844
|
+
foundStart = true;
|
|
16845
|
+
}
|
|
16846
|
+
if (foundStart && textContent.includes(endText)) {
|
|
16847
|
+
endNode = walker.currentNode;
|
|
16848
|
+
break;
|
|
16849
|
+
}
|
|
16850
|
+
}
|
|
16851
|
+
if (startNode && endNode) {
|
|
16852
|
+
const startOffset = startNode.textContent.indexOf(startText);
|
|
16853
|
+
const endOffset = endNode.textContent.indexOf(endText) + endText.length;
|
|
16854
|
+
range.setStart(startNode, startOffset);
|
|
16855
|
+
range.setEnd(endNode, endOffset);
|
|
16856
|
+
}
|
|
16857
|
+
};
|
|
16858
|
+
|
|
16859
|
+
installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
16860
|
+
*[data-navi-space] {
|
|
16861
|
+
/* user-select: none; */
|
|
16862
|
+
}
|
|
16863
|
+
|
|
16864
|
+
.navi_text {
|
|
16865
|
+
position: relative;
|
|
16866
|
+
color: inherit;
|
|
16867
|
+
|
|
16868
|
+
&[data-has-absolute-child] {
|
|
16869
|
+
display: inline-block;
|
|
16870
|
+
}
|
|
16871
|
+
}
|
|
16872
|
+
|
|
16873
|
+
.navi_text_overflow {
|
|
16874
|
+
flex-wrap: wrap;
|
|
16875
|
+
text-overflow: ellipsis;
|
|
16876
|
+
overflow: hidden;
|
|
16877
|
+
}
|
|
16878
|
+
|
|
16879
|
+
.navi_text_overflow_wrapper {
|
|
16880
|
+
display: flex;
|
|
16881
|
+
width: 0;
|
|
16882
|
+
flex-grow: 1;
|
|
16883
|
+
gap: 0.3em;
|
|
16884
|
+
}
|
|
16885
|
+
|
|
16886
|
+
.navi_text_overflow_text {
|
|
16887
|
+
max-width: 100%;
|
|
16888
|
+
text-overflow: ellipsis;
|
|
16889
|
+
overflow: hidden;
|
|
16890
|
+
}
|
|
16891
|
+
|
|
16892
|
+
.navi_custom_space {
|
|
16893
|
+
}
|
|
16894
|
+
|
|
16895
|
+
.navi_text_bold_wrapper {
|
|
16896
|
+
position: relative;
|
|
16897
|
+
display: inline-block;
|
|
16898
|
+
}
|
|
16899
|
+
.navi_text_bold_clone {
|
|
16900
|
+
font-weight: bold;
|
|
16901
|
+
opacity: 0;
|
|
16902
|
+
}
|
|
16903
|
+
.navi_text_bold_foreground {
|
|
16904
|
+
position: absolute;
|
|
16905
|
+
inset: 0;
|
|
16906
|
+
}
|
|
16907
|
+
|
|
16908
|
+
.navi_text_bold_background {
|
|
16909
|
+
position: absolute;
|
|
16910
|
+
top: 0;
|
|
16911
|
+
left: 0;
|
|
16912
|
+
color: currentColor;
|
|
16913
|
+
font-weight: normal;
|
|
16914
|
+
background: currentColor;
|
|
16915
|
+
background-clip: text;
|
|
16916
|
+
-webkit-background-clip: text;
|
|
16917
|
+
transform-origin: center;
|
|
16918
|
+
-webkit-text-fill-color: transparent;
|
|
16919
|
+
opacity: 0;
|
|
16920
|
+
}
|
|
16921
|
+
|
|
16922
|
+
.navi_text[data-bold] {
|
|
16923
|
+
.navi_text_bold_background {
|
|
16924
|
+
opacity: 1;
|
|
16925
|
+
}
|
|
16926
|
+
}
|
|
16927
|
+
|
|
16928
|
+
.navi_text[data-bold-transition] {
|
|
16929
|
+
.navi_text_bold_foreground {
|
|
16930
|
+
transition-property: font-weight;
|
|
16931
|
+
transition-duration: 0.3s;
|
|
16932
|
+
transition-timing-function: ease;
|
|
16933
|
+
}
|
|
16934
|
+
|
|
16935
|
+
.navi_text_bold_background {
|
|
16936
|
+
transition-property: opacity;
|
|
16937
|
+
transition-duration: 0.3s;
|
|
16938
|
+
transition-timing-function: ease;
|
|
16939
|
+
}
|
|
16940
|
+
}
|
|
16941
|
+
`;
|
|
16942
|
+
const REGULAR_SPACE = jsx("span", {
|
|
16943
|
+
"data-navi-space": "",
|
|
16944
|
+
children: " "
|
|
16945
|
+
});
|
|
16946
|
+
const CustomWidthSpace = ({
|
|
16947
|
+
value
|
|
16948
|
+
}) => {
|
|
16949
|
+
return jsx("span", {
|
|
16950
|
+
className: "navi_custom_space",
|
|
16951
|
+
style: `padding-left: ${value}`,
|
|
16952
|
+
children: "\u200B"
|
|
16953
|
+
});
|
|
16954
|
+
};
|
|
16955
|
+
const applySpacingOnTextChildren = (children, spacing) => {
|
|
16956
|
+
if (spacing === "pre" || spacing === "0" || spacing === 0) {
|
|
16957
|
+
return children;
|
|
16958
|
+
}
|
|
16959
|
+
if (!children) {
|
|
16960
|
+
return children;
|
|
16961
|
+
}
|
|
16962
|
+
const childArray = toChildArray(children);
|
|
16963
|
+
const childCount = childArray.length;
|
|
16964
|
+
if (childCount <= 1) {
|
|
16965
|
+
return children;
|
|
16966
|
+
}
|
|
16967
|
+
let separator;
|
|
16968
|
+
if (spacing === undefined) {
|
|
16969
|
+
spacing = REGULAR_SPACE;
|
|
16970
|
+
} else if (typeof spacing === "string") {
|
|
16971
|
+
if (isSizeSpacingScaleKey(spacing)) {
|
|
16972
|
+
separator = jsx(CustomWidthSpace, {
|
|
16973
|
+
value: resolveSpacingSize(spacing)
|
|
16974
|
+
});
|
|
16975
|
+
} else if (hasCSSSizeUnit(spacing)) {
|
|
16976
|
+
separator = jsx(CustomWidthSpace, {
|
|
16977
|
+
value: resolveSpacingSize(spacing)
|
|
16978
|
+
});
|
|
16979
|
+
} else {
|
|
16980
|
+
separator = spacing;
|
|
16981
|
+
}
|
|
16982
|
+
} else if (typeof spacing === "number") {
|
|
16983
|
+
separator = jsx(CustomWidthSpace, {
|
|
16984
|
+
value: spacing
|
|
16985
|
+
});
|
|
16986
|
+
} else {
|
|
16987
|
+
separator = spacing;
|
|
16988
|
+
}
|
|
16989
|
+
const childrenWithGap = [];
|
|
16990
|
+
let i = 0;
|
|
16991
|
+
while (true) {
|
|
16992
|
+
const child = childArray[i];
|
|
16993
|
+
childrenWithGap.push(child);
|
|
16994
|
+
i++;
|
|
16995
|
+
if (i === childCount) {
|
|
17329
16996
|
break;
|
|
17330
16997
|
}
|
|
17331
|
-
|
|
16998
|
+
const currentChild = childArray[i - 1];
|
|
16999
|
+
const nextChild = childArray[i];
|
|
17000
|
+
if (endsWithWhitespace(currentChild)) {
|
|
17001
|
+
continue;
|
|
17002
|
+
}
|
|
17003
|
+
if (startsWithWhitespace(nextChild)) {
|
|
17004
|
+
continue;
|
|
17005
|
+
}
|
|
17006
|
+
childrenWithGap.push(separator);
|
|
17332
17007
|
}
|
|
17333
|
-
|
|
17334
|
-
|
|
17335
|
-
|
|
17008
|
+
return childrenWithGap;
|
|
17009
|
+
};
|
|
17010
|
+
const endsWithWhitespace = jsxChild => {
|
|
17011
|
+
if (typeof jsxChild === "string") {
|
|
17012
|
+
return /\s$/.test(jsxChild);
|
|
17336
17013
|
}
|
|
17014
|
+
return false;
|
|
17337
17015
|
};
|
|
17338
|
-
const
|
|
17339
|
-
|
|
17340
|
-
|
|
17341
|
-
const textContent = walker.currentNode.textContent;
|
|
17342
|
-
const index = textContent.indexOf(text);
|
|
17343
|
-
if (index !== -1) {
|
|
17344
|
-
range.setStart(walker.currentNode, index);
|
|
17345
|
-
range.setEnd(walker.currentNode, index + text.length);
|
|
17346
|
-
return;
|
|
17347
|
-
}
|
|
17016
|
+
const startsWithWhitespace = jsxChild => {
|
|
17017
|
+
if (typeof jsxChild === "string") {
|
|
17018
|
+
return /^\s/.test(jsxChild);
|
|
17348
17019
|
}
|
|
17020
|
+
return false;
|
|
17349
17021
|
};
|
|
17350
|
-
const
|
|
17351
|
-
|
|
17352
|
-
|
|
17353
|
-
|
|
17354
|
-
|
|
17355
|
-
|
|
17356
|
-
|
|
17357
|
-
|
|
17358
|
-
|
|
17359
|
-
|
|
17360
|
-
}
|
|
17361
|
-
if (foundStart && textContent.includes(endText)) {
|
|
17362
|
-
endNode = walker.currentNode;
|
|
17363
|
-
break;
|
|
17364
|
-
}
|
|
17022
|
+
const OverflowPinnedElementContext = createContext(null);
|
|
17023
|
+
const Text = props => {
|
|
17024
|
+
const {
|
|
17025
|
+
overflowEllipsis,
|
|
17026
|
+
...rest
|
|
17027
|
+
} = props;
|
|
17028
|
+
if (overflowEllipsis) {
|
|
17029
|
+
return jsx(TextOverflow, {
|
|
17030
|
+
...rest
|
|
17031
|
+
});
|
|
17365
17032
|
}
|
|
17366
|
-
if (
|
|
17367
|
-
|
|
17368
|
-
|
|
17369
|
-
|
|
17370
|
-
|
|
17033
|
+
if (props.overflowPinned) {
|
|
17034
|
+
return jsx(TextOverflowPinned, {
|
|
17035
|
+
...props
|
|
17036
|
+
});
|
|
17037
|
+
}
|
|
17038
|
+
if (props.selectRange) {
|
|
17039
|
+
return jsx(TextWithSelectRange, {
|
|
17040
|
+
...props
|
|
17041
|
+
});
|
|
17371
17042
|
}
|
|
17043
|
+
return jsx(TextBasic, {
|
|
17044
|
+
...props
|
|
17045
|
+
});
|
|
17372
17046
|
};
|
|
17373
|
-
|
|
17374
|
-
|
|
17375
|
-
|
|
17376
|
-
|
|
17047
|
+
const TextOverflow = ({
|
|
17048
|
+
noWrap,
|
|
17049
|
+
children,
|
|
17050
|
+
...rest
|
|
17051
|
+
}) => {
|
|
17052
|
+
const [OverflowPinnedElement, setOverflowPinnedElement] = useState(null);
|
|
17053
|
+
return jsx(Text, {
|
|
17054
|
+
column: true,
|
|
17055
|
+
as: "div",
|
|
17056
|
+
nowWrap: noWrap,
|
|
17057
|
+
pre: !noWrap
|
|
17058
|
+
// For paragraph we prefer to keep lines and only hide unbreakable long sections
|
|
17059
|
+
,
|
|
17060
|
+
preLine: rest.as === "p",
|
|
17061
|
+
...rest,
|
|
17062
|
+
className: "navi_text_overflow",
|
|
17063
|
+
expandX: true,
|
|
17064
|
+
spacing: "pre",
|
|
17065
|
+
children: jsxs("span", {
|
|
17066
|
+
className: "navi_text_overflow_wrapper",
|
|
17067
|
+
children: [jsx(OverflowPinnedElementContext.Provider, {
|
|
17068
|
+
value: setOverflowPinnedElement,
|
|
17069
|
+
children: jsx(Text, {
|
|
17070
|
+
className: "navi_text_overflow_text",
|
|
17071
|
+
children: children
|
|
17072
|
+
})
|
|
17073
|
+
}), OverflowPinnedElement]
|
|
17074
|
+
})
|
|
17075
|
+
});
|
|
17076
|
+
};
|
|
17077
|
+
const TextOverflowPinned = ({
|
|
17078
|
+
overflowPinned,
|
|
17079
|
+
...props
|
|
17080
|
+
}) => {
|
|
17081
|
+
const setOverflowPinnedElement = useContext(OverflowPinnedElementContext);
|
|
17082
|
+
const text = jsx(Text, {
|
|
17083
|
+
...props
|
|
17084
|
+
});
|
|
17085
|
+
if (!setOverflowPinnedElement) {
|
|
17086
|
+
console.warn("<Text overflowPinned> declared outside a <Text overflowEllipsis>");
|
|
17087
|
+
return text;
|
|
17377
17088
|
}
|
|
17378
|
-
|
|
17379
|
-
|
|
17380
|
-
|
|
17381
|
-
color: inherit;
|
|
17382
|
-
|
|
17383
|
-
&[data-has-absolute-child] {
|
|
17384
|
-
display: inline-block;
|
|
17385
|
-
}
|
|
17089
|
+
if (overflowPinned) {
|
|
17090
|
+
setOverflowPinnedElement(text);
|
|
17091
|
+
return null;
|
|
17386
17092
|
}
|
|
17387
|
-
|
|
17388
|
-
|
|
17389
|
-
|
|
17390
|
-
|
|
17391
|
-
|
|
17093
|
+
setOverflowPinnedElement(null);
|
|
17094
|
+
return text;
|
|
17095
|
+
};
|
|
17096
|
+
const TextWithSelectRange = ({
|
|
17097
|
+
selectRange,
|
|
17098
|
+
...props
|
|
17099
|
+
}) => {
|
|
17100
|
+
const defaultRef = useRef();
|
|
17101
|
+
const ref = props.ref || defaultRef;
|
|
17102
|
+
useInitialTextSelection(ref, selectRange);
|
|
17103
|
+
return jsx(Text, {
|
|
17104
|
+
ref: ref,
|
|
17105
|
+
...props
|
|
17106
|
+
});
|
|
17107
|
+
};
|
|
17108
|
+
const TextBasic = ({
|
|
17109
|
+
spacing = " ",
|
|
17110
|
+
boldTransition,
|
|
17111
|
+
boldStable,
|
|
17112
|
+
preventBoldLayoutShift = boldTransition,
|
|
17113
|
+
children,
|
|
17114
|
+
...rest
|
|
17115
|
+
}) => {
|
|
17116
|
+
const boxProps = {
|
|
17117
|
+
"as": "span",
|
|
17118
|
+
"data-bold-transition": boldTransition ? "" : undefined,
|
|
17119
|
+
...rest,
|
|
17120
|
+
"baseClassName": withPropsClassName("navi_text", rest.baseClassName)
|
|
17121
|
+
};
|
|
17122
|
+
const shouldPreserveSpacing = rest.as === "pre" || rest.box || rest.column || rest.row;
|
|
17123
|
+
if (shouldPreserveSpacing) {
|
|
17124
|
+
boxProps.spacing = spacing;
|
|
17125
|
+
} else {
|
|
17126
|
+
children = applySpacingOnTextChildren(children, spacing);
|
|
17127
|
+
}
|
|
17128
|
+
if (boldStable) {
|
|
17129
|
+
const {
|
|
17130
|
+
bold
|
|
17131
|
+
} = boxProps;
|
|
17132
|
+
return jsxs(Box, {
|
|
17133
|
+
...boxProps,
|
|
17134
|
+
bold: undefined,
|
|
17135
|
+
"data-bold": bold ? "" : undefined,
|
|
17136
|
+
"data-has-absolute-child": "",
|
|
17137
|
+
children: [jsx("span", {
|
|
17138
|
+
className: "navi_text_bold_background",
|
|
17139
|
+
"aria-hidden": "true",
|
|
17140
|
+
children: children
|
|
17141
|
+
}), children]
|
|
17142
|
+
});
|
|
17392
17143
|
}
|
|
17144
|
+
if (preventBoldLayoutShift) {
|
|
17145
|
+
const alignX = rest.alignX || rest.align || "start";
|
|
17393
17146
|
|
|
17394
|
-
|
|
17395
|
-
|
|
17396
|
-
|
|
17397
|
-
|
|
17398
|
-
|
|
17147
|
+
// La technique consiste a avoid un double gras qui force une taille
|
|
17148
|
+
// et la version light par dessus en position absolute
|
|
17149
|
+
// on la centre aussi pour donner l'impression que le gras s'applique depuis le centre
|
|
17150
|
+
// ne fonctionne que sur une seul ligne de texte (donc lorsque noWrap est actif)
|
|
17151
|
+
// on pourrait auto-active cela sur une prop genre boldCanChange
|
|
17152
|
+
return jsx(Box, {
|
|
17153
|
+
...boxProps,
|
|
17154
|
+
children: jsxs("span", {
|
|
17155
|
+
className: "navi_text_bold_wrapper",
|
|
17156
|
+
children: [jsx("span", {
|
|
17157
|
+
className: "navi_text_bold_clone",
|
|
17158
|
+
"aria-hidden": "true",
|
|
17159
|
+
children: children
|
|
17160
|
+
}), jsx("span", {
|
|
17161
|
+
className: "navi_text_bold_foreground",
|
|
17162
|
+
"data-align": alignX,
|
|
17163
|
+
children: children
|
|
17164
|
+
})]
|
|
17165
|
+
})
|
|
17166
|
+
});
|
|
17399
17167
|
}
|
|
17168
|
+
return jsx(Box, {
|
|
17169
|
+
...boxProps,
|
|
17170
|
+
children: children
|
|
17171
|
+
});
|
|
17172
|
+
};
|
|
17400
17173
|
|
|
17401
|
-
|
|
17174
|
+
installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
17175
|
+
.navi_icon {
|
|
17176
|
+
display: inline-block;
|
|
17177
|
+
box-sizing: border-box;
|
|
17402
17178
|
max-width: 100%;
|
|
17403
|
-
|
|
17404
|
-
overflow: hidden;
|
|
17405
|
-
}
|
|
17179
|
+
max-height: 100%;
|
|
17406
17180
|
|
|
17407
|
-
|
|
17181
|
+
&[data-flow-inline] {
|
|
17182
|
+
width: 1em;
|
|
17183
|
+
height: 1em;
|
|
17184
|
+
}
|
|
17185
|
+
&[data-icon-char] {
|
|
17186
|
+
flex-grow: 0 !important;
|
|
17187
|
+
line-height: normal;
|
|
17188
|
+
}
|
|
17408
17189
|
}
|
|
17409
17190
|
|
|
17410
|
-
.
|
|
17411
|
-
|
|
17412
|
-
display: inline-block;
|
|
17191
|
+
.navi_icon[data-interactive] {
|
|
17192
|
+
cursor: pointer;
|
|
17413
17193
|
}
|
|
17414
|
-
|
|
17415
|
-
|
|
17194
|
+
|
|
17195
|
+
.navi_icon_char_slot {
|
|
17416
17196
|
opacity: 0;
|
|
17197
|
+
cursor: default;
|
|
17198
|
+
user-select: none;
|
|
17417
17199
|
}
|
|
17418
|
-
.
|
|
17200
|
+
.navi_icon_foreground {
|
|
17419
17201
|
position: absolute;
|
|
17420
17202
|
inset: 0;
|
|
17421
17203
|
}
|
|
17422
|
-
|
|
17423
|
-
|
|
17424
|
-
|
|
17425
|
-
|
|
17426
|
-
|
|
17427
|
-
|
|
17428
|
-
|
|
17429
|
-
|
|
17430
|
-
background-clip: text;
|
|
17431
|
-
-webkit-background-clip: text;
|
|
17432
|
-
transform-origin: center;
|
|
17433
|
-
-webkit-text-fill-color: transparent;
|
|
17434
|
-
opacity: 0;
|
|
17435
|
-
}
|
|
17436
|
-
|
|
17437
|
-
.navi_text[data-bold] {
|
|
17438
|
-
.navi_text_bold_background {
|
|
17439
|
-
opacity: 1;
|
|
17440
|
-
}
|
|
17204
|
+
.navi_icon_foreground > .navi_text {
|
|
17205
|
+
display: flex;
|
|
17206
|
+
aspect-ratio: 1 / 1;
|
|
17207
|
+
min-width: 0;
|
|
17208
|
+
height: 100%;
|
|
17209
|
+
max-height: 1em;
|
|
17210
|
+
align-items: center;
|
|
17211
|
+
justify-content: center;
|
|
17441
17212
|
}
|
|
17442
17213
|
|
|
17443
|
-
.
|
|
17444
|
-
|
|
17445
|
-
|
|
17446
|
-
|
|
17447
|
-
|
|
17448
|
-
}
|
|
17449
|
-
|
|
17450
|
-
.navi_text_bold_background {
|
|
17451
|
-
transition-property: opacity;
|
|
17452
|
-
transition-duration: 0.3s;
|
|
17453
|
-
transition-timing-function: ease;
|
|
17454
|
-
}
|
|
17455
|
-
}
|
|
17456
|
-
`;
|
|
17457
|
-
const REGULAR_SPACE = jsx("span", {
|
|
17458
|
-
"data-navi-space": "",
|
|
17459
|
-
children: " "
|
|
17460
|
-
});
|
|
17461
|
-
const CustomWidthSpace = ({
|
|
17462
|
-
value
|
|
17463
|
-
}) => {
|
|
17464
|
-
return jsx("span", {
|
|
17465
|
-
className: "navi_custom_space",
|
|
17466
|
-
style: `padding-left: ${value}`,
|
|
17467
|
-
children: "\u200B"
|
|
17468
|
-
});
|
|
17469
|
-
};
|
|
17470
|
-
const applySpacingOnTextChildren = (children, spacing) => {
|
|
17471
|
-
if (spacing === "pre" || spacing === "0" || spacing === 0) {
|
|
17472
|
-
return children;
|
|
17473
|
-
}
|
|
17474
|
-
if (!children) {
|
|
17475
|
-
return children;
|
|
17214
|
+
.navi_icon > svg,
|
|
17215
|
+
.navi_icon > img {
|
|
17216
|
+
width: 100%;
|
|
17217
|
+
height: 100%;
|
|
17218
|
+
backface-visibility: hidden;
|
|
17476
17219
|
}
|
|
17477
|
-
|
|
17478
|
-
|
|
17479
|
-
|
|
17480
|
-
|
|
17220
|
+
.navi_icon[data-has-width] > svg,
|
|
17221
|
+
.navi_icon[data-has-width] > img {
|
|
17222
|
+
width: 100%;
|
|
17223
|
+
height: auto;
|
|
17481
17224
|
}
|
|
17482
|
-
|
|
17483
|
-
|
|
17484
|
-
|
|
17485
|
-
|
|
17486
|
-
if (isSizeSpacingScaleKey(spacing)) {
|
|
17487
|
-
separator = jsx(CustomWidthSpace, {
|
|
17488
|
-
value: resolveSpacingSize(spacing)
|
|
17489
|
-
});
|
|
17490
|
-
} else if (hasCSSSizeUnit(spacing)) {
|
|
17491
|
-
separator = jsx(CustomWidthSpace, {
|
|
17492
|
-
value: resolveSpacingSize(spacing)
|
|
17493
|
-
});
|
|
17494
|
-
} else {
|
|
17495
|
-
separator = spacing;
|
|
17496
|
-
}
|
|
17497
|
-
} else if (typeof spacing === "number") {
|
|
17498
|
-
separator = jsx(CustomWidthSpace, {
|
|
17499
|
-
value: spacing
|
|
17500
|
-
});
|
|
17501
|
-
} else {
|
|
17502
|
-
separator = spacing;
|
|
17225
|
+
.navi_icon[data-has-height] > svg,
|
|
17226
|
+
.navi_icon[data-has-height] > img {
|
|
17227
|
+
width: auto;
|
|
17228
|
+
height: 100%;
|
|
17503
17229
|
}
|
|
17504
|
-
|
|
17505
|
-
|
|
17506
|
-
|
|
17507
|
-
|
|
17508
|
-
childrenWithGap.push(child);
|
|
17509
|
-
i++;
|
|
17510
|
-
if (i === childCount) {
|
|
17511
|
-
break;
|
|
17512
|
-
}
|
|
17513
|
-
const currentChild = childArray[i - 1];
|
|
17514
|
-
const nextChild = childArray[i];
|
|
17515
|
-
if (endsWithWhitespace(currentChild)) {
|
|
17516
|
-
continue;
|
|
17517
|
-
}
|
|
17518
|
-
if (startsWithWhitespace(nextChild)) {
|
|
17519
|
-
continue;
|
|
17520
|
-
}
|
|
17521
|
-
childrenWithGap.push(separator);
|
|
17230
|
+
.navi_icon[data-has-width][data-has-height] > svg,
|
|
17231
|
+
.navi_icon[data-has-width][data-has-height] > img {
|
|
17232
|
+
width: 100%;
|
|
17233
|
+
height: 100%;
|
|
17522
17234
|
}
|
|
17523
|
-
|
|
17524
|
-
|
|
17525
|
-
|
|
17526
|
-
|
|
17527
|
-
|
|
17235
|
+
|
|
17236
|
+
.navi_icon[data-icon-char] svg,
|
|
17237
|
+
.navi_icon[data-icon-char] img {
|
|
17238
|
+
width: 100%;
|
|
17239
|
+
height: 100%;
|
|
17528
17240
|
}
|
|
17529
|
-
|
|
17530
|
-
|
|
17531
|
-
const startsWithWhitespace = jsxChild => {
|
|
17532
|
-
if (typeof jsxChild === "string") {
|
|
17533
|
-
return /^\s/.test(jsxChild);
|
|
17241
|
+
.navi_icon[data-icon-char] svg {
|
|
17242
|
+
overflow: visible;
|
|
17534
17243
|
}
|
|
17535
|
-
|
|
17536
|
-
|
|
17537
|
-
|
|
17538
|
-
|
|
17539
|
-
|
|
17540
|
-
|
|
17541
|
-
|
|
17244
|
+
`;
|
|
17245
|
+
const Icon = ({
|
|
17246
|
+
href,
|
|
17247
|
+
children,
|
|
17248
|
+
charWidth = 1,
|
|
17249
|
+
// 0 (zéro) is the real char width
|
|
17250
|
+
// but 2 zéros gives too big icons
|
|
17251
|
+
// while 1 "W" gives a nice result
|
|
17252
|
+
baseChar = "W",
|
|
17253
|
+
decorative,
|
|
17254
|
+
onClick,
|
|
17255
|
+
...props
|
|
17256
|
+
}) => {
|
|
17257
|
+
const innerChildren = href ? jsx("svg", {
|
|
17258
|
+
width: "100%",
|
|
17259
|
+
height: "100%",
|
|
17260
|
+
children: jsx("use", {
|
|
17261
|
+
href: href
|
|
17262
|
+
})
|
|
17263
|
+
}) : children;
|
|
17264
|
+
let {
|
|
17265
|
+
box,
|
|
17266
|
+
width,
|
|
17267
|
+
height
|
|
17542
17268
|
} = props;
|
|
17543
|
-
if (
|
|
17544
|
-
|
|
17545
|
-
|
|
17546
|
-
|
|
17269
|
+
if (width === "auto") width = undefined;
|
|
17270
|
+
if (height === "auto") height = undefined;
|
|
17271
|
+
const hasExplicitWidth = width !== undefined;
|
|
17272
|
+
const hasExplicitHeight = height !== undefined;
|
|
17273
|
+
if (!hasExplicitWidth && !hasExplicitHeight) {
|
|
17274
|
+
if (decorative === undefined && !onClick) {
|
|
17275
|
+
decorative = true;
|
|
17276
|
+
}
|
|
17277
|
+
} else {
|
|
17278
|
+
box = true;
|
|
17547
17279
|
}
|
|
17548
|
-
|
|
17549
|
-
|
|
17550
|
-
|
|
17280
|
+
const ariaProps = decorative ? {
|
|
17281
|
+
"aria-hidden": "true"
|
|
17282
|
+
} : {};
|
|
17283
|
+
if (typeof children === "string") {
|
|
17284
|
+
return jsx(Text, {
|
|
17285
|
+
...props,
|
|
17286
|
+
...ariaProps,
|
|
17287
|
+
"data-icon-text": "",
|
|
17288
|
+
children: children
|
|
17551
17289
|
});
|
|
17552
17290
|
}
|
|
17553
|
-
if (
|
|
17554
|
-
return jsx(
|
|
17555
|
-
|
|
17291
|
+
if (box) {
|
|
17292
|
+
return jsx(Box, {
|
|
17293
|
+
square: true,
|
|
17294
|
+
...props,
|
|
17295
|
+
...ariaProps,
|
|
17296
|
+
box: box,
|
|
17297
|
+
baseClassName: "navi_icon",
|
|
17298
|
+
"data-has-width": hasExplicitWidth ? "" : undefined,
|
|
17299
|
+
"data-has-height": hasExplicitHeight ? "" : undefined,
|
|
17300
|
+
"data-interactive": onClick ? "" : undefined,
|
|
17301
|
+
onClick: onClick,
|
|
17302
|
+
children: innerChildren
|
|
17556
17303
|
});
|
|
17557
17304
|
}
|
|
17558
|
-
|
|
17559
|
-
|
|
17305
|
+
const invisibleText = baseChar.repeat(charWidth);
|
|
17306
|
+
return jsxs(Text, {
|
|
17307
|
+
...props,
|
|
17308
|
+
...ariaProps,
|
|
17309
|
+
className: withPropsClassName("navi_icon", props.className),
|
|
17310
|
+
spacing: "pre",
|
|
17311
|
+
"data-icon-char": "",
|
|
17312
|
+
"data-has-width": hasExplicitWidth ? "" : undefined,
|
|
17313
|
+
"data-has-height": hasExplicitHeight ? "" : undefined,
|
|
17314
|
+
"data-interactive": onClick ? "" : undefined,
|
|
17315
|
+
onClick: onClick,
|
|
17316
|
+
children: [jsx("span", {
|
|
17317
|
+
className: "navi_icon_char_slot",
|
|
17318
|
+
"aria-hidden": "true",
|
|
17319
|
+
children: invisibleText
|
|
17320
|
+
}), jsx(Text, {
|
|
17321
|
+
className: "navi_icon_foreground",
|
|
17322
|
+
spacing: "pre",
|
|
17323
|
+
children: innerChildren
|
|
17324
|
+
})]
|
|
17560
17325
|
});
|
|
17561
17326
|
};
|
|
17562
|
-
|
|
17563
|
-
|
|
17564
|
-
|
|
17565
|
-
|
|
17566
|
-
|
|
17567
|
-
|
|
17568
|
-
|
|
17569
|
-
|
|
17570
|
-
|
|
17571
|
-
|
|
17572
|
-
|
|
17573
|
-
|
|
17574
|
-
|
|
17575
|
-
|
|
17576
|
-
|
|
17577
|
-
|
|
17578
|
-
|
|
17579
|
-
|
|
17580
|
-
|
|
17581
|
-
|
|
17582
|
-
|
|
17583
|
-
|
|
17584
|
-
|
|
17585
|
-
|
|
17586
|
-
|
|
17587
|
-
|
|
17588
|
-
|
|
17327
|
+
|
|
17328
|
+
const EmailSvg = () => {
|
|
17329
|
+
return jsxs("svg", {
|
|
17330
|
+
viewBox: "0 0 24 24",
|
|
17331
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
17332
|
+
children: [jsx("path", {
|
|
17333
|
+
d: "M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z",
|
|
17334
|
+
fill: "none",
|
|
17335
|
+
stroke: "currentColor",
|
|
17336
|
+
"stroke-width": "2"
|
|
17337
|
+
}), jsx("path", {
|
|
17338
|
+
d: "m2 6 8 5 2 1.5 2-1.5 8-5",
|
|
17339
|
+
fill: "none",
|
|
17340
|
+
stroke: "currentColor",
|
|
17341
|
+
"stroke-width": "2",
|
|
17342
|
+
"stroke-linecap": "round",
|
|
17343
|
+
"stroke-linejoin": "round"
|
|
17344
|
+
})]
|
|
17345
|
+
});
|
|
17346
|
+
};
|
|
17347
|
+
|
|
17348
|
+
const LinkBlankTargetSvg = () => {
|
|
17349
|
+
return jsx("svg", {
|
|
17350
|
+
viewBox: "0 0 24 24",
|
|
17351
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
17352
|
+
children: jsx("path", {
|
|
17353
|
+
d: "M10.0002 5H8.2002C7.08009 5 6.51962 5 6.0918 5.21799C5.71547 5.40973 5.40973 5.71547 5.21799 6.0918C5 6.51962 5 7.08009 5 8.2002V15.8002C5 16.9203 5 17.4801 5.21799 17.9079C5.40973 18.2842 5.71547 18.5905 6.0918 18.7822C6.5192 19 7.07899 19 8.19691 19H15.8031C16.921 19 17.48 19 17.9074 18.7822C18.2837 18.5905 18.5905 18.2839 18.7822 17.9076C19 17.4802 19 16.921 19 15.8031V14M20 9V4M20 4H15M20 4L13 11",
|
|
17354
|
+
stroke: "currentColor",
|
|
17355
|
+
fill: "none",
|
|
17356
|
+
"stroke-width": "2",
|
|
17357
|
+
"stroke-linecap": "round",
|
|
17358
|
+
"stroke-linejoin": "round"
|
|
17589
17359
|
})
|
|
17590
17360
|
});
|
|
17591
17361
|
};
|
|
17592
|
-
const
|
|
17593
|
-
|
|
17594
|
-
|
|
17595
|
-
|
|
17596
|
-
|
|
17597
|
-
|
|
17598
|
-
|
|
17362
|
+
const LinkAnchorSvg = () => {
|
|
17363
|
+
return jsx("svg", {
|
|
17364
|
+
viewBox: "0 0 24 24",
|
|
17365
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
17366
|
+
children: jsxs("g", {
|
|
17367
|
+
children: [jsx("path", {
|
|
17368
|
+
d: "M13.2218 3.32234C15.3697 1.17445 18.8521 1.17445 21 3.32234C23.1479 5.47022 23.1479 8.95263 21 11.1005L17.4645 14.636C15.3166 16.7839 11.8342 16.7839 9.6863 14.636C9.48752 14.4373 9.30713 14.2271 9.14514 14.0075C8.90318 13.6796 8.97098 13.2301 9.25914 12.9419C9.73221 12.4688 10.5662 12.6561 11.0245 13.1435C11.0494 13.1699 11.0747 13.196 11.1005 13.2218C12.4673 14.5887 14.6834 14.5887 16.0503 13.2218L19.5858 9.6863C20.9526 8.31947 20.9526 6.10339 19.5858 4.73655C18.219 3.36972 16.0029 3.36972 14.636 4.73655L13.5754 5.79721C13.1849 6.18774 12.5517 6.18774 12.1612 5.79721C11.7706 5.40669 11.7706 4.77352 12.1612 4.383L13.2218 3.32234Z",
|
|
17369
|
+
fill: "currentColor"
|
|
17370
|
+
}), jsx("path", {
|
|
17371
|
+
d: "M6.85787 9.6863C8.90184 7.64233 12.2261 7.60094 14.3494 9.42268C14.7319 9.75083 14.7008 10.3287 14.3444 10.685C13.9253 11.1041 13.2317 11.0404 12.7416 10.707C11.398 9.79292 9.48593 9.88667 8.27209 11.1005L4.73655 14.636C3.36972 16.0029 3.36972 18.219 4.73655 19.5858C6.10339 20.9526 8.31947 20.9526 9.6863 19.5858L10.747 18.5251C11.1375 18.1346 11.7706 18.1346 12.1612 18.5251C12.5517 18.9157 12.5517 19.5488 12.1612 19.9394L11.1005 21C8.95263 23.1479 5.47022 23.1479 3.32234 21C1.17445 18.8521 1.17445 15.3697 3.32234 13.2218L6.85787 9.6863Z",
|
|
17372
|
+
fill: "currentColor"
|
|
17373
|
+
})]
|
|
17374
|
+
})
|
|
17599
17375
|
});
|
|
17600
|
-
if (!setOverflowPinnedElement) {
|
|
17601
|
-
console.warn("<Text overflowPinned> declared outside a <Text overflowEllipsis>");
|
|
17602
|
-
return text;
|
|
17603
|
-
}
|
|
17604
|
-
if (overflowPinned) {
|
|
17605
|
-
setOverflowPinnedElement(text);
|
|
17606
|
-
return null;
|
|
17607
|
-
}
|
|
17608
|
-
setOverflowPinnedElement(null);
|
|
17609
|
-
return text;
|
|
17610
17376
|
};
|
|
17611
|
-
|
|
17612
|
-
|
|
17613
|
-
|
|
17614
|
-
|
|
17615
|
-
|
|
17616
|
-
|
|
17617
|
-
|
|
17618
|
-
|
|
17619
|
-
|
|
17620
|
-
...props
|
|
17377
|
+
|
|
17378
|
+
const PhoneSvg = () => {
|
|
17379
|
+
return jsx("svg", {
|
|
17380
|
+
viewBox: "0 0 24 24",
|
|
17381
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
17382
|
+
children: jsx("path", {
|
|
17383
|
+
d: "M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z",
|
|
17384
|
+
fill: "currentColor"
|
|
17385
|
+
})
|
|
17621
17386
|
});
|
|
17622
17387
|
};
|
|
17623
|
-
|
|
17624
|
-
|
|
17625
|
-
|
|
17626
|
-
|
|
17627
|
-
|
|
17628
|
-
|
|
17629
|
-
|
|
17630
|
-
|
|
17631
|
-
|
|
17632
|
-
|
|
17633
|
-
|
|
17634
|
-
|
|
17635
|
-
|
|
17636
|
-
|
|
17637
|
-
|
|
17638
|
-
|
|
17639
|
-
|
|
17640
|
-
|
|
17641
|
-
|
|
17388
|
+
|
|
17389
|
+
const useDebounceTrue = (value, delay = 300) => {
|
|
17390
|
+
const [debouncedTrue, setDebouncedTrue] = useState(false);
|
|
17391
|
+
const timerRef = useRef(null);
|
|
17392
|
+
|
|
17393
|
+
useLayoutEffect(() => {
|
|
17394
|
+
// If value is true or becomes true, start a timer
|
|
17395
|
+
if (value) {
|
|
17396
|
+
timerRef.current = setTimeout(() => {
|
|
17397
|
+
setDebouncedTrue(true);
|
|
17398
|
+
}, delay);
|
|
17399
|
+
} else {
|
|
17400
|
+
// If value becomes false, clear any pending timer and immediately set to false
|
|
17401
|
+
if (timerRef.current) {
|
|
17402
|
+
clearTimeout(timerRef.current);
|
|
17403
|
+
timerRef.current = null;
|
|
17404
|
+
}
|
|
17405
|
+
setDebouncedTrue(false);
|
|
17406
|
+
}
|
|
17407
|
+
|
|
17408
|
+
// Cleanup function
|
|
17409
|
+
return () => {
|
|
17410
|
+
if (timerRef.current) {
|
|
17411
|
+
clearTimeout(timerRef.current);
|
|
17412
|
+
}
|
|
17413
|
+
};
|
|
17414
|
+
}, [value, delay]);
|
|
17415
|
+
|
|
17416
|
+
return debouncedTrue;
|
|
17417
|
+
};
|
|
17418
|
+
|
|
17419
|
+
const useNetworkSpeed = () => {
|
|
17420
|
+
return networkSpeedSignal.value;
|
|
17421
|
+
};
|
|
17422
|
+
|
|
17423
|
+
const connection =
|
|
17424
|
+
window.navigator.connection ||
|
|
17425
|
+
window.navigator.mozConnection ||
|
|
17426
|
+
window.navigator.webkitConnection;
|
|
17427
|
+
|
|
17428
|
+
const getNetworkSpeed = () => {
|
|
17429
|
+
// ✅ Network Information API (support moderne)
|
|
17430
|
+
if (!connection) {
|
|
17431
|
+
return "3g";
|
|
17642
17432
|
}
|
|
17643
|
-
if (
|
|
17644
|
-
const
|
|
17645
|
-
|
|
17646
|
-
|
|
17647
|
-
|
|
17648
|
-
|
|
17649
|
-
|
|
17650
|
-
|
|
17651
|
-
"
|
|
17652
|
-
|
|
17653
|
-
|
|
17654
|
-
|
|
17655
|
-
|
|
17656
|
-
}), children]
|
|
17657
|
-
});
|
|
17433
|
+
if (connection) {
|
|
17434
|
+
const effectiveType = connection.effectiveType;
|
|
17435
|
+
if (effectiveType) {
|
|
17436
|
+
return effectiveType; // "slow-2g", "2g", "3g", "4g", "5g"
|
|
17437
|
+
}
|
|
17438
|
+
const downlink = connection.downlink;
|
|
17439
|
+
if (downlink) {
|
|
17440
|
+
// downlink is in Mbps
|
|
17441
|
+
if (downlink < 1) return "slow-2g"; // < 1 Mbps
|
|
17442
|
+
if (downlink < 2.5) return "2g"; // 1-2.5 Mbps
|
|
17443
|
+
if (downlink < 10) return "3g"; // 2.5-10 Mbps
|
|
17444
|
+
return "4g"; // > 10 Mbps
|
|
17445
|
+
}
|
|
17658
17446
|
}
|
|
17659
|
-
|
|
17660
|
-
|
|
17447
|
+
return "3g";
|
|
17448
|
+
};
|
|
17661
17449
|
|
|
17662
|
-
|
|
17663
|
-
|
|
17664
|
-
|
|
17665
|
-
|
|
17666
|
-
|
|
17667
|
-
|
|
17668
|
-
|
|
17669
|
-
|
|
17670
|
-
|
|
17671
|
-
|
|
17672
|
-
|
|
17673
|
-
|
|
17674
|
-
|
|
17675
|
-
|
|
17676
|
-
|
|
17677
|
-
"data-align": alignX,
|
|
17678
|
-
children: children
|
|
17679
|
-
})]
|
|
17680
|
-
})
|
|
17450
|
+
const updateNetworkSpeed = () => {
|
|
17451
|
+
networkSpeedSignal.value = getNetworkSpeed();
|
|
17452
|
+
};
|
|
17453
|
+
|
|
17454
|
+
const networkSpeedSignal = signal(getNetworkSpeed());
|
|
17455
|
+
|
|
17456
|
+
const setupNetworkMonitoring = () => {
|
|
17457
|
+
const cleanupFunctions = [];
|
|
17458
|
+
|
|
17459
|
+
// ✅ 1. Écouter les changements natifs
|
|
17460
|
+
|
|
17461
|
+
if (connection) {
|
|
17462
|
+
connection.addEventListener("change", updateNetworkSpeed);
|
|
17463
|
+
cleanupFunctions.push(() => {
|
|
17464
|
+
connection.removeEventListener("change", updateNetworkSpeed);
|
|
17681
17465
|
});
|
|
17682
17466
|
}
|
|
17683
|
-
|
|
17684
|
-
|
|
17685
|
-
|
|
17467
|
+
|
|
17468
|
+
// ✅ 2. Polling de backup (toutes les 60 secondes)
|
|
17469
|
+
const pollInterval = setInterval(updateNetworkSpeed, 60000);
|
|
17470
|
+
cleanupFunctions.push(() => clearInterval(pollInterval));
|
|
17471
|
+
|
|
17472
|
+
// ✅ 3. Vérifier lors de la reprise d'activité
|
|
17473
|
+
const handleVisibilityChange = () => {
|
|
17474
|
+
if (!document.hidden) {
|
|
17475
|
+
updateNetworkSpeed();
|
|
17476
|
+
}
|
|
17477
|
+
};
|
|
17478
|
+
|
|
17479
|
+
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
17480
|
+
cleanupFunctions.push(() => {
|
|
17481
|
+
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
17686
17482
|
});
|
|
17687
|
-
};
|
|
17688
17483
|
|
|
17689
|
-
|
|
17690
|
-
|
|
17691
|
-
|
|
17692
|
-
|
|
17693
|
-
max-width: 100%;
|
|
17694
|
-
max-height: 100%;
|
|
17484
|
+
// ✅ 4. Vérifier lors de la reprise de connexion
|
|
17485
|
+
const handleOnline = () => {
|
|
17486
|
+
updateNetworkSpeed();
|
|
17487
|
+
};
|
|
17695
17488
|
|
|
17696
|
-
|
|
17697
|
-
|
|
17698
|
-
|
|
17699
|
-
|
|
17700
|
-
&[data-icon-char] {
|
|
17701
|
-
flex-grow: 0 !important;
|
|
17702
|
-
line-height: normal;
|
|
17703
|
-
}
|
|
17704
|
-
}
|
|
17489
|
+
window.addEventListener("online", handleOnline);
|
|
17490
|
+
cleanupFunctions.push(() => {
|
|
17491
|
+
window.removeEventListener("online", handleOnline);
|
|
17492
|
+
});
|
|
17705
17493
|
|
|
17706
|
-
|
|
17707
|
-
|
|
17708
|
-
|
|
17494
|
+
// Cleanup global
|
|
17495
|
+
return () => {
|
|
17496
|
+
cleanupFunctions.forEach((cleanup) => cleanup());
|
|
17497
|
+
};
|
|
17498
|
+
};
|
|
17499
|
+
setupNetworkMonitoring();
|
|
17709
17500
|
|
|
17710
|
-
|
|
17711
|
-
|
|
17712
|
-
|
|
17713
|
-
user-select: none;
|
|
17714
|
-
}
|
|
17715
|
-
.navi_icon_foreground {
|
|
17716
|
-
position: absolute;
|
|
17717
|
-
inset: 0;
|
|
17718
|
-
}
|
|
17719
|
-
.navi_icon_foreground > .navi_text {
|
|
17501
|
+
installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
17502
|
+
.navi_rectangle_loading {
|
|
17503
|
+
position: relative;
|
|
17720
17504
|
display: flex;
|
|
17721
|
-
aspect-ratio: 1 / 1;
|
|
17722
|
-
min-width: 0;
|
|
17723
|
-
height: 100%;
|
|
17724
|
-
max-height: 1em;
|
|
17725
|
-
align-items: center;
|
|
17726
|
-
justify-content: center;
|
|
17727
|
-
}
|
|
17728
|
-
|
|
17729
|
-
.navi_icon > svg,
|
|
17730
|
-
.navi_icon > img {
|
|
17731
17505
|
width: 100%;
|
|
17732
17506
|
height: 100%;
|
|
17733
|
-
|
|
17734
|
-
}
|
|
17735
|
-
.navi_icon[data-has-width] > svg,
|
|
17736
|
-
.navi_icon[data-has-width] > img {
|
|
17737
|
-
width: 100%;
|
|
17738
|
-
height: auto;
|
|
17507
|
+
opacity: 0;
|
|
17739
17508
|
}
|
|
17740
|
-
|
|
17741
|
-
.
|
|
17742
|
-
|
|
17743
|
-
height: 100%;
|
|
17509
|
+
|
|
17510
|
+
.navi_rectangle_loading[data-visible] {
|
|
17511
|
+
opacity: 1;
|
|
17744
17512
|
}
|
|
17745
|
-
|
|
17746
|
-
|
|
17747
|
-
|
|
17748
|
-
|
|
17513
|
+
`;
|
|
17514
|
+
const RectangleLoading = ({
|
|
17515
|
+
shouldShowSpinner,
|
|
17516
|
+
color = "currentColor",
|
|
17517
|
+
radius = 0,
|
|
17518
|
+
size = 2
|
|
17519
|
+
}) => {
|
|
17520
|
+
const containerRef = useRef(null);
|
|
17521
|
+
const [containerWidth, setContainerWidth] = useState(0);
|
|
17522
|
+
const [containerHeight, setContainerHeight] = useState(0);
|
|
17523
|
+
useLayoutEffect(() => {
|
|
17524
|
+
const container = containerRef.current;
|
|
17525
|
+
if (!container) {
|
|
17526
|
+
return null;
|
|
17527
|
+
}
|
|
17528
|
+
const {
|
|
17529
|
+
width,
|
|
17530
|
+
height
|
|
17531
|
+
} = container.getBoundingClientRect();
|
|
17532
|
+
setContainerWidth(width);
|
|
17533
|
+
setContainerHeight(height);
|
|
17534
|
+
let animationFrameId = null;
|
|
17535
|
+
// Create a resize observer to detect changes in the container's dimensions
|
|
17536
|
+
const resizeObserver = new ResizeObserver(entries => {
|
|
17537
|
+
// Use requestAnimationFrame to debounce updates
|
|
17538
|
+
if (animationFrameId) {
|
|
17539
|
+
cancelAnimationFrame(animationFrameId);
|
|
17540
|
+
}
|
|
17541
|
+
animationFrameId = requestAnimationFrame(() => {
|
|
17542
|
+
const [containerEntry] = entries;
|
|
17543
|
+
const {
|
|
17544
|
+
width,
|
|
17545
|
+
height
|
|
17546
|
+
} = containerEntry.contentRect;
|
|
17547
|
+
setContainerWidth(width);
|
|
17548
|
+
setContainerHeight(height);
|
|
17549
|
+
});
|
|
17550
|
+
});
|
|
17551
|
+
resizeObserver.observe(container);
|
|
17552
|
+
return () => {
|
|
17553
|
+
if (animationFrameId) {
|
|
17554
|
+
cancelAnimationFrame(animationFrameId);
|
|
17555
|
+
}
|
|
17556
|
+
resizeObserver.disconnect();
|
|
17557
|
+
};
|
|
17558
|
+
}, []);
|
|
17559
|
+
return jsx("span", {
|
|
17560
|
+
ref: containerRef,
|
|
17561
|
+
className: "navi_rectangle_loading",
|
|
17562
|
+
"data-visible": shouldShowSpinner ? "" : undefined,
|
|
17563
|
+
children: containerWidth > 0 && containerHeight > 0 && jsx(RectangleLoadingSvg, {
|
|
17564
|
+
radius: radius,
|
|
17565
|
+
color: color,
|
|
17566
|
+
width: containerWidth,
|
|
17567
|
+
height: containerHeight,
|
|
17568
|
+
strokeWidth: size
|
|
17569
|
+
})
|
|
17570
|
+
});
|
|
17571
|
+
};
|
|
17572
|
+
const RectangleLoadingSvg = ({
|
|
17573
|
+
width,
|
|
17574
|
+
height,
|
|
17575
|
+
color,
|
|
17576
|
+
radius,
|
|
17577
|
+
trailColor = "transparent",
|
|
17578
|
+
strokeWidth
|
|
17579
|
+
}) => {
|
|
17580
|
+
const margin = Math.max(2, Math.min(width, height) * 0.03);
|
|
17581
|
+
|
|
17582
|
+
// Calculate the drawable area
|
|
17583
|
+
const drawableWidth = width - margin * 2;
|
|
17584
|
+
const drawableHeight = height - margin * 2;
|
|
17585
|
+
|
|
17586
|
+
// ✅ Check if this should be a circle - only if width and height are nearly equal
|
|
17587
|
+
const maxPossibleRadius = Math.min(drawableWidth, drawableHeight) / 2;
|
|
17588
|
+
const actualRadius = Math.min(radius || Math.min(drawableWidth, drawableHeight) * 0.05, maxPossibleRadius // ✅ Limité au radius maximum possible
|
|
17589
|
+
);
|
|
17590
|
+
const aspectRatio = Math.max(drawableWidth, drawableHeight) / Math.min(drawableWidth, drawableHeight);
|
|
17591
|
+
const isNearlySquare = aspectRatio <= 1.2; // Allow some tolerance for nearly square shapes
|
|
17592
|
+
const isCircle = isNearlySquare && actualRadius >= maxPossibleRadius * 0.95;
|
|
17593
|
+
let pathLength;
|
|
17594
|
+
let rectPath;
|
|
17595
|
+
if (isCircle) {
|
|
17596
|
+
// ✅ Circle: perimeter = 2πr
|
|
17597
|
+
pathLength = 2 * Math.PI * actualRadius;
|
|
17598
|
+
|
|
17599
|
+
// ✅ Circle path centered in the drawable area
|
|
17600
|
+
const centerX = margin + drawableWidth / 2;
|
|
17601
|
+
const centerY = margin + drawableHeight / 2;
|
|
17602
|
+
rectPath = `
|
|
17603
|
+
M ${centerX + actualRadius},${centerY}
|
|
17604
|
+
A ${actualRadius},${actualRadius} 0 1 1 ${centerX - actualRadius},${centerY}
|
|
17605
|
+
A ${actualRadius},${actualRadius} 0 1 1 ${centerX + actualRadius},${centerY}
|
|
17606
|
+
`;
|
|
17607
|
+
} else {
|
|
17608
|
+
// ✅ Rectangle: calculate perimeter properly
|
|
17609
|
+
const straightEdges = 2 * (drawableWidth - 2 * actualRadius) + 2 * (drawableHeight - 2 * actualRadius);
|
|
17610
|
+
const cornerArcs = actualRadius > 0 ? 2 * Math.PI * actualRadius : 0;
|
|
17611
|
+
pathLength = straightEdges + cornerArcs;
|
|
17612
|
+
rectPath = `
|
|
17613
|
+
M ${margin + actualRadius},${margin}
|
|
17614
|
+
L ${margin + drawableWidth - actualRadius},${margin}
|
|
17615
|
+
A ${actualRadius},${actualRadius} 0 0 1 ${margin + drawableWidth},${margin + actualRadius}
|
|
17616
|
+
L ${margin + drawableWidth},${margin + drawableHeight - actualRadius}
|
|
17617
|
+
A ${actualRadius},${actualRadius} 0 0 1 ${margin + drawableWidth - actualRadius},${margin + drawableHeight}
|
|
17618
|
+
L ${margin + actualRadius},${margin + drawableHeight}
|
|
17619
|
+
A ${actualRadius},${actualRadius} 0 0 1 ${margin},${margin + drawableHeight - actualRadius}
|
|
17620
|
+
L ${margin},${margin + actualRadius}
|
|
17621
|
+
A ${actualRadius},${actualRadius} 0 0 1 ${margin + actualRadius},${margin}
|
|
17622
|
+
`;
|
|
17749
17623
|
}
|
|
17750
17624
|
|
|
17751
|
-
|
|
17752
|
-
|
|
17753
|
-
|
|
17754
|
-
|
|
17625
|
+
// Fixed segment size in pixels
|
|
17626
|
+
const maxSegmentSize = 40;
|
|
17627
|
+
const segmentLength = Math.min(maxSegmentSize, pathLength * 0.25);
|
|
17628
|
+
const gapLength = pathLength - segmentLength;
|
|
17629
|
+
|
|
17630
|
+
// Vitesse constante en pixels par seconde
|
|
17631
|
+
const networkSpeed = useNetworkSpeed();
|
|
17632
|
+
const pixelsPerSecond = {
|
|
17633
|
+
"slow-2g": 40,
|
|
17634
|
+
"2g": 60,
|
|
17635
|
+
"3g": 80,
|
|
17636
|
+
"4g": 120
|
|
17637
|
+
}[networkSpeed] || 80;
|
|
17638
|
+
const animationDuration = Math.max(1.5, pathLength / pixelsPerSecond);
|
|
17639
|
+
|
|
17640
|
+
// ✅ Calculate correct offset based on actual segment size
|
|
17641
|
+
const segmentRatio = segmentLength / pathLength;
|
|
17642
|
+
const circleOffset = -animationDuration * segmentRatio;
|
|
17643
|
+
return jsxs("svg", {
|
|
17644
|
+
width: "100%",
|
|
17645
|
+
height: "100%",
|
|
17646
|
+
viewBox: `0 0 ${width} ${height}`,
|
|
17647
|
+
preserveAspectRatio: "none",
|
|
17648
|
+
style: "overflow: visible",
|
|
17649
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
17650
|
+
"shape-rendering": "geometricPrecision",
|
|
17651
|
+
children: [isCircle ? jsx("circle", {
|
|
17652
|
+
cx: margin + drawableWidth / 2,
|
|
17653
|
+
cy: margin + drawableHeight / 2,
|
|
17654
|
+
r: actualRadius,
|
|
17655
|
+
fill: "none",
|
|
17656
|
+
stroke: trailColor,
|
|
17657
|
+
strokeWidth: strokeWidth
|
|
17658
|
+
}) : jsx("rect", {
|
|
17659
|
+
x: margin,
|
|
17660
|
+
y: margin,
|
|
17661
|
+
width: drawableWidth,
|
|
17662
|
+
height: drawableHeight,
|
|
17663
|
+
fill: "none",
|
|
17664
|
+
stroke: trailColor,
|
|
17665
|
+
strokeWidth: strokeWidth,
|
|
17666
|
+
rx: actualRadius
|
|
17667
|
+
}), jsx("path", {
|
|
17668
|
+
d: rectPath,
|
|
17669
|
+
fill: "none",
|
|
17670
|
+
stroke: color,
|
|
17671
|
+
strokeWidth: strokeWidth,
|
|
17672
|
+
strokeLinecap: "round",
|
|
17673
|
+
strokeDasharray: `${segmentLength} ${gapLength}`,
|
|
17674
|
+
pathLength: pathLength,
|
|
17675
|
+
children: jsx("animate", {
|
|
17676
|
+
attributeName: "stroke-dashoffset",
|
|
17677
|
+
from: pathLength,
|
|
17678
|
+
to: "0",
|
|
17679
|
+
dur: `${animationDuration}s`,
|
|
17680
|
+
repeatCount: "indefinite",
|
|
17681
|
+
begin: "0s"
|
|
17682
|
+
})
|
|
17683
|
+
}), jsx("circle", {
|
|
17684
|
+
r: strokeWidth,
|
|
17685
|
+
fill: color,
|
|
17686
|
+
children: jsx("animateMotion", {
|
|
17687
|
+
path: rectPath,
|
|
17688
|
+
dur: `${animationDuration}s`,
|
|
17689
|
+
repeatCount: "indefinite",
|
|
17690
|
+
rotate: "auto",
|
|
17691
|
+
begin: `${circleOffset}s`
|
|
17692
|
+
})
|
|
17693
|
+
})]
|
|
17694
|
+
});
|
|
17695
|
+
};
|
|
17696
|
+
|
|
17697
|
+
installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
17698
|
+
.navi_loading_rectangle_wrapper {
|
|
17699
|
+
position: absolute;
|
|
17700
|
+
top: var(--rectangle-top, 0);
|
|
17701
|
+
right: var(--rectangle-right, 0);
|
|
17702
|
+
bottom: var(--rectangle-bottom, 0);
|
|
17703
|
+
left: var(--rectangle-left, 0);
|
|
17704
|
+
z-index: 1;
|
|
17705
|
+
opacity: 0;
|
|
17706
|
+
pointer-events: none;
|
|
17755
17707
|
}
|
|
17756
|
-
.
|
|
17757
|
-
|
|
17708
|
+
.navi_loading_rectangle_wrapper[data-visible] {
|
|
17709
|
+
opacity: 1;
|
|
17758
17710
|
}
|
|
17759
17711
|
`;
|
|
17760
|
-
const
|
|
17761
|
-
|
|
17762
|
-
|
|
17763
|
-
|
|
17764
|
-
|
|
17765
|
-
|
|
17766
|
-
|
|
17767
|
-
|
|
17768
|
-
|
|
17769
|
-
|
|
17770
|
-
|
|
17771
|
-
...props
|
|
17712
|
+
const LoaderBackground = ({
|
|
17713
|
+
loading,
|
|
17714
|
+
containerRef,
|
|
17715
|
+
targetSelector,
|
|
17716
|
+
color,
|
|
17717
|
+
inset = 0,
|
|
17718
|
+
spacingTop = 0,
|
|
17719
|
+
spacingLeft = 0,
|
|
17720
|
+
spacingBottom = 0,
|
|
17721
|
+
spacingRight = 0,
|
|
17722
|
+
children
|
|
17772
17723
|
}) => {
|
|
17773
|
-
|
|
17774
|
-
|
|
17775
|
-
|
|
17776
|
-
|
|
17777
|
-
href: href
|
|
17778
|
-
})
|
|
17779
|
-
}) : children;
|
|
17780
|
-
let {
|
|
17781
|
-
box,
|
|
17782
|
-
width,
|
|
17783
|
-
height
|
|
17784
|
-
} = props;
|
|
17785
|
-
if (width === "auto") width = undefined;
|
|
17786
|
-
if (height === "auto") height = undefined;
|
|
17787
|
-
const hasExplicitWidth = width !== undefined;
|
|
17788
|
-
const hasExplicitHeight = height !== undefined;
|
|
17789
|
-
if (!hasExplicitWidth && !hasExplicitHeight) {
|
|
17790
|
-
if (decorative === undefined) {
|
|
17791
|
-
decorative = true;
|
|
17724
|
+
if (containerRef) {
|
|
17725
|
+
const container = containerRef.current;
|
|
17726
|
+
if (!container) {
|
|
17727
|
+
return children;
|
|
17792
17728
|
}
|
|
17793
|
-
|
|
17794
|
-
|
|
17795
|
-
|
|
17796
|
-
|
|
17797
|
-
|
|
17798
|
-
|
|
17799
|
-
|
|
17800
|
-
|
|
17801
|
-
|
|
17802
|
-
...ariaProps,
|
|
17803
|
-
"data-icon-text": "",
|
|
17729
|
+
return createPortal(jsx(LoaderBackgroundWithPortal, {
|
|
17730
|
+
container: container,
|
|
17731
|
+
loading: loading,
|
|
17732
|
+
color: color,
|
|
17733
|
+
inset: inset,
|
|
17734
|
+
spacingTop: spacingTop,
|
|
17735
|
+
spacingLeft: spacingLeft,
|
|
17736
|
+
spacingBottom: spacingBottom,
|
|
17737
|
+
spacingRight: spacingRight,
|
|
17804
17738
|
children: children
|
|
17805
|
-
});
|
|
17739
|
+
}), container);
|
|
17806
17740
|
}
|
|
17807
|
-
|
|
17808
|
-
|
|
17809
|
-
|
|
17810
|
-
|
|
17811
|
-
|
|
17812
|
-
|
|
17813
|
-
|
|
17814
|
-
|
|
17815
|
-
|
|
17816
|
-
|
|
17817
|
-
|
|
17818
|
-
|
|
17819
|
-
|
|
17741
|
+
return jsx(LoaderBackgroundBasic, {
|
|
17742
|
+
targetSelector: targetSelector,
|
|
17743
|
+
loading: loading,
|
|
17744
|
+
color: color,
|
|
17745
|
+
inset: inset,
|
|
17746
|
+
spacingTop: spacingTop,
|
|
17747
|
+
spacingLeft: spacingLeft,
|
|
17748
|
+
spacingBottom: spacingBottom,
|
|
17749
|
+
spacingRight: spacingRight,
|
|
17750
|
+
children: children
|
|
17751
|
+
});
|
|
17752
|
+
};
|
|
17753
|
+
const LoaderBackgroundWithPortal = ({
|
|
17754
|
+
container,
|
|
17755
|
+
loading,
|
|
17756
|
+
color,
|
|
17757
|
+
inset,
|
|
17758
|
+
spacingTop,
|
|
17759
|
+
spacingLeft,
|
|
17760
|
+
spacingBottom,
|
|
17761
|
+
spacingRight,
|
|
17762
|
+
children
|
|
17763
|
+
}) => {
|
|
17764
|
+
const shouldShowSpinner = useDebounceTrue(loading, 300);
|
|
17765
|
+
if (!shouldShowSpinner) {
|
|
17766
|
+
return children;
|
|
17767
|
+
}
|
|
17768
|
+
container.style.position = "relative";
|
|
17769
|
+
let paddingTop = 0;
|
|
17770
|
+
if (container.nodeName === "DETAILS") {
|
|
17771
|
+
paddingTop = container.querySelector("summary").offsetHeight;
|
|
17772
|
+
}
|
|
17773
|
+
return jsxs(Fragment, {
|
|
17774
|
+
children: [jsx("div", {
|
|
17775
|
+
style: {
|
|
17776
|
+
position: "absolute",
|
|
17777
|
+
top: `${inset + paddingTop + spacingTop}px`,
|
|
17778
|
+
bottom: `${inset + spacingBottom}px`,
|
|
17779
|
+
left: `${inset + spacingLeft}px`,
|
|
17780
|
+
right: `${inset + spacingRight}px`
|
|
17781
|
+
},
|
|
17782
|
+
children: shouldShowSpinner && jsx(RectangleLoading, {
|
|
17783
|
+
color: color
|
|
17784
|
+
})
|
|
17785
|
+
}), children]
|
|
17786
|
+
});
|
|
17787
|
+
};
|
|
17788
|
+
const LoaderBackgroundBasic = ({
|
|
17789
|
+
loading,
|
|
17790
|
+
targetSelector,
|
|
17791
|
+
color,
|
|
17792
|
+
spacingTop,
|
|
17793
|
+
spacingLeft,
|
|
17794
|
+
spacingBottom,
|
|
17795
|
+
spacingRight,
|
|
17796
|
+
inset,
|
|
17797
|
+
children
|
|
17798
|
+
}) => {
|
|
17799
|
+
const shouldShowSpinner = useDebounceTrue(loading, 300);
|
|
17800
|
+
const rectangleRef = useRef(null);
|
|
17801
|
+
const [, setOutlineOffset] = useState(0);
|
|
17802
|
+
const [borderRadius, setBorderRadius] = useState(0);
|
|
17803
|
+
const [borderTopWidth, setBorderTopWidth] = useState(0);
|
|
17804
|
+
const [borderLeftWidth, setBorderLeftWidth] = useState(0);
|
|
17805
|
+
const [borderRightWidth, setBorderRightWidth] = useState(0);
|
|
17806
|
+
const [borderBottomWidth, setBorderBottomWidth] = useState(0);
|
|
17807
|
+
const [marginTop, setMarginTop] = useState(0);
|
|
17808
|
+
const [marginBottom, setMarginBottom] = useState(0);
|
|
17809
|
+
const [marginLeft, setMarginLeft] = useState(0);
|
|
17810
|
+
const [marginRight, setMarginRight] = useState(0);
|
|
17811
|
+
const [paddingTop, setPaddingTop] = useState(0);
|
|
17812
|
+
const [paddingLeft, setPaddingLeft] = useState(0);
|
|
17813
|
+
const [paddingRight, setPaddingRight] = useState(0);
|
|
17814
|
+
const [paddingBottom, setPaddingBottom] = useState(0);
|
|
17815
|
+
const [currentColor, setCurrentColor] = useState(color);
|
|
17816
|
+
useLayoutEffect(() => {
|
|
17817
|
+
let animationFrame;
|
|
17818
|
+
const updateStyles = () => {
|
|
17819
|
+
const rectangle = rectangleRef.current;
|
|
17820
|
+
if (!rectangle) {
|
|
17821
|
+
return;
|
|
17822
|
+
}
|
|
17823
|
+
const container = rectangle.parentElement;
|
|
17824
|
+
const containedElement = rectangle.nextElementSibling;
|
|
17825
|
+
const target = targetSelector ? container.querySelector(targetSelector) : containedElement;
|
|
17826
|
+
if (target) {
|
|
17827
|
+
const {
|
|
17828
|
+
width,
|
|
17829
|
+
height
|
|
17830
|
+
} = target.getBoundingClientRect();
|
|
17831
|
+
const containedComputedStyle = window.getComputedStyle(containedElement);
|
|
17832
|
+
const targetComputedStyle = window.getComputedStyle(target);
|
|
17833
|
+
const newBorderTopWidth = resolveCSSSize(targetComputedStyle.borderTopWidth);
|
|
17834
|
+
const newBorderLeftWidth = resolveCSSSize(targetComputedStyle.borderLeftWidth);
|
|
17835
|
+
const newBorderRightWidth = resolveCSSSize(targetComputedStyle.borderRightWidth);
|
|
17836
|
+
const newBorderBottomWidth = resolveCSSSize(targetComputedStyle.borderBottomWidth);
|
|
17837
|
+
const newBorderRadius = resolveCSSSize(targetComputedStyle.borderRadius, {
|
|
17838
|
+
availableSize: Math.min(width, height)
|
|
17839
|
+
});
|
|
17840
|
+
const newOutlineColor = targetComputedStyle.outlineColor;
|
|
17841
|
+
const newBorderColor = targetComputedStyle.borderColor;
|
|
17842
|
+
const newDetectedColor = targetComputedStyle.color;
|
|
17843
|
+
const newOutlineOffset = resolveCSSSize(targetComputedStyle.outlineOffset);
|
|
17844
|
+
const newMarginTop = resolveCSSSize(targetComputedStyle.marginTop);
|
|
17845
|
+
const newMarginBottom = resolveCSSSize(targetComputedStyle.marginBottom);
|
|
17846
|
+
const newMarginLeft = resolveCSSSize(targetComputedStyle.marginLeft);
|
|
17847
|
+
const newMarginRight = resolveCSSSize(targetComputedStyle.marginRight);
|
|
17848
|
+
const paddingTop = resolveCSSSize(containedComputedStyle.paddingTop);
|
|
17849
|
+
const paddingLeft = resolveCSSSize(containedComputedStyle.paddingLeft);
|
|
17850
|
+
const paddingRight = resolveCSSSize(containedComputedStyle.paddingRight);
|
|
17851
|
+
const paddingBottom = resolveCSSSize(containedComputedStyle.paddingBottom);
|
|
17852
|
+
setBorderTopWidth(newBorderTopWidth);
|
|
17853
|
+
setBorderLeftWidth(newBorderLeftWidth);
|
|
17854
|
+
setBorderRightWidth(newBorderRightWidth);
|
|
17855
|
+
setBorderBottomWidth(newBorderBottomWidth);
|
|
17856
|
+
setBorderRadius(newBorderRadius);
|
|
17857
|
+
setOutlineOffset(newOutlineOffset);
|
|
17858
|
+
setMarginTop(newMarginTop);
|
|
17859
|
+
setMarginBottom(newMarginBottom);
|
|
17860
|
+
setMarginLeft(newMarginLeft);
|
|
17861
|
+
setMarginRight(newMarginRight);
|
|
17862
|
+
setPaddingTop(paddingTop);
|
|
17863
|
+
setPaddingLeft(paddingLeft);
|
|
17864
|
+
setPaddingRight(paddingRight);
|
|
17865
|
+
setPaddingBottom(paddingBottom);
|
|
17866
|
+
if (color) {
|
|
17867
|
+
// const resolvedColor = resolveCSSColor(color, rectangle, "css");
|
|
17868
|
+
// console.log(resolvedColor);
|
|
17869
|
+
setCurrentColor(color);
|
|
17870
|
+
} else if (newOutlineColor && newOutlineColor !== "rgba(0, 0, 0, 0)" && (document.activeElement === containedElement || newBorderColor === "rgba(0, 0, 0, 0)")) {
|
|
17871
|
+
setCurrentColor(newOutlineColor);
|
|
17872
|
+
} else if (newBorderColor && newBorderColor !== "rgba(0, 0, 0, 0)") {
|
|
17873
|
+
setCurrentColor(newBorderColor);
|
|
17874
|
+
} else {
|
|
17875
|
+
setCurrentColor(newDetectedColor);
|
|
17876
|
+
}
|
|
17877
|
+
}
|
|
17878
|
+
// updateStyles is very cheap so we run it every frame
|
|
17879
|
+
animationFrame = requestAnimationFrame(updateStyles);
|
|
17880
|
+
};
|
|
17881
|
+
updateStyles();
|
|
17882
|
+
return () => {
|
|
17883
|
+
cancelAnimationFrame(animationFrame);
|
|
17884
|
+
};
|
|
17885
|
+
}, [color, targetSelector]);
|
|
17886
|
+
spacingTop += inset;
|
|
17887
|
+
// spacingTop += outlineOffset;
|
|
17888
|
+
// spacingTop -= borderTopWidth;
|
|
17889
|
+
spacingTop += marginTop;
|
|
17890
|
+
spacingLeft += inset;
|
|
17891
|
+
// spacingLeft += outlineOffset;
|
|
17892
|
+
// spacingLeft -= borderLeftWidth;
|
|
17893
|
+
spacingLeft += marginLeft;
|
|
17894
|
+
spacingRight += inset;
|
|
17895
|
+
// spacingRight += outlineOffset;
|
|
17896
|
+
// spacingRight -= borderRightWidth;
|
|
17897
|
+
spacingRight += marginRight;
|
|
17898
|
+
spacingBottom += inset;
|
|
17899
|
+
// spacingBottom += outlineOffset;
|
|
17900
|
+
// spacingBottom -= borderBottomWidth;
|
|
17901
|
+
spacingBottom += marginBottom;
|
|
17902
|
+
if (targetSelector) {
|
|
17903
|
+
// oversimplification that actually works
|
|
17904
|
+
// (simplified because it assumes the targeted element is a direct child of the contained element which may have padding)
|
|
17905
|
+
spacingTop += paddingTop;
|
|
17906
|
+
spacingLeft += paddingLeft;
|
|
17907
|
+
spacingRight += paddingRight;
|
|
17908
|
+
spacingBottom += paddingBottom;
|
|
17820
17909
|
}
|
|
17821
|
-
const
|
|
17822
|
-
|
|
17823
|
-
|
|
17824
|
-
|
|
17825
|
-
|
|
17826
|
-
|
|
17827
|
-
|
|
17828
|
-
|
|
17829
|
-
|
|
17830
|
-
"data-interactive": onClick ? "" : undefined,
|
|
17831
|
-
onClick: onClick,
|
|
17910
|
+
const maxBorderWidth = Math.max(borderTopWidth, borderLeftWidth, borderRightWidth, borderBottomWidth);
|
|
17911
|
+
const halfMaxBorderSize = maxBorderWidth / 2;
|
|
17912
|
+
const size = halfMaxBorderSize < 2 ? 2 : halfMaxBorderSize;
|
|
17913
|
+
const lineHalfSize = size / 2;
|
|
17914
|
+
spacingTop -= lineHalfSize;
|
|
17915
|
+
spacingLeft -= lineHalfSize;
|
|
17916
|
+
spacingRight -= lineHalfSize;
|
|
17917
|
+
spacingBottom -= lineHalfSize;
|
|
17918
|
+
return jsxs(Fragment, {
|
|
17832
17919
|
children: [jsx("span", {
|
|
17833
|
-
|
|
17834
|
-
|
|
17835
|
-
|
|
17836
|
-
|
|
17837
|
-
|
|
17838
|
-
|
|
17839
|
-
|
|
17840
|
-
|
|
17841
|
-
|
|
17842
|
-
|
|
17843
|
-
|
|
17844
|
-
|
|
17845
|
-
|
|
17846
|
-
|
|
17847
|
-
|
|
17848
|
-
|
|
17849
|
-
d: "M10.0002 5H8.2002C7.08009 5 6.51962 5 6.0918 5.21799C5.71547 5.40973 5.40973 5.71547 5.21799 6.0918C5 6.51962 5 7.08009 5 8.2002V15.8002C5 16.9203 5 17.4801 5.21799 17.9079C5.40973 18.2842 5.71547 18.5905 6.0918 18.7822C6.5192 19 7.07899 19 8.19691 19H15.8031C16.921 19 17.48 19 17.9074 18.7822C18.2837 18.5905 18.5905 18.2839 18.7822 17.9076C19 17.4802 19 16.921 19 15.8031V14M20 9V4M20 4H15M20 4L13 11",
|
|
17850
|
-
stroke: "currentColor",
|
|
17851
|
-
fill: "none",
|
|
17852
|
-
"stroke-width": "2",
|
|
17853
|
-
"stroke-linecap": "round",
|
|
17854
|
-
"stroke-linejoin": "round"
|
|
17855
|
-
})
|
|
17856
|
-
});
|
|
17857
|
-
};
|
|
17858
|
-
const LinkAnchorSvg = () => {
|
|
17859
|
-
return jsx("svg", {
|
|
17860
|
-
viewBox: "0 0 24 24",
|
|
17861
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
17862
|
-
children: jsxs("g", {
|
|
17863
|
-
children: [jsx("path", {
|
|
17864
|
-
d: "M13.2218 3.32234C15.3697 1.17445 18.8521 1.17445 21 3.32234C23.1479 5.47022 23.1479 8.95263 21 11.1005L17.4645 14.636C15.3166 16.7839 11.8342 16.7839 9.6863 14.636C9.48752 14.4373 9.30713 14.2271 9.14514 14.0075C8.90318 13.6796 8.97098 13.2301 9.25914 12.9419C9.73221 12.4688 10.5662 12.6561 11.0245 13.1435C11.0494 13.1699 11.0747 13.196 11.1005 13.2218C12.4673 14.5887 14.6834 14.5887 16.0503 13.2218L19.5858 9.6863C20.9526 8.31947 20.9526 6.10339 19.5858 4.73655C18.219 3.36972 16.0029 3.36972 14.636 4.73655L13.5754 5.79721C13.1849 6.18774 12.5517 6.18774 12.1612 5.79721C11.7706 5.40669 11.7706 4.77352 12.1612 4.383L13.2218 3.32234Z",
|
|
17865
|
-
fill: "currentColor"
|
|
17866
|
-
}), jsx("path", {
|
|
17867
|
-
d: "M6.85787 9.6863C8.90184 7.64233 12.2261 7.60094 14.3494 9.42268C14.7319 9.75083 14.7008 10.3287 14.3444 10.685C13.9253 11.1041 13.2317 11.0404 12.7416 10.707C11.398 9.79292 9.48593 9.88667 8.27209 11.1005L4.73655 14.636C3.36972 16.0029 3.36972 18.219 4.73655 19.5858C6.10339 20.9526 8.31947 20.9526 9.6863 19.5858L10.747 18.5251C11.1375 18.1346 11.7706 18.1346 12.1612 18.5251C12.5517 18.9157 12.5517 19.5488 12.1612 19.9394L11.1005 21C8.95263 23.1479 5.47022 23.1479 3.32234 21C1.17445 18.8521 1.17445 15.3697 3.32234 13.2218L6.85787 9.6863Z",
|
|
17868
|
-
fill: "currentColor"
|
|
17869
|
-
})]
|
|
17870
|
-
})
|
|
17920
|
+
ref: rectangleRef,
|
|
17921
|
+
className: "navi_loading_rectangle_wrapper",
|
|
17922
|
+
"data-visible": shouldShowSpinner ? "" : undefined,
|
|
17923
|
+
style: {
|
|
17924
|
+
"--rectangle-top": `${spacingTop}px`,
|
|
17925
|
+
"--rectangle-left": `${spacingLeft}px`,
|
|
17926
|
+
"--rectangle-bottom": `${spacingBottom}px`,
|
|
17927
|
+
"--rectangle-right": `${spacingRight}px`
|
|
17928
|
+
},
|
|
17929
|
+
children: loading && jsx(RectangleLoading, {
|
|
17930
|
+
shouldShowSpinner: shouldShowSpinner,
|
|
17931
|
+
color: currentColor,
|
|
17932
|
+
radius: borderRadius,
|
|
17933
|
+
size: size
|
|
17934
|
+
})
|
|
17935
|
+
}), children]
|
|
17871
17936
|
});
|
|
17872
17937
|
};
|
|
17873
17938
|
|
|
@@ -20036,16 +20101,6 @@ const LinkPlain = props => {
|
|
|
20036
20101
|
})]
|
|
20037
20102
|
});
|
|
20038
20103
|
};
|
|
20039
|
-
const PhoneSvg = () => {
|
|
20040
|
-
return jsx("svg", {
|
|
20041
|
-
viewBox: "0 0 24 24",
|
|
20042
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
20043
|
-
children: jsx("path", {
|
|
20044
|
-
d: "M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z",
|
|
20045
|
-
fill: "currentColor"
|
|
20046
|
-
})
|
|
20047
|
-
});
|
|
20048
|
-
};
|
|
20049
20104
|
const SmsSvg = () => {
|
|
20050
20105
|
return jsx("svg", {
|
|
20051
20106
|
viewBox: "0 0 24 24",
|
|
@@ -20056,25 +20111,6 @@ const SmsSvg = () => {
|
|
|
20056
20111
|
})
|
|
20057
20112
|
});
|
|
20058
20113
|
};
|
|
20059
|
-
const EmailSvg = () => {
|
|
20060
|
-
return jsxs("svg", {
|
|
20061
|
-
viewBox: "0 0 24 24",
|
|
20062
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
20063
|
-
children: [jsx("path", {
|
|
20064
|
-
d: "M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z",
|
|
20065
|
-
fill: "none",
|
|
20066
|
-
stroke: "currentColor",
|
|
20067
|
-
"stroke-width": "2"
|
|
20068
|
-
}), jsx("path", {
|
|
20069
|
-
d: "m2 6 8 5 2 1.5 2-1.5 8-5",
|
|
20070
|
-
fill: "none",
|
|
20071
|
-
stroke: "currentColor",
|
|
20072
|
-
"stroke-width": "2",
|
|
20073
|
-
"stroke-linecap": "round",
|
|
20074
|
-
"stroke-linejoin": "round"
|
|
20075
|
-
})]
|
|
20076
|
-
});
|
|
20077
|
-
};
|
|
20078
20114
|
const GithubSvg = () => {
|
|
20079
20115
|
return jsx("svg", {
|
|
20080
20116
|
viewBox: "0 0 24 24",
|
|
@@ -22451,6 +22487,15 @@ const InputRangeWithAction = props => {
|
|
|
22451
22487
|
});
|
|
22452
22488
|
};
|
|
22453
22489
|
|
|
22490
|
+
const SearchSvg = () => jsx("svg", {
|
|
22491
|
+
viewBox: "0 0 24 24",
|
|
22492
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
22493
|
+
children: jsx("path", {
|
|
22494
|
+
d: "M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z",
|
|
22495
|
+
fill: "currentColor"
|
|
22496
|
+
})
|
|
22497
|
+
});
|
|
22498
|
+
|
|
22454
22499
|
installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
22455
22500
|
@layer navi {
|
|
22456
22501
|
.navi_input {
|
|
@@ -22514,29 +22559,73 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
|
22514
22559
|
--x-background-color: var(--background-color);
|
|
22515
22560
|
--x-color: var(--color);
|
|
22516
22561
|
--x-placeholder-color: var(--placeholder-color);
|
|
22517
|
-
}
|
|
22518
22562
|
|
|
22519
|
-
|
|
22520
|
-
|
|
22521
|
-
|
|
22522
|
-
|
|
22523
|
-
|
|
22524
|
-
|
|
22525
|
-
|
|
22526
|
-
|
|
22527
|
-
|
|
22528
|
-
|
|
22529
|
-
|
|
22530
|
-
|
|
22531
|
-
|
|
22532
|
-
|
|
22533
|
-
|
|
22534
|
-
|
|
22535
|
-
|
|
22536
|
-
|
|
22537
|
-
|
|
22538
|
-
|
|
22563
|
+
.navi_native_input {
|
|
22564
|
+
box-sizing: border-box;
|
|
22565
|
+
padding-top: var(--padding-top, var(--padding-y, var(--padding, 1px)));
|
|
22566
|
+
padding-right: var(
|
|
22567
|
+
--padding-right,
|
|
22568
|
+
var(--padding-x, var(--padding, 2px))
|
|
22569
|
+
);
|
|
22570
|
+
padding-bottom: var(
|
|
22571
|
+
--padding-bottom,
|
|
22572
|
+
var(--padding-y, var(--padding, 1px))
|
|
22573
|
+
);
|
|
22574
|
+
padding-left: var(--padding-left, var(--padding-x, var(--padding, 2px)));
|
|
22575
|
+
color: var(--x-color);
|
|
22576
|
+
background-color: var(--x-background-color);
|
|
22577
|
+
border-width: var(--x-outer-width);
|
|
22578
|
+
border-width: var(--x-outer-width);
|
|
22579
|
+
border-style: solid;
|
|
22580
|
+
border-color: transparent;
|
|
22581
|
+
border-radius: var(--x-border-radius);
|
|
22582
|
+
outline-width: var(--x-border-width);
|
|
22583
|
+
outline-style: solid;
|
|
22584
|
+
outline-color: var(--x-border-color);
|
|
22585
|
+
outline-offset: calc(-1 * (var(--x-border-width)));
|
|
22586
|
+
|
|
22587
|
+
&[type="search"] {
|
|
22588
|
+
-webkit-appearance: textfield;
|
|
22589
|
+
|
|
22590
|
+
&::-webkit-search-cancel-button {
|
|
22591
|
+
display: none;
|
|
22592
|
+
}
|
|
22593
|
+
}
|
|
22594
|
+
}
|
|
22595
|
+
|
|
22596
|
+
.navi_start_icon_label {
|
|
22597
|
+
position: absolute;
|
|
22598
|
+
top: 0;
|
|
22599
|
+
bottom: 0;
|
|
22600
|
+
left: 0.25em;
|
|
22601
|
+
}
|
|
22602
|
+
.navi_end_icon_label {
|
|
22603
|
+
position: absolute;
|
|
22604
|
+
top: 0;
|
|
22605
|
+
right: 0.25em;
|
|
22606
|
+
bottom: 0;
|
|
22607
|
+
opacity: 0;
|
|
22608
|
+
pointer-events: none;
|
|
22609
|
+
}
|
|
22610
|
+
&[data-has-value] {
|
|
22611
|
+
.navi_end_icon_label {
|
|
22612
|
+
opacity: 1;
|
|
22613
|
+
pointer-events: auto;
|
|
22614
|
+
}
|
|
22615
|
+
}
|
|
22616
|
+
|
|
22617
|
+
&[data-start-icon] {
|
|
22618
|
+
.navi_native_input {
|
|
22619
|
+
padding-left: 20px;
|
|
22620
|
+
}
|
|
22621
|
+
}
|
|
22622
|
+
&[data-end-icon] {
|
|
22623
|
+
.navi_native_input {
|
|
22624
|
+
padding-right: 20px;
|
|
22625
|
+
}
|
|
22626
|
+
}
|
|
22539
22627
|
}
|
|
22628
|
+
|
|
22540
22629
|
.navi_input .navi_native_input::placeholder {
|
|
22541
22630
|
color: var(--x-placeholder-color);
|
|
22542
22631
|
}
|
|
@@ -22615,7 +22704,52 @@ const InputStyleCSSVars = {
|
|
|
22615
22704
|
color: "--color-disabled"
|
|
22616
22705
|
}
|
|
22617
22706
|
};
|
|
22618
|
-
const InputPseudoClasses = [":hover", ":active", ":focus", ":focus-visible", ":read-only", ":disabled", ":-navi-loading"];
|
|
22707
|
+
const InputPseudoClasses = [":hover", ":active", ":focus", ":focus-visible", ":read-only", ":disabled", ":-navi-loading", ":navi-has-value"];
|
|
22708
|
+
Object.assign(PSEUDO_CLASSES, {
|
|
22709
|
+
":navi-has-value": {
|
|
22710
|
+
attribute: "data-has-value",
|
|
22711
|
+
setup: (el, callback) => {
|
|
22712
|
+
const onValueChange = () => {
|
|
22713
|
+
callback();
|
|
22714
|
+
};
|
|
22715
|
+
|
|
22716
|
+
// Standard user input (typing)
|
|
22717
|
+
el.addEventListener("input", onValueChange);
|
|
22718
|
+
// Autocomplete, programmatic changes, form restoration
|
|
22719
|
+
el.addEventListener("change", onValueChange);
|
|
22720
|
+
// Form reset - need to check the form
|
|
22721
|
+
const form = el.form;
|
|
22722
|
+
const onFormReset = () => {
|
|
22723
|
+
// Form reset happens asynchronously, check value after reset completes
|
|
22724
|
+
setTimeout(onValueChange, 0);
|
|
22725
|
+
};
|
|
22726
|
+
if (form) {
|
|
22727
|
+
form.addEventListener("reset", onFormReset);
|
|
22728
|
+
}
|
|
22729
|
+
|
|
22730
|
+
// Paste events (some browsers need special handling)
|
|
22731
|
+
el.addEventListener("paste", onValueChange);
|
|
22732
|
+
// Focus events to catch programmatic changes that don't fire other events
|
|
22733
|
+
// (like when value is set before user interaction)
|
|
22734
|
+
el.addEventListener("focus", onValueChange);
|
|
22735
|
+
return () => {
|
|
22736
|
+
el.removeEventListener("input", onValueChange);
|
|
22737
|
+
el.removeEventListener("change", onValueChange);
|
|
22738
|
+
el.removeEventListener("paste", onValueChange);
|
|
22739
|
+
el.removeEventListener("focus", onValueChange);
|
|
22740
|
+
if (form) {
|
|
22741
|
+
form.removeEventListener("reset", onFormReset);
|
|
22742
|
+
}
|
|
22743
|
+
};
|
|
22744
|
+
},
|
|
22745
|
+
test: el => {
|
|
22746
|
+
if (el.value === "") {
|
|
22747
|
+
return false;
|
|
22748
|
+
}
|
|
22749
|
+
return true;
|
|
22750
|
+
}
|
|
22751
|
+
}
|
|
22752
|
+
});
|
|
22619
22753
|
const InputPseudoElements = ["::-navi-loader"];
|
|
22620
22754
|
const InputTextualBasic = props => {
|
|
22621
22755
|
const contextReadOnly = useContext(ReadOnlyContext);
|
|
@@ -22634,6 +22768,8 @@ const InputTextualBasic = props => {
|
|
|
22634
22768
|
autoFocus,
|
|
22635
22769
|
autoFocusVisible,
|
|
22636
22770
|
autoSelect,
|
|
22771
|
+
icon,
|
|
22772
|
+
cancelButton = type === "search",
|
|
22637
22773
|
...rest
|
|
22638
22774
|
} = props;
|
|
22639
22775
|
const defaultRef = useRef();
|
|
@@ -22650,10 +22786,13 @@ const InputTextualBasic = props => {
|
|
|
22650
22786
|
});
|
|
22651
22787
|
const remainingProps = useConstraints(ref, rest);
|
|
22652
22788
|
const innerOnInput = useStableCallback(onInput);
|
|
22789
|
+
const autoId = useId();
|
|
22790
|
+
const innerId = rest.id || autoId;
|
|
22653
22791
|
const renderInput = inputProps => {
|
|
22654
22792
|
return jsx(Box, {
|
|
22655
22793
|
...inputProps,
|
|
22656
22794
|
as: "input",
|
|
22795
|
+
id: innerId,
|
|
22657
22796
|
ref: ref,
|
|
22658
22797
|
type: type,
|
|
22659
22798
|
"data-value": uiState,
|
|
@@ -22684,7 +22823,19 @@ const InputTextualBasic = props => {
|
|
|
22684
22823
|
baseClassName: "navi_native_input"
|
|
22685
22824
|
});
|
|
22686
22825
|
};
|
|
22687
|
-
const renderInputMemoized = useCallback(renderInput, [type, uiState, innerValue, innerOnInput]);
|
|
22826
|
+
const renderInputMemoized = useCallback(renderInput, [type, uiState, innerValue, innerOnInput, innerId]);
|
|
22827
|
+
let innerIcon;
|
|
22828
|
+
if (icon === undefined) {
|
|
22829
|
+
if (type === "search") {
|
|
22830
|
+
innerIcon = jsx(SearchSvg, {});
|
|
22831
|
+
} else if (type === "email") {
|
|
22832
|
+
innerIcon = jsx(EmailSvg, {});
|
|
22833
|
+
} else if (type === "tel") {
|
|
22834
|
+
innerIcon = jsx(PhoneSvg, {});
|
|
22835
|
+
}
|
|
22836
|
+
} else {
|
|
22837
|
+
innerIcon = icon;
|
|
22838
|
+
}
|
|
22688
22839
|
return jsxs(Box, {
|
|
22689
22840
|
as: "span",
|
|
22690
22841
|
box: true,
|
|
@@ -22700,13 +22851,37 @@ const InputTextualBasic = props => {
|
|
|
22700
22851
|
pseudoClasses: InputPseudoClasses,
|
|
22701
22852
|
pseudoElements: InputPseudoElements,
|
|
22702
22853
|
hasChildFunction: true,
|
|
22854
|
+
"data-start-icon": innerIcon ? "" : undefined,
|
|
22855
|
+
"data-end-icon": cancelButton ? "" : undefined,
|
|
22703
22856
|
...remainingProps,
|
|
22704
22857
|
ref: undefined,
|
|
22705
22858
|
children: [jsx(LoaderBackground, {
|
|
22706
22859
|
loading: innerLoading,
|
|
22707
22860
|
color: "var(--loader-color)",
|
|
22708
22861
|
inset: -1
|
|
22709
|
-
}),
|
|
22862
|
+
}), innerIcon && jsx(Icon, {
|
|
22863
|
+
as: "label",
|
|
22864
|
+
htmlFor: innerId,
|
|
22865
|
+
className: "navi_start_icon_label",
|
|
22866
|
+
alignY: "center",
|
|
22867
|
+
color: "rgba(28, 43, 52, 0.5)",
|
|
22868
|
+
children: innerIcon
|
|
22869
|
+
}), renderInputMemoized, cancelButton && jsx(Icon, {
|
|
22870
|
+
as: "label",
|
|
22871
|
+
htmlFor: innerId,
|
|
22872
|
+
className: "navi_end_icon_label",
|
|
22873
|
+
alignY: "center",
|
|
22874
|
+
color: "rgba(28, 43, 52, 0.5)",
|
|
22875
|
+
onMousedown: e => {
|
|
22876
|
+
e.preventDefault(); // keep focus on the button
|
|
22877
|
+
},
|
|
22878
|
+
onClick: () => {
|
|
22879
|
+
uiStateController.setUIState("", {
|
|
22880
|
+
trigger: "cancel_button"
|
|
22881
|
+
});
|
|
22882
|
+
},
|
|
22883
|
+
children: jsx(CloseSvg, {})
|
|
22884
|
+
})]
|
|
22710
22885
|
});
|
|
22711
22886
|
};
|
|
22712
22887
|
const InputTextualWithAction = props => {
|
|
@@ -27221,6 +27396,69 @@ const Address = ({
|
|
|
27221
27396
|
});
|
|
27222
27397
|
};
|
|
27223
27398
|
|
|
27399
|
+
const LoadingDots = ({
|
|
27400
|
+
color = "FF156D"
|
|
27401
|
+
}) => {
|
|
27402
|
+
return jsxs("svg", {
|
|
27403
|
+
viewBox: "0 0 200 200",
|
|
27404
|
+
width: "100%",
|
|
27405
|
+
height: "100%",
|
|
27406
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
27407
|
+
children: [jsx("rect", {
|
|
27408
|
+
fill: color,
|
|
27409
|
+
stroke: color,
|
|
27410
|
+
"stroke-width": "15",
|
|
27411
|
+
width: "30",
|
|
27412
|
+
height: "30",
|
|
27413
|
+
x: "25",
|
|
27414
|
+
y: "85",
|
|
27415
|
+
children: jsx("animate", {
|
|
27416
|
+
attributeName: "opacity",
|
|
27417
|
+
calcMode: "spline",
|
|
27418
|
+
dur: "2",
|
|
27419
|
+
values: "1;0;1;",
|
|
27420
|
+
keySplines: ".5 0 .5 1;.5 0 .5 1",
|
|
27421
|
+
repeatCount: "indefinite",
|
|
27422
|
+
begin: "-.4"
|
|
27423
|
+
})
|
|
27424
|
+
}), jsx("rect", {
|
|
27425
|
+
fill: color,
|
|
27426
|
+
stroke: color,
|
|
27427
|
+
"stroke-width": "15",
|
|
27428
|
+
width: "30",
|
|
27429
|
+
height: "30",
|
|
27430
|
+
x: "85",
|
|
27431
|
+
y: "85",
|
|
27432
|
+
children: jsx("animate", {
|
|
27433
|
+
attributeName: "opacity",
|
|
27434
|
+
calcMode: "spline",
|
|
27435
|
+
dur: "2",
|
|
27436
|
+
values: "1;0;1;",
|
|
27437
|
+
keySplines: ".5 0 .5 1;.5 0 .5 1",
|
|
27438
|
+
repeatCount: "indefinite",
|
|
27439
|
+
begin: "-.2"
|
|
27440
|
+
})
|
|
27441
|
+
}), jsx("rect", {
|
|
27442
|
+
fill: color,
|
|
27443
|
+
stroke: color,
|
|
27444
|
+
"stroke-width": "15",
|
|
27445
|
+
width: "30",
|
|
27446
|
+
height: "30",
|
|
27447
|
+
x: "145",
|
|
27448
|
+
y: "85",
|
|
27449
|
+
children: jsx("animate", {
|
|
27450
|
+
attributeName: "opacity",
|
|
27451
|
+
calcMode: "spline",
|
|
27452
|
+
dur: "2",
|
|
27453
|
+
values: "1;0;1;",
|
|
27454
|
+
keySplines: ".5 0 .5 1;.5 0 .5 1",
|
|
27455
|
+
repeatCount: "indefinite",
|
|
27456
|
+
begin: "0"
|
|
27457
|
+
})
|
|
27458
|
+
})]
|
|
27459
|
+
});
|
|
27460
|
+
};
|
|
27461
|
+
|
|
27224
27462
|
const CSS_VAR_NAME = "--x-color-contrasting";
|
|
27225
27463
|
|
|
27226
27464
|
const useContrastingColor = (ref, backgroundElementSelector) => {
|
|
@@ -27388,10 +27626,11 @@ const BadgeCountCircle = ({
|
|
|
27388
27626
|
ref,
|
|
27389
27627
|
charCount,
|
|
27390
27628
|
hasOverflow,
|
|
27629
|
+
loading,
|
|
27391
27630
|
children,
|
|
27392
27631
|
...props
|
|
27393
27632
|
}) => {
|
|
27394
|
-
return
|
|
27633
|
+
return jsx(Text, {
|
|
27395
27634
|
ref: ref,
|
|
27396
27635
|
className: "navi_badge_count",
|
|
27397
27636
|
"data-circle": "",
|
|
@@ -27403,18 +27642,20 @@ const BadgeCountCircle = ({
|
|
|
27403
27642
|
...props,
|
|
27404
27643
|
styleCSSVars: BadgeStyleCSSVars,
|
|
27405
27644
|
spacing: "pre",
|
|
27406
|
-
children:
|
|
27407
|
-
|
|
27408
|
-
|
|
27409
|
-
|
|
27410
|
-
|
|
27411
|
-
|
|
27412
|
-
|
|
27413
|
-
|
|
27414
|
-
|
|
27415
|
-
|
|
27416
|
-
|
|
27417
|
-
|
|
27645
|
+
children: loading ? jsx(LoadingDots, {}) : jsxs(Fragment, {
|
|
27646
|
+
children: [jsx("span", {
|
|
27647
|
+
style: "user-select: none",
|
|
27648
|
+
children: "\u200B"
|
|
27649
|
+
}), jsx("span", {
|
|
27650
|
+
className: "navi_badge_count_frame"
|
|
27651
|
+
}), jsx("span", {
|
|
27652
|
+
className: "navi_badge_count_text",
|
|
27653
|
+
children: children
|
|
27654
|
+
}), jsx("span", {
|
|
27655
|
+
style: "user-select: none",
|
|
27656
|
+
children: "\u200B"
|
|
27657
|
+
})]
|
|
27658
|
+
})
|
|
27418
27659
|
});
|
|
27419
27660
|
};
|
|
27420
27661
|
const BadgeCountEllipse = ({
|
|
@@ -28496,15 +28737,6 @@ const HomeSvg = () => jsx("svg", {
|
|
|
28496
28737
|
})
|
|
28497
28738
|
});
|
|
28498
28739
|
|
|
28499
|
-
const SearchSvg = () => jsx("svg", {
|
|
28500
|
-
viewBox: "0 0 24 24",
|
|
28501
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
28502
|
-
children: jsx("path", {
|
|
28503
|
-
d: "M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z",
|
|
28504
|
-
fill: "currentColor"
|
|
28505
|
-
})
|
|
28506
|
-
});
|
|
28507
|
-
|
|
28508
28740
|
const SettingsSvg = () => jsx("svg", {
|
|
28509
28741
|
viewBox: "0 0 24 24",
|
|
28510
28742
|
xmlns: "http://www.w3.org/2000/svg",
|