@jsenv/navi 0.29.396 → 0.29.397

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.
@@ -6227,6 +6227,9 @@ const findControlProxyTarget = (el) => {
6227
6227
  return document.getElementById(proxyFor);
6228
6228
  };
6229
6229
 
6230
+ // Shared: asked on every pseudo state change of every box, and almost always
6231
+ // empty.
6232
+ const NO_PROXIES = Object.freeze([]);
6230
6233
  /**
6231
6234
  * Given a real control element, returns every proxy that visually represents
6232
6235
  * it — a control can have more than one (an "enable"/"disable" button pair for
@@ -6241,11 +6244,11 @@ const findControlProxyTarget = (el) => {
6241
6244
  */
6242
6245
  const findControlProxies = (el) => {
6243
6246
  if (!el.id) {
6244
- return [];
6247
+ return NO_PROXIES;
6245
6248
  }
6246
6249
  const proxyControllerSet = findProxyControllers(el.id);
6247
6250
  if (!proxyControllerSet) {
6248
- return [];
6251
+ return NO_PROXIES;
6249
6252
  }
6250
6253
  const proxyElements = [];
6251
6254
  for (const proxyController of proxyControllerSet) {
@@ -10614,15 +10617,17 @@ const resolveInteractions = (interactions) => {
10614
10617
  }
10615
10618
  }
10616
10619
  const kept = {};
10620
+ let keptSome = false;
10617
10621
  for (const type of Object.keys(resolved)) {
10618
10622
  if (resolved[type]) {
10619
10623
  kept[type] = resolved[type];
10624
+ keptSome = true;
10620
10625
  }
10621
10626
  }
10622
- resolved = kept;
10623
- if (Object.keys(resolved).length === 0) {
10627
+ if (!keptSome) {
10624
10628
  return null;
10625
10629
  }
10630
+ resolved = kept;
10626
10631
  return resolved;
10627
10632
  };
10628
10633
 
@@ -21561,8 +21566,7 @@ const getStyleToApply = (styles, pseudoState, pseudoNamedStyles) => {
21561
21566
  }
21562
21567
  let style = styles;
21563
21568
  for (const pseudoKey of Object.keys(pseudoNamedStyles)) {
21564
- const requiredStates = getPseudoKeyRequiredStates(pseudoKey);
21565
- if (!requiredStates.every((state) => pseudoState[state])) {
21569
+ if (!hasEveryState(pseudoState, getPseudoKeyRequiredStates(pseudoKey))) {
21566
21570
  continue;
21567
21571
  }
21568
21572
  if (style === styles) {
@@ -21617,6 +21621,14 @@ const getPseudoKeyRequiredStates = (pseudoKey) => {
21617
21621
  pseudoKeyRequiredStatesMap.set(pseudoKey, requiredStates);
21618
21622
  return requiredStates;
21619
21623
  };
21624
+ const hasEveryState = (pseudoState, states) => {
21625
+ for (const state of states) {
21626
+ if (!pseudoState[state]) {
21627
+ return false;
21628
+ }
21629
+ }
21630
+ return true;
21631
+ };
21620
21632
 
21621
21633
  // element → the style object last written to it, so the next one is written
21622
21634
  // as a difference: the values that changed, the keys it no longer has.
@@ -21694,7 +21706,7 @@ const updateStyle = (element, style, preventInitialTransition) => {
21694
21706
  // the browser for a frame costs more than that, and a page mounting thousands of
21695
21707
  // boxes asks thousands of times in the same tick. A Set, so an element styled
21696
21708
  // twice before the frame arrives is still one entry.
21697
- const elementSetWaitingFirstFrame = new Set();
21709
+ let elementSetWaitingFirstFrame = new Set();
21698
21710
  let firstFrameScheduled = false;
21699
21711
  const afterFirstFrame = (element) => {
21700
21712
  elementSetWaitingFirstFrame.add(element);
@@ -21704,8 +21716,8 @@ const afterFirstFrame = (element) => {
21704
21716
  firstFrameScheduled = true;
21705
21717
  requestAnimationFrame(() => {
21706
21718
  firstFrameScheduled = false;
21707
- const elements = [...elementSetWaitingFirstFrame];
21708
- elementSetWaitingFirstFrame.clear();
21719
+ const elements = elementSetWaitingFirstFrame;
21720
+ elementSetWaitingFirstFrame = new Set();
21709
21721
  for (const element of elements) {
21710
21722
  if (elementTransitionWeakMap.has(element)) {
21711
21723
  const transitionToRestore = elementTransitionWeakMap.get(element);
@@ -22017,6 +22029,7 @@ const readCSSVarEntry = entry => {
22017
22029
  }
22018
22030
  return [entry, null];
22019
22031
  };
22032
+ const readCSSVarName = entry => Array.isArray(entry) ? entry[0] : entry;
22020
22033
  // When only pseudoStateSelector is set (no visualSelector), the box owns its
22021
22034
  // visual identity. Only event handlers and these explicit props are forwarded
22022
22035
  // to the inner semantic/interactive child element.
@@ -22126,18 +22139,23 @@ const Box = props => {
22126
22139
  // exception — a closure is new on every render — so they are compared by
22127
22140
  // name only and put back fresh, see withCurrentHandlers.
22128
22141
  const renderMemoRef = useRef(null);
22142
+ if (!renderMemoRef.current) {
22143
+ renderMemoRef.current = {
22144
+ props: null,
22145
+ parentBoxFlow: null,
22146
+ computed: null
22147
+ };
22148
+ }
22129
22149
  const renderMemo = renderMemoRef.current;
22130
22150
  let computed;
22131
- if (renderMemo && renderMemo.parentBoxFlow === parentBoxFlow && arePropsEquivalent(renderMemo.props, computeProps)) {
22151
+ if (renderMemo.computed && renderMemo.parentBoxFlow === parentBoxFlow && arePropsEquivalent(renderMemo.props, computeProps)) {
22132
22152
  computed = withCurrentHandlers(renderMemo.computed, computeProps);
22133
22153
  } else {
22134
22154
  computed = computeBox(computeProps, parentBoxFlow);
22135
22155
  }
22136
- renderMemoRef.current = {
22137
- props: computeProps,
22138
- parentBoxFlow,
22139
- computed
22140
- };
22156
+ renderMemo.props = computeProps;
22157
+ renderMemo.parentBoxFlow = parentBoxFlow;
22158
+ renderMemo.computed = computed;
22141
22159
  const {
22142
22160
  TagName,
22143
22161
  boxFlow,
@@ -22169,6 +22187,16 @@ const Box = props => {
22169
22187
  children: innerChildren
22170
22188
  });
22171
22189
  }
22190
+
22191
+ // Only a Box reads the flow, and a box holding nothing but text has no Box
22192
+ // below it: the provider, a component of its own, is left out there. Moving
22193
+ // between the two shapes recreates text nodes, never a component.
22194
+ if (mayHoldComponent(innerChildren)) {
22195
+ innerChildren = jsx(BoxFlowContext.Provider, {
22196
+ value: boxFlow,
22197
+ children: innerChildren
22198
+ });
22199
+ }
22172
22200
  return jsx(TagName, {
22173
22201
  ref: finalRef,
22174
22202
  className: innerClassName,
@@ -22178,10 +22206,7 @@ const Box = props => {
22178
22206
  "navi-aspect-ratio": aspectRatio ? aspectRatio : undefined,
22179
22207
  "data-visual-selector": visualSelector,
22180
22208
  ...selfForwardedProps,
22181
- children: jsx(BoxFlowContext.Provider, {
22182
- value: boxFlow,
22183
- children: innerChildren
22184
- })
22209
+ children: innerChildren
22185
22210
  });
22186
22211
  };
22187
22212
 
@@ -22399,21 +22424,15 @@ const computeBox = (props, parentBoxFlow) => {
22399
22424
  let innerPseudoState;
22400
22425
  if (basePseudoState && pseudoState) {
22401
22426
  innerPseudoState = {};
22402
- const baseStateKeys = Object.keys(basePseudoState);
22403
- const pseudoStateKeySet = new Set(Object.keys(pseudoState));
22404
- for (const key of baseStateKeys) {
22405
- if (pseudoStateKeySet.has(key)) {
22406
- pseudoStateKeySet.delete(key);
22407
- const value = pseudoState[key];
22408
- styleDeps.push(key, value);
22409
- innerPseudoState[key] = value;
22410
- } else {
22411
- const value = basePseudoState[key];
22412
- styleDeps.push(key, value);
22413
- innerPseudoState[key] = value;
22414
- }
22427
+ for (const key of Object.keys(basePseudoState)) {
22428
+ const value = Object.hasOwn(pseudoState, key) ? pseudoState[key] : basePseudoState[key];
22429
+ styleDeps.push(key, value);
22430
+ innerPseudoState[key] = value;
22415
22431
  }
22416
- for (const key of pseudoStateKeySet) {
22432
+ for (const key of Object.keys(pseudoState)) {
22433
+ if (Object.hasOwn(basePseudoState, key)) {
22434
+ continue;
22435
+ }
22417
22436
  const value = pseudoState[key];
22418
22437
  styleDeps.push(key, value);
22419
22438
  innerPseudoState[key] = value;
@@ -22447,7 +22466,7 @@ const computeBox = (props, parentBoxFlow) => {
22447
22466
  const canForwardToChild = hasChildUsingForwardedProps;
22448
22467
  const addStyle = (value, name, styleContext, stylesTarget) => {
22449
22468
  const mergedValue = prepareStyleValue(stylesTarget[name], value, name, styleContext);
22450
- const [cssVar] = readCSSVarEntry(styleContext.styleCSSVars[name]);
22469
+ const cssVar = readCSSVarName(styleContext.styleCSSVars[name]);
22451
22470
  if (cssVar) {
22452
22471
  addCSSVar(mergedValue, cssVar, stylesTarget);
22453
22472
  if (name === "borderRadius" && value === "inherit") {
@@ -22503,12 +22522,13 @@ const computeBox = (props, parentBoxFlow) => {
22503
22522
  if (boxPseudoNamedStyles === PSEUDO_NAMED_STYLES_DEFAULT) {
22504
22523
  boxPseudoNamedStyles = {};
22505
22524
  }
22525
+ const pseudoCSSVars = styleCSSVars[name];
22506
22526
  const pseudoStyleContext = {
22507
22527
  ...styleContext,
22508
- styleCSSVars: {
22528
+ styleCSSVars: pseudoCSSVars ? {
22509
22529
  ...styleCSSVars,
22510
- ...styleCSSVars[name]
22511
- },
22530
+ ...pseudoCSSVars
22531
+ } : styleCSSVars,
22512
22532
  pseudoName: name
22513
22533
  };
22514
22534
  const pseudoStyleKeys = Object.keys(value);
@@ -22755,17 +22775,51 @@ const declaresSomething = value => {
22755
22775
  return true;
22756
22776
  };
22757
22777
  const isScrollingOverflow = value => value === "auto" || value === "scroll";
22778
+ const mayHoldComponent = children => {
22779
+ if (children === null || children === undefined) {
22780
+ return false;
22781
+ }
22782
+ const type = typeof children;
22783
+ if (type === "string" || type === "number" || type === "boolean") {
22784
+ return false;
22785
+ }
22786
+ if (Array.isArray(children)) {
22787
+ for (const child of children) {
22788
+ if (mayHoldComponent(child)) {
22789
+ return true;
22790
+ }
22791
+ }
22792
+ return false;
22793
+ }
22794
+ return true;
22795
+ };
22758
22796
 
22759
22797
  // Same props as far as computeBox is concerned. Handlers count by name only,
22760
- // see withCurrentHandlers; no style or state key starts with "on".
22761
- const arePropsEquivalent = (previousProps, props) => compareTwoJsValues(previousProps, props, {
22762
- keyComparator: comparePropAt
22763
- });
22764
- const comparePropAt = (a, b, key, recurse) => {
22765
- if (typeof key === "string" && key.startsWith("on")) {
22766
- return true;
22798
+ // see withCurrentHandlers. Identity first: most values are the very ones of
22799
+ // the previous render, only what a caller rebuilds inline (a style, a pseudo
22800
+ // state) needs the deep walk.
22801
+ const arePropsEquivalent = (previousProps, props) => {
22802
+ const keys = Object.keys(props);
22803
+ if (keys.length !== Object.keys(previousProps).length) {
22804
+ return false;
22805
+ }
22806
+ for (const key of keys) {
22807
+ if (!Object.hasOwn(previousProps, key)) {
22808
+ return false;
22809
+ }
22810
+ if (key.startsWith("on")) {
22811
+ continue;
22812
+ }
22813
+ const value = props[key];
22814
+ const previousValue = previousProps[key];
22815
+ if (value === previousValue) {
22816
+ continue;
22817
+ }
22818
+ if (!compareTwoJsValues(previousValue, value)) {
22819
+ return false;
22820
+ }
22767
22821
  }
22768
- return recurse(a, b);
22822
+ return true;
22769
22823
  };
22770
22824
  // The previous computation with this render's handlers: a handler goes where
22771
22825
  // its name went the previous time, self or child, the split being decided by