@astryxdesign/core 0.7.2-canary.3aca324 → 0.7.2-canary.3f45fc2

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.
@@ -172,7 +172,7 @@ const styles = {
172
172
  kI3sdo: "x1a2a7pz",
173
173
  k7VYTy: "xpdipgo",
174
174
  kfSwDN: "x87ps6o",
175
- ks0D6T: "x1p5vr2b",
175
+ ks0D6T: "xc0b1yq",
176
176
  kskxy: "x1uh1i8a",
177
177
  "--_dropdown-menu-radius": "x1fcsqxe",
178
178
  "--_dropdown-menu-padding": "xgory14",
@@ -659,16 +659,16 @@ export function DropdownMenuSubMenu(props) {
659
659
  ...menuPress.menuProps,
660
660
  ...mergeProps(themeProps('dropdown-menu'), {
661
661
  0: {
662
- className: "x9f619 x78zum5 xdt5ytf x1lsbc85 x1p5vr2b x1uh1i8a x1fcsqxe xgory14 x9epnlk x1n97fys x1prclbq x1i5ehqx x1hc1fzr x19991ni xuedmi6 xlr8y92 xpdipgo x87ps6o x1j4r261"
662
+ className: "x9f619 x78zum5 xdt5ytf x1lsbc85 xc0b1yq x1uh1i8a x1fcsqxe xgory14 x9epnlk x1n97fys x1prclbq x1i5ehqx x1hc1fzr x19991ni xuedmi6 xlr8y92 xpdipgo x87ps6o x1j4r261"
663
663
  },
664
664
  2: {
665
- className: "x9f619 x78zum5 xdt5ytf x1lsbc85 x1p5vr2b x1uh1i8a x1fcsqxe xgory14 x9epnlk x1n97fys x1prclbq x1i5ehqx x1hc1fzr x19991ni xuedmi6 xlr8y92 xpdipgo x87ps6o xge0x1e xish69e"
665
+ className: "x9f619 x78zum5 xdt5ytf x1lsbc85 xc0b1yq x1uh1i8a x1fcsqxe xgory14 x9epnlk x1n97fys x1prclbq x1i5ehqx x1hc1fzr x19991ni xuedmi6 xlr8y92 xpdipgo x87ps6o xge0x1e xish69e"
666
666
  },
667
667
  1: {
668
- className: "x9f619 x78zum5 xdt5ytf x1lsbc85 x1p5vr2b x1uh1i8a x1fcsqxe xgory14 x9epnlk x1n97fys x1prclbq x1i5ehqx x1hc1fzr x19991ni xuedmi6 xlr8y92 xpdipgo x87ps6o x1j4r261 x1odjw0f x6ikm8r xish69e"
668
+ className: "x9f619 x78zum5 xdt5ytf x1lsbc85 xc0b1yq x1uh1i8a x1fcsqxe xgory14 x9epnlk x1n97fys x1prclbq x1i5ehqx x1hc1fzr x19991ni xuedmi6 xlr8y92 xpdipgo x87ps6o x1j4r261 x1odjw0f x6ikm8r xish69e"
669
669
  },
670
670
  3: {
671
- className: "x9f619 x78zum5 xdt5ytf x1lsbc85 x1p5vr2b x1uh1i8a x1fcsqxe xgory14 x9epnlk x1n97fys x1prclbq x1i5ehqx x1hc1fzr x19991ni xuedmi6 xlr8y92 xpdipgo x87ps6o xge0x1e x1odjw0f x6ikm8r xish69e"
671
+ className: "x9f619 x78zum5 xdt5ytf x1lsbc85 xc0b1yq x1uh1i8a x1fcsqxe xgory14 x9epnlk x1n97fys x1prclbq x1i5ehqx x1hc1fzr x19991ni xuedmi6 xlr8y92 xpdipgo x87ps6o xge0x1e x1odjw0f x6ikm8r xish69e"
672
672
  }
673
673
  }[!!hasOverflow << 1 | !!hasOverflow << 0]),
674
674
  children: nestedContent
@@ -1,7 +1,11 @@
1
1
  /**
2
2
  * The viewport gutter and the caps derived from it. Every value has an
3
- * `env()`-less fallback for engines without safe-area support; pair them with
4
- * `stylex.firstThatWorks(cap, capFallback)`.
3
+ * `env()`-less fallback for engines without safe-area support; pair them as
4
+ * `stylex.firstThatWorks(`calc(${cap})`, `calc(${capFallback})`)`. Pass
5
+ * each inside a `calc()` (or another function), never as a bare reference: a
6
+ * constant reference compiles to a `var()`, and `firstThatWorks` folds two
7
+ * `var()` arguments into one `var(cap, capFallback)` whose constant is never
8
+ * inlined, so every engine would take the fallback.
5
9
  */
6
10
  export declare const layerViewportInset: {
7
11
  /** Gutter from the block-start viewport edge. */
@@ -1 +1 @@
1
- {"version":3,"file":"layerViewportInset.stylex.d.ts","sourceRoot":"","sources":["../../src/Layer/layerViewportInset.stylex.ts"],"names":[],"mappings":"AAwDA;;;;GAIG;AACH,eAAO,MAAM,kBAAkB;IAC7B,iDAAiD;;IAEjD,+CAA+C;;IAE/C,+CAA+C;;IAE/C,gFAAgF;;;;;;IAMhF,iFAAiF;;;IAGjF,gFAAgF;;;CAGhF,CAAC"}
1
+ {"version":3,"file":"layerViewportInset.stylex.d.ts","sourceRoot":"","sources":["../../src/Layer/layerViewportInset.stylex.ts"],"names":[],"mappings":"AAwDA;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB;IAC7B,iDAAiD;;IAEjD,+CAA+C;;IAE/C,+CAA+C;;IAE/C,gFAAgF;;;;;;IAMhF,iFAAiF;;;IAGjF,gFAAgF;;;CAGhF,CAAC"}
@@ -54,8 +54,12 @@ const GUTTER_BLOCK = `calc(max(${SPACING}, env(safe-area-inset-top, 0px), env(sa
54
54
 
55
55
  /**
56
56
  * The viewport gutter and the caps derived from it. Every value has an
57
- * `env()`-less fallback for engines without safe-area support; pair them with
58
- * `stylex.firstThatWorks(cap, capFallback)`.
57
+ * `env()`-less fallback for engines without safe-area support; pair them as
58
+ * `stylex.firstThatWorks(`calc(${cap})`, `calc(${capFallback})`)`. Pass
59
+ * each inside a `calc()` (or another function), never as a bare reference: a
60
+ * constant reference compiles to a `var()`, and `firstThatWorks` folds two
61
+ * `var()` arguments into one `var(cap, capFallback)` whose constant is never
62
+ * inlined, so every engine would take the fallback.
59
63
  */
60
64
  export const layerViewportInset = {
61
65
  gutterBlockStart: "calc(max(var(--spacing-4), env(safe-area-inset-top, 0px)) + var(--astryx-layer-inset-block-start, 0px))",
@@ -1 +1 @@
1
- {"version":3,"file":"useLayer.d.ts","sourceRoot":"","sources":["../../src/Layer/useLayer.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useLayer.d.ts","sourceRoot":"","sources":["../../src/Layer/useLayer.tsx"],"names":[],"mappings":"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"}
@@ -104,24 +104,24 @@ const styles = {
104
104
  },
105
105
  viewportFit: {
106
106
  kB7OPa: "x9f619",
107
- ks0D6T: "x1p5vr2b",
108
- kskxy: "xv8yize",
107
+ ks0D6T: "xc0b1yq",
108
+ kskxy: "x3v4n1",
109
109
  $$css: true
110
110
  },
111
111
  gutterInlineEnd: {
112
- k71WvV: "x1m9hk3x",
112
+ k71WvV: "x144kxal",
113
113
  $$css: true
114
114
  },
115
115
  gutterInlineStart: {
116
- keTefX: "x1ey4id",
116
+ keTefX: "xpdk1p0",
117
117
  $$css: true
118
118
  },
119
119
  gutterBlockEnd: {
120
- k1K539: "x1chv945",
120
+ k1K539: "x3z50q0",
121
121
  $$css: true
122
122
  },
123
123
  gutterBlockStart: {
124
- keoZOQ: "x3390rn",
124
+ keoZOQ: "x1j6tnbc",
125
125
  $$css: true
126
126
  }
127
127
  };
@@ -464,8 +464,14 @@ function useLayerImplementation(options) {
464
464
  // hosted away from its trigger then still takes its sequential focus
465
465
  // order (and its popover nesting) from the trigger rather than from
466
466
  // its own DOM position. Browsers without the option ignore it.
467
+ // `source` is declared as an `HTMLElement`. A caller-rendered icon
468
+ // trigger is an `SVGElement`, whose dictionary conversion throws
469
+ // before the popover opens. Omitting the option for it still anchors
470
+ // the layer, because positioning reads the anchor-name pair, and only
471
+ // gives up the invoker's focus order.
472
+ const trigger = triggerRef.current instanceof HTMLElement ? triggerRef.current : undefined;
467
473
  popover.showPopover({
468
- source: triggerRef.current ?? undefined
474
+ source: trigger
469
475
  });
470
476
  });
471
477
  } else {
@@ -60,8 +60,8 @@ function findTriggerButton(el) {
60
60
  const styles = {
61
61
  surfaceViewportFit: {
62
62
  kB7OPa: "x9f619",
63
- ks0D6T: "x1p5vr2b",
64
- kskxy: "xv8yize",
63
+ ks0D6T: "xc0b1yq",
64
+ kskxy: "x3v4n1",
65
65
  $$css: true
66
66
  },
67
67
  surfaceScrollable: {
package/dist/astryx.css CHANGED
@@ -1115,10 +1115,10 @@
1115
1115
  .xkd40ry:not(#\#):not(#\#):not(#\#){margin-inline-end:calc(-1 * var(--spacing-1))}
1116
1116
  .x3kzqx6:not(#\#):not(#\#):not(#\#){margin-inline-end:calc(-1 * var(--spacing-2))}
1117
1117
  .xmequkd:not(#\#):not(#\#):not(#\#){margin-inline-end:calc(var(--spacing-1) * -1)}
1118
+ .x144kxal:not(#\#):not(#\#):not(#\#){margin-inline-end:calc(calc(var(--spacing-4) + max(var(--astryx-layer-inset-inline-start, 0px), var(--astryx-layer-inset-inline-end, 0px))));margin-inline-end:calc(calc(max(var(--spacing-4), env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px)) + max(var(--astryx-layer-inset-inline-start, 0px), var(--astryx-layer-inset-inline-end, 0px))))}
1118
1119
  .xnur1sd:not(#\#):not(#\#):not(#\#){margin-inline-end:var(--spacing-1)}
1119
1120
  .x1pezmd8:not(#\#):not(#\#):not(#\#){margin-inline-end:var(--spacing-2)}
1120
1121
  .x1c9tiao:not(#\#):not(#\#):not(#\#){margin-inline-end:var(--x-marginInlineEnd)}
1121
- .x1m9hk3x:not(#\#):not(#\#):not(#\#){margin-inline-end:var(--x3pzc91,calc(var(--spacing-4) + max(var(--astryx-layer-inset-inline-start, 0px), var(--astryx-layer-inset-inline-end, 0px))))}
1122
1122
  .xa3ewmy:not(#\#):not(#\#):not(#\#){margin-inline-end:calc(max(var(--spacing-4), env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px)) + max(var(--astryx-layer-inset-inline-start, 0px), var(--astryx-layer-inset-inline-end, 0px)))}
1123
1123
  .x1qfufaz:not(#\#):not(#\#):not(#\#){margin-inline-start:-8px}
1124
1124
  .x1lziwak:not(#\#):not(#\#):not(#\#){margin-inline-start:0}
@@ -1134,6 +1134,7 @@
1134
1134
  .x1idpjx9:not(#\#):not(#\#):not(#\#){margin-inline-start:calc((40px - min(var(--spacing-6),40px)) / 2 - var(--spacing-4))}
1135
1135
  .x1xrm450:not(#\#):not(#\#):not(#\#){margin-inline-start:calc(var(--spacing-2) - var(--spacing-1) + 1px)}
1136
1136
  .x6w1cxl:not(#\#):not(#\#):not(#\#){margin-inline-start:calc(var(--spacing-3) + var(--border-width) + var(--spacing-4))}
1137
+ .xpdk1p0:not(#\#):not(#\#):not(#\#){margin-inline-start:calc(calc(var(--spacing-4) + max(var(--astryx-layer-inset-inline-start, 0px), var(--astryx-layer-inset-inline-end, 0px))));margin-inline-start:calc(calc(max(var(--spacing-4), env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px)) + max(var(--astryx-layer-inset-inline-start, 0px), var(--astryx-layer-inset-inline-end, 0px))))}
1137
1138
  .x13hpdyo:not(#\#):not(#\#):not(#\#){margin-inline-start:var(--_avatar-group-overlap)}
1138
1139
  .x12vn87o:not(#\#):not(#\#):not(#\#){margin-inline-start:var(--_tree-indent,0px)}
1139
1140
  .xladpz9:not(#\#):not(#\#):not(#\#){margin-inline-start:var(--spacing-0-5)}
@@ -1142,7 +1143,6 @@
1142
1143
  .x6i7dpz:not(#\#):not(#\#):not(#\#){margin-inline-start:var(--spacing-3)}
1143
1144
  .x1l10yog:not(#\#):not(#\#):not(#\#){margin-inline-start:var(--spacing-6)}
1144
1145
  .x4lel18:not(#\#):not(#\#):not(#\#){margin-inline-start:var(--x-marginInlineStart)}
1145
- .x1ey4id:not(#\#):not(#\#):not(#\#){margin-inline-start:var(--x3pzc91,calc(var(--spacing-4) + max(var(--astryx-layer-inset-inline-start, 0px), var(--astryx-layer-inset-inline-end, 0px))))}
1146
1146
  .x1cytvie:not(#\#):not(#\#):not(#\#){margin-inline-start:calc(max(var(--spacing-4), env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px)) + max(var(--astryx-layer-inset-inline-start, 0px), var(--astryx-layer-inset-inline-end, 0px)))}
1147
1147
  .xkm2don:not(#\#):not(#\#):not(#\#){mask-image:linear-gradient(to bottom,transparent,black 24px)}
1148
1148
  .xw26lqc:not(#\#):not(#\#):not(#\#){mask-image:linear-gradient(to bottom,transparent,black 36px)}
@@ -1757,6 +1757,7 @@
1757
1757
  .x6h7pi7:not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:calc(-1 * var(--container-padding-block-end,0px))}
1758
1758
  .x1cdrix3:not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:calc(-1 * var(--radius-chat))}
1759
1759
  .xdrfirk:not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:calc(-1 * var(--spacing-1-5))}
1760
+ .x3z50q0:not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:calc(calc(var(--spacing-4) + max(var(--astryx-layer-inset-block-start, 0px), var(--astryx-layer-inset-block-end, 0px))));margin-bottom:calc(calc(max(var(--spacing-4), env(safe-area-inset-top, 0px), env(safe-area-inset-bottom, 0px)) + max(var(--astryx-layer-inset-block-start, 0px), var(--astryx-layer-inset-block-end, 0px))))}
1760
1761
  .xlstkdb:not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:var(--spacing-0-5)}
1761
1762
  .x14cgwvg:not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:var(--spacing-1)}
1762
1763
  .x1p37lm5:not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:var(--spacing-2)}
@@ -1764,7 +1765,6 @@
1764
1765
  .xwh1t77:not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:var(--spacing-4)}
1765
1766
  .x4d5cxa:not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:var(--spacing-6)}
1766
1767
  .xlm3tn6:not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:var(--x-marginBlockEnd)}
1767
- .x1chv945:not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:var(--x1ot8se4,calc(var(--spacing-4) + max(var(--astryx-layer-inset-block-start, 0px), var(--astryx-layer-inset-block-end, 0px))))}
1768
1768
  .x119uzjn:not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:calc(max(var(--spacing-4), env(safe-area-inset-top, 0px), env(safe-area-inset-bottom, 0px)) + max(var(--astryx-layer-inset-block-start, 0px), var(--astryx-layer-inset-block-end, 0px)))}
1769
1769
  .xdj266r:not(#\#):not(#\#):not(#\#):not(#\#){margin-top:0}
1770
1770
  .xr1yuqi:not(#\#):not(#\#):not(#\#):not(#\#){margin-top:auto}
@@ -1778,6 +1778,7 @@
1778
1778
  .x1ajqlyv:not(#\#):not(#\#):not(#\#):not(#\#){margin-top:calc(-1 * var(--spacing-2))}
1779
1779
  .x1oms9s6:not(#\#):not(#\#):not(#\#):not(#\#){margin-top:calc((1em * var(--text-body-leading) - 20px) / 2)}
1780
1780
  .x1233pnv:not(#\#):not(#\#):not(#\#):not(#\#){margin-top:calc((1em * var(--text-body-leading) - 6px) / 2)}
1781
+ .x1j6tnbc:not(#\#):not(#\#):not(#\#):not(#\#){margin-top:calc(calc(var(--spacing-4) + max(var(--astryx-layer-inset-block-start, 0px), var(--astryx-layer-inset-block-end, 0px))));margin-top:calc(calc(max(var(--spacing-4), env(safe-area-inset-top, 0px), env(safe-area-inset-bottom, 0px)) + max(var(--astryx-layer-inset-block-start, 0px), var(--astryx-layer-inset-block-end, 0px))))}
1781
1782
  .xjc2qm6:not(#\#):not(#\#):not(#\#):not(#\#){margin-top:var(--spacing-0-5)}
1782
1783
  .xcsaf9d:not(#\#):not(#\#):not(#\#):not(#\#){margin-top:var(--spacing-1)}
1783
1784
  .xtbrsbv:not(#\#):not(#\#):not(#\#):not(#\#){margin-top:var(--spacing-2)}
@@ -1785,7 +1786,6 @@
1785
1786
  .x1s1qpeq:not(#\#):not(#\#):not(#\#):not(#\#){margin-top:var(--spacing-4)}
1786
1787
  .x13rv44w:not(#\#):not(#\#):not(#\#):not(#\#){margin-top:var(--spacing-6)}
1787
1788
  .x1vhfslr:not(#\#):not(#\#):not(#\#):not(#\#){margin-top:var(--x-marginBlockStart)}
1788
- .x3390rn:not(#\#):not(#\#):not(#\#):not(#\#){margin-top:var(--x1ot8se4,calc(var(--spacing-4) + max(var(--astryx-layer-inset-block-start, 0px), var(--astryx-layer-inset-block-end, 0px))))}
1789
1789
  .x1lhixnp:not(#\#):not(#\#):not(#\#):not(#\#){margin-top:calc(max(var(--spacing-4), env(safe-area-inset-top, 0px), env(safe-area-inset-bottom, 0px)) + max(var(--astryx-layer-inset-block-start, 0px), var(--astryx-layer-inset-block-end, 0px)))}
1790
1790
  .xmz0i5r:not(#\#):not(#\#):not(#\#):not(#\#){max-height:100%}
1791
1791
  .x1wj9ous:not(#\#):not(#\#):not(#\#):not(#\#){max-height:100dvh}
@@ -1794,13 +1794,13 @@
1794
1794
  .xuyqlj2:not(#\#):not(#\#):not(#\#):not(#\#){max-height:300px}
1795
1795
  .xbhvqqn:not(#\#):not(#\#):not(#\#):not(#\#){max-height:calc(100% - var(--spacing-3))}
1796
1796
  .x14bu9tk:not(#\#):not(#\#):not(#\#):not(#\#){max-height:calc(92dvh + 48px)}
1797
+ .x3v4n1:not(#\#):not(#\#):not(#\#):not(#\#){max-height:calc(calc(100vh - var(--spacing-4) - var(--spacing-4) - var(--astryx-layer-inset-block-start, 0px) - var(--astryx-layer-inset-block-end, 0px)));max-height:calc(calc(100dvb - calc(max(var(--spacing-4), env(safe-area-inset-top, 0px)) + var(--astryx-layer-inset-block-start, 0px)) - calc(max(var(--spacing-4), env(safe-area-inset-bottom, 0px)) + var(--astryx-layer-inset-block-end, 0px))))}
1797
1798
  .x1uh1i8a:not(#\#):not(#\#):not(#\#):not(#\#){max-height:min(300px,calc(100vh - var(--spacing-4) - var(--spacing-4) - var(--astryx-layer-inset-block-start, 0px) - var(--astryx-layer-inset-block-end, 0px)));max-height:min(300px,calc(100dvb - calc(max(var(--spacing-4), env(safe-area-inset-top, 0px)) + var(--astryx-layer-inset-block-start, 0px)) - calc(max(var(--spacing-4), env(safe-area-inset-bottom, 0px)) + var(--astryx-layer-inset-block-end, 0px))))}
1798
1799
  .xpnbb6b:not(#\#):not(#\#):not(#\#):not(#\#){max-height:min(480px,calc(100vh - 32px))}
1799
1800
  .x7ab17h:not(#\#):not(#\#):not(#\#):not(#\#){max-height:none}
1800
1801
  .xenllk4:not(#\#):not(#\#):not(#\#):not(#\#){max-height:var(--container-max-height,none)}
1801
1802
  .xbmfmqd:not(#\#):not(#\#):not(#\#):not(#\#){max-height:var(--x-maxBlockSize)}
1802
1803
  .x1jols5v:not(#\#):not(#\#):not(#\#):not(#\#){max-height:var(--x-maxHeight)}
1803
- .xv8yize:not(#\#):not(#\#):not(#\#):not(#\#){max-height:var(--x17ekfff,calc(100vh - var(--spacing-4) - var(--spacing-4) - var(--astryx-layer-inset-block-start, 0px) - var(--astryx-layer-inset-block-end, 0px)))}
1804
1804
  .x1m189uc:not(#\#):not(#\#):not(#\#):not(#\#){max-width:0}
1805
1805
  .x193iq5w:not(#\#):not(#\#):not(#\#):not(#\#){max-width:100%}
1806
1806
  .xlbgzzq:not(#\#):not(#\#):not(#\#):not(#\#){max-width:100dvw}
@@ -1815,13 +1815,13 @@
1815
1815
  .x1ap80js:not(#\#):not(#\#):not(#\#):not(#\#){max-width:800px}
1816
1816
  .xq8v1hd:not(#\#):not(#\#):not(#\#):not(#\#){max-width:90%}
1817
1817
  .x1rfgw7b:not(#\#):not(#\#):not(#\#):not(#\#){max-width:calc(100% + var(--container-padding-inline-start,0px) + var(--container-padding-inline-end,0px))}
1818
+ .xc0b1yq:not(#\#):not(#\#):not(#\#):not(#\#){max-width:calc(calc(100vw - var(--spacing-4) - var(--spacing-4) - var(--astryx-layer-inset-inline-start, 0px) - var(--astryx-layer-inset-inline-end, 0px)));max-width:calc(calc(100vi - calc(max(var(--spacing-4), env(safe-area-inset-left, 0px)) + var(--astryx-layer-inset-inline-start, 0px)) - calc(max(var(--spacing-4), env(safe-area-inset-right, 0px)) + var(--astryx-layer-inset-inline-end, 0px))))}
1818
1819
  .xl6temz:not(#\#):not(#\#):not(#\#):not(#\#){max-width:max(80%,280px)}
1819
1820
  .x1m1aaou:not(#\#):not(#\#):not(#\#):not(#\#){max-width:min(960px,calc(100dvw - var(--spacing-4)))}
1820
1821
  .x1x1rfll:not(#\#):not(#\#):not(#\#):not(#\#){max-width:none}
1821
1822
  .xjl2t3p:not(#\#):not(#\#):not(#\#):not(#\#){max-width:var(--layout-content-width,none)}
1822
1823
  .x1jys5uj:not(#\#):not(#\#):not(#\#):not(#\#){max-width:var(--size-element-md)}
1823
1824
  .xf68679:not(#\#):not(#\#):not(#\#):not(#\#){max-width:var(--x-maxWidth)}
1824
- .x1p5vr2b:not(#\#):not(#\#):not(#\#):not(#\#){max-width:var(--xdig2zt,calc(100vw - var(--spacing-4) - var(--spacing-4) - var(--astryx-layer-inset-inline-start, 0px) - var(--astryx-layer-inset-inline-end, 0px)))}
1825
1825
  .x2lwn1j:not(#\#):not(#\#):not(#\#):not(#\#){min-height:0}
1826
1826
  .x1us19tq:not(#\#):not(#\#):not(#\#):not(#\#){min-height:100%}
1827
1827
  .x1ov3xa9:not(#\#):not(#\#):not(#\#):not(#\#){min-height:100dvh}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astryxdesign/core",
3
- "version": "0.7.2-canary.3aca324",
3
+ "version": "0.7.2-canary.3f45fc2",
4
4
  "displayName": "Astryx Core",
5
5
  "description": "The component library. Accessible, themeable React components with built-in spacing, dark mode, and StyleX styling.",
6
6
  "author": "Meta Open Source",
@@ -787,8 +787,8 @@
787
787
  "react-dom": ">=19.0.0"
788
788
  },
789
789
  "devDependencies": {
790
- "@astryxdesign/a11y-spec": "0.7.2-canary.3aca324",
791
- "@astryxdesign/cli": "0.7.2-canary.3aca324",
790
+ "@astryxdesign/a11y-spec": "0.7.2-canary.3f45fc2",
791
+ "@astryxdesign/cli": "0.7.2-canary.3f45fc2",
792
792
  "@babel/cli": "^7.29.7",
793
793
  "@babel/core": "^7.29.7",
794
794
  "@babel/preset-react": "^7.29.7",
@@ -229,8 +229,8 @@ const styles = stylex.create({
229
229
  WebkitTouchCallout: 'none',
230
230
  userSelect: 'none',
231
231
  maxInlineSize: stylex.firstThatWorks(
232
- layerViewportInset.maxInlineSize,
233
- layerViewportInset.maxInlineSizeFallback,
232
+ `calc(${layerViewportInset.maxInlineSize})`,
233
+ `calc(${layerViewportInset.maxInlineSizeFallback})`,
234
234
  ),
235
235
  maxHeight: stylex.firstThatWorks(
236
236
  MENU_MAX_BLOCK_SIZE,
@@ -166,8 +166,8 @@ const flyoutStyles = stylex.create({
166
166
  flexDirection: 'column',
167
167
  gap: spacingVars['--spacing-0-5'],
168
168
  maxInlineSize: stylex.firstThatWorks(
169
- layerViewportInset.maxInlineSize,
170
- layerViewportInset.maxInlineSizeFallback,
169
+ `calc(${layerViewportInset.maxInlineSize})`,
170
+ `calc(${layerViewportInset.maxInlineSizeFallback})`,
171
171
  ),
172
172
  maxHeight: stylex.firstThatWorks(
173
173
  MENU_MAX_BLOCK_SIZE,
@@ -0,0 +1,90 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file layerViewportInset.source-build.test.mjs
5
+ * @input Uses Babel, the core StyleX build config, the StyleX rule processor,
6
+ * and the sources that cap or inset anchored layers
7
+ * @output Verifies the shipped stylesheet carries the dynamic-viewport,
8
+ * safe-area gutter and caps (spec:AST-059 FR1–FR3), not only the fallbacks
9
+ * @position Regression test for the compiled layer viewport inset
10
+ *
11
+ * `stylex.firstThatWorks(a, b)` turns two `var()` arguments into one nested
12
+ * `var(a, b)`. A `defineConsts` reference compiles to such a `var()`, and the
13
+ * rule processor inlines a constant only where its `var()` stands alone, so a
14
+ * pair of bare constant references shipped as `var(--<hash>, <fallback>)`
15
+ * with `--<hash>` defined nowhere: every engine took the fallback.
16
+ */
17
+
18
+ import fs from 'node:fs/promises';
19
+ import path from 'node:path';
20
+ import {fileURLToPath} from 'node:url';
21
+ import {transformAsync} from '@babel/core';
22
+ import stylexBabelPlugin from '@stylexjs/babel-plugin';
23
+ import {describe, expect, it} from 'vitest';
24
+
25
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
26
+ const SRC = path.resolve(__dirname, '..');
27
+ const CORE_ROOT = path.resolve(SRC, '..');
28
+
29
+ const SOURCES = [
30
+ 'Layer/layerViewportInset.stylex.ts',
31
+ 'Layer/useLayer.tsx',
32
+ 'Popover/Popover.tsx',
33
+ 'DropdownMenu/DropdownMenu.tsx',
34
+ 'DropdownMenu/DropdownMenuSubMenu.tsx',
35
+ ];
36
+
37
+ async function compileStylesheet() {
38
+ const rules = [];
39
+ for (const relative of SOURCES) {
40
+ const filename = path.join(SRC, relative);
41
+ const result = await transformAsync(await fs.readFile(filename, 'utf8'), {
42
+ babelrc: false,
43
+ configFile: path.join(CORE_ROOT, 'babel.config.json'),
44
+ filename,
45
+ });
46
+ rules.push(...(result?.metadata?.stylex ?? []));
47
+ }
48
+ return stylexBabelPlugin.processStylexRules(rules, false);
49
+ }
50
+
51
+ /** Every declaration of `property` in the compiled sheet. */
52
+ function declarations(css, property) {
53
+ return [...css.matchAll(new RegExp(`[{;]${property}:([^;}]+)`, 'g'))].map(
54
+ match => match[1],
55
+ );
56
+ }
57
+
58
+ describe('layer viewport inset stylesheet (spec:AST-059)', () => {
59
+ it('leaves no constant reference unresolved behind a fallback', async () => {
60
+ const css = await compileStylesheet();
61
+ const defined = new Set(
62
+ [...css.matchAll(/(--[\w-]+)\s*:/g)].map(match => match[1]),
63
+ );
64
+ const undefinedReferences = [
65
+ ...css.matchAll(/var\((--x[a-z0-9]+),/g),
66
+ ].flatMap(match => (defined.has(match[1]) ? [] : [match[0]]));
67
+ // Covers the caps and the four alignment-axis gutter margins.
68
+ expect(undefinedReferences).toEqual([]);
69
+ });
70
+
71
+ it('caps both axes against the dynamic viewport and the safe-area gutters', async () => {
72
+ const css = await compileStylesheet();
73
+ const blockCaps = declarations(css, 'max-height');
74
+ const inlineCaps = declarations(css, 'max-width');
75
+
76
+ expect(blockCaps).toContainEqual(
77
+ expect.stringMatching(/^calc\(calc\(100dvb - .*safe-area-inset-top/),
78
+ );
79
+ expect(inlineCaps).toContainEqual(
80
+ expect.stringMatching(/^calc\(calc\(100vi - .*safe-area-inset-left/),
81
+ );
82
+ // The older-engine fallbacks still ship, ahead of the preferred value.
83
+ expect(blockCaps).toContainEqual(
84
+ expect.stringMatching(/^calc\(calc\(100vh - /),
85
+ );
86
+ expect(inlineCaps).toContainEqual(
87
+ expect.stringMatching(/^calc\(calc\(100vw - /),
88
+ );
89
+ });
90
+ });
@@ -56,8 +56,12 @@ const GUTTER_BLOCK = `calc(max(${SPACING}, env(safe-area-inset-top, 0px), env(sa
56
56
 
57
57
  /**
58
58
  * The viewport gutter and the caps derived from it. Every value has an
59
- * `env()`-less fallback for engines without safe-area support; pair them with
60
- * `stylex.firstThatWorks(cap, capFallback)`.
59
+ * `env()`-less fallback for engines without safe-area support; pair them as
60
+ * `stylex.firstThatWorks(`calc(${cap})`, `calc(${capFallback})`)`. Pass
61
+ * each inside a `calc()` (or another function), never as a bare reference: a
62
+ * constant reference compiles to a `var()`, and `firstThatWorks` folds two
63
+ * `var()` arguments into one `var(cap, capFallback)` whose constant is never
64
+ * inlined, so every engine would take the fallback.
61
65
  */
62
66
  export const layerViewportInset = stylex.defineConsts({
63
67
  /** Gutter from the block-start viewport edge. */
@@ -102,15 +102,17 @@ const styles = stylex.create({
102
102
  // The cap is on the layer box itself: content wider than the viewport
103
103
  // overflows inside the layer, where the composing component decides
104
104
  // whether it scrolls or clips; the box never leaves the viewport.
105
+ // Each constant is wrapped in `calc()` so both declarations ship (see
106
+ // layerViewportInset).
105
107
  viewportFit: {
106
108
  boxSizing: 'border-box',
107
109
  maxInlineSize: stylex.firstThatWorks(
108
- layerViewportInset.maxInlineSize,
109
- layerViewportInset.maxInlineSizeFallback,
110
+ `calc(${layerViewportInset.maxInlineSize})`,
111
+ `calc(${layerViewportInset.maxInlineSizeFallback})`,
110
112
  ),
111
113
  maxBlockSize: stylex.firstThatWorks(
112
- layerViewportInset.maxBlockSize,
113
- layerViewportInset.maxBlockSizeFallback,
114
+ `calc(${layerViewportInset.maxBlockSize})`,
115
+ `calc(${layerViewportInset.maxBlockSizeFallback})`,
114
116
  ),
115
117
  },
116
118
  // Alignment-axis gutter (spec:AST-059 FR1): a margin on the far viewport
@@ -120,26 +122,26 @@ const styles = stylex.create({
120
122
  // (see layerSlideRules.ts).
121
123
  gutterInlineEnd: {
122
124
  marginInlineEnd: stylex.firstThatWorks(
123
- layerViewportInset.gutterInline,
124
- layerViewportInset.gutterInlineFallback,
125
+ `calc(${layerViewportInset.gutterInline})`,
126
+ `calc(${layerViewportInset.gutterInlineFallback})`,
125
127
  ),
126
128
  },
127
129
  gutterInlineStart: {
128
130
  marginInlineStart: stylex.firstThatWorks(
129
- layerViewportInset.gutterInline,
130
- layerViewportInset.gutterInlineFallback,
131
+ `calc(${layerViewportInset.gutterInline})`,
132
+ `calc(${layerViewportInset.gutterInlineFallback})`,
131
133
  ),
132
134
  },
133
135
  gutterBlockEnd: {
134
136
  marginBlockEnd: stylex.firstThatWorks(
135
- layerViewportInset.gutterBlock,
136
- layerViewportInset.gutterBlockFallback,
137
+ `calc(${layerViewportInset.gutterBlock})`,
138
+ `calc(${layerViewportInset.gutterBlockFallback})`,
137
139
  ),
138
140
  },
139
141
  gutterBlockStart: {
140
142
  marginBlockStart: stylex.firstThatWorks(
141
- layerViewportInset.gutterBlock,
142
- layerViewportInset.gutterBlockFallback,
143
+ `calc(${layerViewportInset.gutterBlock})`,
144
+ `calc(${layerViewportInset.gutterBlockFallback})`,
143
145
  ),
144
146
  },
145
147
  });
@@ -760,7 +762,16 @@ function useLayerImplementation(
760
762
  // hosted away from its trigger then still takes its sequential focus
761
763
  // order (and its popover nesting) from the trigger rather than from
762
764
  // its own DOM position. Browsers without the option ignore it.
763
- popover.showPopover({source: triggerRef.current ?? undefined});
765
+ // `source` is declared as an `HTMLElement`. A caller-rendered icon
766
+ // trigger is an `SVGElement`, whose dictionary conversion throws
767
+ // before the popover opens. Omitting the option for it still anchors
768
+ // the layer, because positioning reads the anchor-name pair, and only
769
+ // gives up the invoker's focus order.
770
+ const trigger =
771
+ triggerRef.current instanceof HTMLElement
772
+ ? triggerRef.current
773
+ : undefined;
774
+ popover.showPopover({source: trigger});
764
775
  });
765
776
  } else {
766
777
  popover.style.display = 'block';
@@ -280,10 +280,10 @@ describe('Popover', () => {
280
280
  'utf8',
281
281
  );
282
282
  expect(popoverSource).toMatch(
283
- /surfaceViewportFit:[\s\S]*?maxInlineSize: stylex\.firstThatWorks\(\s*layerViewportInset\.maxInlineSize/,
283
+ /surfaceViewportFit:[\s\S]*?maxInlineSize: stylex\.firstThatWorks\(\s*`calc\(\$\{layerViewportInset\.maxInlineSize\}\)`/,
284
284
  );
285
285
  expect(popoverSource).toMatch(
286
- /surfaceViewportFit:[\s\S]*?maxBlockSize: stylex\.firstThatWorks\(\s*layerViewportInset\.maxBlockSize/,
286
+ /surfaceViewportFit:[\s\S]*?maxBlockSize: stylex\.firstThatWorks\(\s*`calc\(\$\{layerViewportInset\.maxBlockSize\}\)`/,
287
287
  );
288
288
  expect(popoverSource).not.toMatch(/safe-area-inset|calc\(100%/);
289
289
  expect(surface?.className).not.toContain(
@@ -272,12 +272,12 @@ const styles = stylex.create({
272
272
  surfaceViewportFit: {
273
273
  boxSizing: 'border-box',
274
274
  maxInlineSize: stylex.firstThatWorks(
275
- layerViewportInset.maxInlineSize,
276
- layerViewportInset.maxInlineSizeFallback,
275
+ `calc(${layerViewportInset.maxInlineSize})`,
276
+ `calc(${layerViewportInset.maxInlineSizeFallback})`,
277
277
  ),
278
278
  maxBlockSize: stylex.firstThatWorks(
279
- layerViewportInset.maxBlockSize,
280
- layerViewportInset.maxBlockSizeFallback,
279
+ `calc(${layerViewportInset.maxBlockSize})`,
280
+ `calc(${layerViewportInset.maxBlockSizeFallback})`,
281
281
  ),
282
282
  },
283
283
  surfaceScrollable: {
@@ -183,6 +183,37 @@ describe('Tooltip', () => {
183
183
  });
184
184
  });
185
185
 
186
+ describe('icon-only trigger', () => {
187
+ // A rendered icon is an SVGElement, and ShowPopoverOptions.source is
188
+ // declared as an HTMLElement. Handing the icon to showPopover throws
189
+ // during dictionary conversion, before the popover opens, so the hint
190
+ // never appeared. (#7226)
191
+ it('opens an icon trigger without passing an SVGElement as the source', async () => {
192
+ const showSpy = vi.mocked(HTMLElement.prototype.showPopover);
193
+ showSpy.mockClear();
194
+
195
+ render(
196
+ <Tooltip content="Shared memory" isDefaultOpen>
197
+ <svg data-testid="icon" aria-hidden="true" />
198
+ </Tooltip>,
199
+ );
200
+
201
+ await waitFor(() => {
202
+ expect(showSpy).toHaveBeenCalled();
203
+ });
204
+
205
+ const [options] = showSpy.mock.calls[0];
206
+ // Compared as a boolean on purpose: a plain `toBeUndefined` failure makes
207
+ // the diff printer walk the SVGElement, which it cannot inspect.
208
+ expect(options?.source === undefined).toBe(true);
209
+
210
+ // The icon is still the trigger the ARIA tooltip pattern is wired to.
211
+ expect(screen.getByTestId('icon').getAttribute('aria-describedby')).toBe(
212
+ screen.getByRole('tooltip', {hidden: true}).id,
213
+ );
214
+ });
215
+ });
216
+
186
217
  describe('WCAG 1.4.13 — content on hover or focus', () => {
187
218
  it('dismisses on Escape while visible (dismissible)', async () => {
188
219
  const onOpenChange = vi.fn();