@jsenv/navi 0.14.14 → 0.14.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5088,9 +5088,15 @@ const getHowToHandleStyleProp = (name) => {
5088
5088
  }
5089
5089
  return getStyle;
5090
5090
  };
5091
- const prepareStyleValue = (existingValue, value, name, context) => {
5091
+ const prepareStyleValue = (
5092
+ existingValue,
5093
+ value,
5094
+ name,
5095
+ styleContext,
5096
+ context,
5097
+ ) => {
5092
5098
  const normalizer = getNormalizer(name);
5093
- const cssValue = normalizer(value, name);
5099
+ const cssValue = normalizer(value, name, styleContext, context);
5094
5100
  const mergedValue = mergeOneStyle(existingValue, cssValue, name, context);
5095
5101
  return mergedValue;
5096
5102
  };
@@ -5623,7 +5629,8 @@ const applyStyle = (element, style, pseudoState, pseudoNamedStyles) => {
5623
5629
  if (!element) {
5624
5630
  return;
5625
5631
  }
5626
- updateStyle(element, getStyleToApply(style, pseudoState, pseudoNamedStyles));
5632
+ const styleToApply = getStyleToApply(style, pseudoState, pseudoNamedStyles);
5633
+ updateStyle(element, styleToApply);
5627
5634
  };
5628
5635
 
5629
5636
  const PSEUDO_STATE_DEFAULT = {};
@@ -5677,40 +5684,72 @@ const getStyleToApply = (styles, pseudoState, pseudoNamedStyles) => {
5677
5684
  };
5678
5685
 
5679
5686
  const styleKeySetWeakMap = new WeakMap();
5687
+ const elementTransitionStateWeakMap = new WeakMap();
5688
+ const elementRenderedWeakSet = new WeakSet();
5689
+ const NO_STYLE_KEY_SET = new Set();
5690
+
5680
5691
  const updateStyle = (element, style) => {
5681
- const oldStyleKeySet = styleKeySetWeakMap.get(element);
5682
- const styleKeySet = new Set(style ? Object.keys(style) : []);
5683
- if (!oldStyleKeySet) {
5684
- for (const key of styleKeySet) {
5685
- if (key.startsWith("--")) {
5686
- element.style.setProperty(key, style[key]);
5692
+ const styleKeySet = style ? new Set(Object.keys(style)) : NO_STYLE_KEY_SET;
5693
+ const oldStyleKeySet = styleKeySetWeakMap.get(element) || NO_STYLE_KEY_SET;
5694
+ // TRANSITION ANTI-FLICKER STRATEGY:
5695
+ // Problem: When setting both transition and styled properties simultaneously
5696
+ // (e.g., el.style.transition = "border-radius 0.3s ease"; el.style.borderRadius = "20px"),
5697
+ // the browser will immediately perform a transition even if no transition existed before.
5698
+ //
5699
+ // Solution: Temporarily disable transitions during initial style application by setting
5700
+ // transition to "none", then restore the intended transition after the frame completes.
5701
+ // We handle multiple updateStyle calls in the same frame gracefully - only one
5702
+ // requestAnimationFrame is scheduled per element, and the final transition value wins.
5703
+ let styleKeySetToApply = styleKeySet;
5704
+ if (!elementRenderedWeakSet.has(element)) {
5705
+ const hasTransition = styleKeySet.has("transition");
5706
+ if (hasTransition) {
5707
+ if (elementTransitionStateWeakMap.has(element)) {
5708
+ elementTransitionStateWeakMap.set(element, style.transition);
5687
5709
  } else {
5688
- element.style[key] = style[key];
5710
+ element.style.transition = "none";
5711
+ elementTransitionStateWeakMap.set(element, style.transition);
5712
+ }
5713
+ // Don't apply the transition property now - we've set it to "none" temporarily
5714
+ styleKeySetToApply = new Set(styleKeySet);
5715
+ styleKeySetToApply.delete("transition");
5716
+ }
5717
+ requestAnimationFrame(() => {
5718
+ if (elementTransitionStateWeakMap.has(element)) {
5719
+ const transitionToRestore = elementTransitionStateWeakMap.get(element);
5720
+ if (transitionToRestore === undefined) {
5721
+ element.style.transition = "";
5722
+ } else {
5723
+ element.style.transition = transitionToRestore;
5724
+ }
5725
+ elementTransitionStateWeakMap.delete(element);
5689
5726
  }
5690
- }
5691
- styleKeySetWeakMap.set(element, styleKeySet);
5692
- return;
5727
+ elementRenderedWeakSet.add(element);
5728
+ });
5693
5729
  }
5694
- const toDeleteKeySet = new Set(oldStyleKeySet);
5695
- for (const key of styleKeySet) {
5696
- toDeleteKeySet.delete(key);
5730
+
5731
+ // Apply all styles normally (excluding transition during anti-flicker)
5732
+ const keysToDelete = new Set(oldStyleKeySet);
5733
+ for (const key of styleKeySetToApply) {
5734
+ keysToDelete.delete(key);
5735
+ const value = style[key];
5697
5736
  if (key.startsWith("--")) {
5698
- element.style.setProperty(key, style[key]);
5737
+ element.style.setProperty(key, value);
5699
5738
  } else {
5700
- element.style[key] = style[key];
5739
+ element.style[key] = value;
5701
5740
  }
5702
5741
  }
5703
- for (const toDeleteKey of toDeleteKeySet) {
5704
- if (toDeleteKey.startsWith("--")) {
5705
- element.style.removeProperty(toDeleteKey);
5742
+
5743
+ // Remove obsolete styles
5744
+ for (const key of keysToDelete) {
5745
+ if (key.startsWith("--")) {
5746
+ element.style.removeProperty(key);
5706
5747
  } else {
5707
- // we can't use removeProperty because "toDeleteKey" is in camelCase
5708
- // e.g., backgroundColor (and it's safer to just let the browser do the conversion)
5709
- element.style[toDeleteKey] = "";
5748
+ element.style[key] = "";
5710
5749
  }
5711
5750
  }
5751
+
5712
5752
  styleKeySetWeakMap.set(element, styleKeySet);
5713
- return;
5714
5753
  };
5715
5754
 
5716
5755
  installImportMetaCss(import.meta);import.meta.css = /* css */`
@@ -5866,7 +5905,7 @@ const Box = props => {
5866
5905
  const addStyle = (value, name, styleContext, stylesTarget, context) => {
5867
5906
  styleDeps.push(value); // impact box style -> add to deps
5868
5907
  const cssVar = styleContext.styleCSSVars[name];
5869
- const mergedValue = prepareStyleValue(stylesTarget[name], value, name, context);
5908
+ const mergedValue = prepareStyleValue(stylesTarget[name], value, name, styleContext, context);
5870
5909
  if (cssVar) {
5871
5910
  stylesTarget[cssVar] = mergedValue;
5872
5911
  return true;
@@ -14309,7 +14348,9 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
14309
14348
  .navi_icon {
14310
14349
  display: inline-block;
14311
14350
  box-sizing: border-box;
14351
+ width: 1em;
14312
14352
  max-width: 100%;
14353
+ height: 1em;
14313
14354
  max-height: 100%;
14314
14355
  }
14315
14356
 
@@ -14348,6 +14389,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
14348
14389
  .navi_icon > img {
14349
14390
  width: 100%;
14350
14391
  height: 100%;
14392
+ backface-visibility: hidden;
14351
14393
  }
14352
14394
  .navi_icon[data-width] > svg,
14353
14395
  .navi_icon[data-width] > img {
@@ -14359,6 +14401,11 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
14359
14401
  width: auto;
14360
14402
  height: 100%;
14361
14403
  }
14404
+ .navi_icon[data-width][data-height] > svg,
14405
+ .navi_icon[data-width][data-height] > img {
14406
+ width: 100%;
14407
+ height: 100%;
14408
+ }
14362
14409
 
14363
14410
  .navi_icon[data-icon-char] svg,
14364
14411
  .navi_icon[data-icon-char] img {
@@ -16510,6 +16557,7 @@ const LinkPlain = props => {
16510
16557
  icon,
16511
16558
  spacing,
16512
16559
  revealOnInteraction = Boolean(titleLevel),
16560
+ hrefFallback = !anchor,
16513
16561
  children,
16514
16562
  ...rest
16515
16563
  } = props;
@@ -16553,9 +16601,10 @@ const LinkPlain = props => {
16553
16601
  } else {
16554
16602
  innerIcon = icon;
16555
16603
  }
16604
+ const innerChildren = children || (hrefFallback ? href : children);
16556
16605
  return jsxs(Box, {
16557
16606
  as: "a",
16558
- color: anchor && !children ? "inherit" : undefined,
16607
+ color: anchor && !innerChildren ? "inherit" : undefined,
16559
16608
  id: anchor ? href.slice(1) : undefined,
16560
16609
  ...rest,
16561
16610
  ref: ref,
@@ -16607,8 +16656,8 @@ const LinkPlain = props => {
16607
16656
  children: [jsx(LoaderBackground, {
16608
16657
  loading: loading,
16609
16658
  color: "var(--link-loader-color)"
16610
- }), applySpacingOnTextChildren(children, spacing), innerIcon && jsx(Icon, {
16611
- marginLeft: children ? "xxs" : undefined,
16659
+ }), applySpacingOnTextChildren(innerChildren, spacing), innerIcon && jsx(Icon, {
16660
+ marginLeft: innerChildren ? "xxs" : undefined,
16612
16661
  children: innerIcon
16613
16662
  })]
16614
16663
  });