@oxyhq/bloom 0.35.6 → 0.35.7
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/lib/commonjs/content-panel/index.js +22 -6
- package/lib/commonjs/content-panel/index.js.map +1 -1
- package/lib/commonjs/content-panel/index.web.js +37 -12
- package/lib/commonjs/content-panel/index.web.js.map +1 -1
- package/lib/module/content-panel/index.js +22 -6
- package/lib/module/content-panel/index.js.map +1 -1
- package/lib/module/content-panel/index.web.js +37 -12
- package/lib/module/content-panel/index.web.js.map +1 -1
- package/lib/typescript/commonjs/content-panel/index.d.ts +21 -8
- package/lib/typescript/commonjs/content-panel/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/content-panel/index.web.d.ts +26 -6
- package/lib/typescript/commonjs/content-panel/index.web.d.ts.map +1 -1
- package/lib/typescript/module/content-panel/index.d.ts +21 -8
- package/lib/typescript/module/content-panel/index.d.ts.map +1 -1
- package/lib/typescript/module/content-panel/index.web.d.ts +26 -6
- package/lib/typescript/module/content-panel/index.web.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/content-panel/index.tsx +33 -14
- package/src/content-panel/index.web.tsx +62 -22
|
@@ -18,11 +18,20 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
|
|
|
18
18
|
* the rounded corners / lateral gutters is masked while a single seamless border
|
|
19
19
|
* is drawn around the panel — see `index.web.tsx`.
|
|
20
20
|
*
|
|
21
|
-
* On NATIVE none of
|
|
22
|
-
* positioning, and no bleed to mask, so the panel is simply a
|
|
23
|
-
* surface wrapping its content. The `framed`
|
|
24
|
-
*
|
|
25
|
-
* (
|
|
21
|
+
* On NATIVE none of the WEB overlay machinery applies: there is no document
|
|
22
|
+
* scroll, no sticky positioning, and no bleed to mask, so the panel is simply a
|
|
23
|
+
* surface wrapping its content. The `framed` prop still drives whether that
|
|
24
|
+
* surface is rounded + bordered, tri-state and resolved with pure NativeWind
|
|
25
|
+
* (`md:` evaluates against the window width on native too — no JS breakpoint
|
|
26
|
+
* hook needed):
|
|
27
|
+
*
|
|
28
|
+
* - `undefined` (DEFAULT) → responsive: full-bleed below `md`, rounded +
|
|
29
|
+
* bordered at `md`+ (`md:rounded-radius-28 md:border md:border-border`).
|
|
30
|
+
* - `false` → never framed (plain full-bleed at every size).
|
|
31
|
+
* - `true` → always rounded + bordered.
|
|
32
|
+
*
|
|
33
|
+
* `showStickyFrame` and `maskColor` are accepted for cross-platform API parity
|
|
34
|
+
* but are no-ops here (there are no sticky overlays on native).
|
|
26
35
|
*
|
|
27
36
|
* Web bundlers select `./index.web` via the `"browser"` export condition in
|
|
28
37
|
* `package.json`; native bundlers fall through to this file.
|
|
@@ -43,6 +52,7 @@ const PANEL_TOP_INSET = exports.PANEL_TOP_INSET = 8;
|
|
|
43
52
|
const PANEL_BOTTOM_INSET = exports.PANEL_BOTTOM_INSET = 8;
|
|
44
53
|
const ContentPanelComponent = ({
|
|
45
54
|
children,
|
|
55
|
+
framed,
|
|
46
56
|
surfaceClassName,
|
|
47
57
|
surfaceStyle,
|
|
48
58
|
contentClassName,
|
|
@@ -50,7 +60,13 @@ const ContentPanelComponent = ({
|
|
|
50
60
|
}) => {
|
|
51
61
|
// Dev-only invariant — a ContentPanel must never be nested inside another.
|
|
52
62
|
(0, _nestingContext.useContentPanelNestingGuard)();
|
|
53
|
-
|
|
63
|
+
|
|
64
|
+
// Tri-state: `undefined` → responsive (md:-gated), `true` → always framed,
|
|
65
|
+
// `false` → never framed (plain full-bleed). Whole literal class strings are
|
|
66
|
+
// selected per mode so the Tailwind content-scan over `src/**` picks up every
|
|
67
|
+
// `md:` / `rounded-radius-28` token verbatim (no dynamic concatenation).
|
|
68
|
+
const surfaceBase = framed === undefined ? 'flex-1 md:overflow-hidden md:rounded-radius-28 md:border md:border-border' : framed ? 'flex-1 overflow-hidden rounded-radius-28 border border-border' : 'flex-1';
|
|
69
|
+
const surfaceClass = [surfaceBase, surfaceClassName ?? 'bg-card'].join(' ');
|
|
54
70
|
const contentClass = ['flex-1', contentClassName].filter(Boolean).join(' ');
|
|
55
71
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_nestingContext.ContentPanelNestingContext.Provider, {
|
|
56
72
|
value: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_nestingContext","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","GUTTER_MASK_SPREAD","exports","PANEL_TOP_INSET","PANEL_BOTTOM_INSET","ContentPanelComponent","children","surfaceClassName","surfaceStyle","contentClassName","contentStyle","useContentPanelNestingGuard","surfaceClass","join","contentClass","filter","Boolean","jsx","ContentPanelNestingContext","Provider","value","View","className","style","ContentPanel","memo","displayName"],"sourceRoot":"../../../src","sources":["content-panel/index.tsx"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_nestingContext","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","GUTTER_MASK_SPREAD","exports","PANEL_TOP_INSET","PANEL_BOTTOM_INSET","ContentPanelComponent","children","framed","surfaceClassName","surfaceStyle","contentClassName","contentStyle","useContentPanelNestingGuard","surfaceBase","undefined","surfaceClass","join","contentClass","filter","Boolean","jsx","ContentPanelNestingContext","Provider","value","View","className","style","ContentPanel","memo","displayName"],"sourceRoot":"../../../src","sources":["content-panel/index.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -35,16 +35,29 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
|
|
|
35
35
|
* content rather than displacing it). They render BEFORE the content wrapper so
|
|
36
36
|
* z-index — not DOM order — decides layering.
|
|
37
37
|
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
38
|
+
* Framing is tri-state via the `framed` prop:
|
|
39
|
+
*
|
|
40
|
+
* - `undefined` (DEFAULT) → RESPONSIVE, driven purely by NativeWind: full-bleed
|
|
41
|
+
* below `md`, framed at `md`+. The rounding is `md:`-gated and both overlays
|
|
42
|
+
* are always rendered but carry `max-md:hidden` (`display:none` below `md`),
|
|
43
|
+
* so the breakpoint is decided in CSS — no consumer JS breakpoint hook.
|
|
44
|
+
* - `false` → NEVER framed (full-bleed at every size): a single flat surface,
|
|
45
|
+
* no rounding, no overlays.
|
|
46
|
+
* - `true` → ALWAYS framed (rounded + overlays at every size).
|
|
47
|
+
*
|
|
48
|
+
* The overlays are gated by VISIBILITY (a `max-md:hidden` literal) rather than
|
|
49
|
+
* by conditional mounting for the responsive case, so crossing the breakpoint
|
|
50
|
+
* never remounts them. The content wrapper likewise keeps a stable `key` so
|
|
51
|
+
* `{children}` reconciles in place across the breakpoint instead of remounting
|
|
52
|
+
* (which would reset feed scroll / the virtualizer + refetch).
|
|
40
53
|
*
|
|
41
54
|
* Native bundlers use `./index.tsx` (a plain rounded surface); web bundlers
|
|
42
55
|
* select this file via the `"browser"` export condition in `package.json`.
|
|
43
56
|
*
|
|
44
57
|
* Styling is NativeWind-className-first; the literal class strings below MUST
|
|
45
58
|
* stay literal so a consumer's Tailwind content-scan over `lib/**` picks them up
|
|
46
|
-
* (no dynamic concatenation of the arbitrary `web:[…]` / `rounded-radius-28`
|
|
47
|
-
* parts).
|
|
59
|
+
* (no dynamic concatenation of the arbitrary `web:[…]` / `rounded-radius-28` /
|
|
60
|
+
* `md:` parts — whole class strings are selected per mode instead).
|
|
48
61
|
*/
|
|
49
62
|
|
|
50
63
|
/** Width (in px) of the sticky gutter-mask box-shadow ring. */
|
|
@@ -63,28 +76,40 @@ const ContentPanelComponent = ({
|
|
|
63
76
|
showStickyFrame,
|
|
64
77
|
maskColor
|
|
65
78
|
}) => {
|
|
66
|
-
// Dev-only invariant — must run unconditionally before
|
|
67
|
-
//
|
|
79
|
+
// Dev-only invariant — must run unconditionally (before deriving any
|
|
80
|
+
// mode-specific branch) so the hook order stays stable (rules of hooks).
|
|
68
81
|
(0, _nestingContext.useContentPanelNestingGuard)();
|
|
69
82
|
const {
|
|
70
83
|
colors
|
|
71
84
|
} = (0, _useTheme.useTheme)();
|
|
72
|
-
|
|
73
|
-
|
|
85
|
+
|
|
86
|
+
// Tri-state: `undefined` → responsive (md:-gated), `true` → always framed,
|
|
87
|
+
// `false` → never framed (full-bleed).
|
|
88
|
+
const responsive = framed === undefined;
|
|
89
|
+
const showOverlays = framed !== false;
|
|
90
|
+
|
|
91
|
+
// Whole literal class strings selected per mode (the Tailwind content-scan
|
|
92
|
+
// over `lib/**` requires each arbitrary/`md:`/`web:` token stay literal).
|
|
93
|
+
// `web:md:overflow-x-clip` is platform-first-then-breakpoint, matching the
|
|
94
|
+
// consumer convention (`web:sm:flex` in `@mercaria/ui`).
|
|
95
|
+
const surfaceBase = responsive ? 'flex-1 md:rounded-radius-28' : framed ? 'flex-1 rounded-radius-28' : 'flex-1';
|
|
96
|
+
const contentBase = responsive ? 'flex-1 md:rounded-radius-28 web:md:overflow-x-clip' : framed ? 'flex-1 rounded-radius-28 web:overflow-x-clip' : 'flex-1';
|
|
97
|
+
const surfaceClass = [surfaceBase, surfaceClassName ?? 'bg-card'].join(' ');
|
|
98
|
+
const contentClass = [contentBase, contentClassName].filter(Boolean).join(' ');
|
|
74
99
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_nestingContext.ContentPanelNestingContext.Provider, {
|
|
75
100
|
value: true,
|
|
76
101
|
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
77
102
|
className: surfaceClass,
|
|
78
103
|
style: surfaceStyle,
|
|
79
|
-
children: [
|
|
104
|
+
children: [showOverlays && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
80
105
|
pointerEvents: "none",
|
|
81
|
-
className: 'web:sticky web:top-2 z-30 h-[calc(100dvh-16px)] w-full rounded-radius-28 web:[margin-bottom:calc(-100dvh+16px)] web:[clip-path:inset(-12px)]',
|
|
106
|
+
className: responsive ? 'web:sticky web:top-2 z-30 h-[calc(100dvh-16px)] w-full rounded-radius-28 max-md:hidden web:[margin-bottom:calc(-100dvh+16px)] web:[clip-path:inset(-12px)]' : 'web:sticky web:top-2 z-30 h-[calc(100dvh-16px)] w-full rounded-radius-28 web:[margin-bottom:calc(-100dvh+16px)] web:[clip-path:inset(-12px)]',
|
|
82
107
|
style: {
|
|
83
108
|
boxShadow: `0 0 0 ${GUTTER_MASK_SPREAD}px ${maskColor ?? colors.background}`
|
|
84
109
|
}
|
|
85
|
-
}, "bleed-mask"),
|
|
110
|
+
}, "bleed-mask"), showOverlays && showStickyFrame !== false && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
86
111
|
pointerEvents: "none",
|
|
87
|
-
className: 'web:sticky web:top-2 z-[120] h-[calc(100dvh-16px)] w-full rounded-radius-28 border border-border web:[margin-bottom:calc(-100dvh+16px)]'
|
|
112
|
+
className: responsive ? 'web:sticky web:top-2 z-[120] h-[calc(100dvh-16px)] w-full rounded-radius-28 border border-border max-md:hidden web:[margin-bottom:calc(-100dvh+16px)]' : 'web:sticky web:top-2 z-[120] h-[calc(100dvh-16px)] w-full rounded-radius-28 border border-border web:[margin-bottom:calc(-100dvh+16px)]'
|
|
88
113
|
}, "border-frame"), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
89
114
|
className: contentClass,
|
|
90
115
|
style: contentStyle,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_useTheme","_nestingContext","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","GUTTER_MASK_SPREAD","exports","PANEL_TOP_INSET","PANEL_BOTTOM_INSET","ContentPanelComponent","children","framed","surfaceClassName","surfaceStyle","contentClassName","contentStyle","showStickyFrame","maskColor","useContentPanelNestingGuard","colors","useTheme","surfaceClass","join","contentClass","filter","Boolean","jsx","ContentPanelNestingContext","Provider","value","jsxs","View","className","style","pointerEvents","boxShadow","background","ContentPanel","memo","displayName"],"sourceRoot":"../../../src","sources":["content-panel/index.web.tsx"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_useTheme","_nestingContext","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","GUTTER_MASK_SPREAD","exports","PANEL_TOP_INSET","PANEL_BOTTOM_INSET","ContentPanelComponent","children","framed","surfaceClassName","surfaceStyle","contentClassName","contentStyle","showStickyFrame","maskColor","useContentPanelNestingGuard","colors","useTheme","responsive","undefined","showOverlays","surfaceBase","contentBase","surfaceClass","join","contentClass","filter","Boolean","jsx","ContentPanelNestingContext","Provider","value","jsxs","View","className","style","pointerEvents","boxShadow","background","ContentPanel","memo","displayName"],"sourceRoot":"../../../src","sources":["content-panel/index.web.tsx"],"mappings":";;;;;;AAiDA,IAAAA,MAAA,GAAAC,uBAAA,CAAAC,OAAA;AACA,IAAAC,YAAA,GAAAD,OAAA;AAEA,IAAAE,SAAA,GAAAF,OAAA;AACA,IAAAG,eAAA,GAAAH,OAAA;AAG2B,IAAAI,WAAA,GAAAJ,OAAA;AAAA,SAAAD,wBAAAM,CAAA,EAAAC,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAR,uBAAA,YAAAA,CAAAM,CAAA,EAAAC,CAAA,SAAAA,CAAA,IAAAD,CAAA,IAAAA,CAAA,CAAAK,UAAA,SAAAL,CAAA,MAAAM,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAC,OAAA,EAAAV,CAAA,iBAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,SAAAQ,CAAA,MAAAF,CAAA,GAAAL,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAG,CAAA,CAAAK,GAAA,CAAAX,CAAA,UAAAM,CAAA,CAAAM,GAAA,CAAAZ,CAAA,GAAAM,CAAA,CAAAO,GAAA,CAAAb,CAAA,EAAAQ,CAAA,gBAAAP,CAAA,IAAAD,CAAA,gBAAAC,CAAA,OAAAa,cAAA,CAAAC,IAAA,CAAAf,CAAA,EAAAC,CAAA,OAAAM,CAAA,IAAAD,CAAA,GAAAU,MAAA,CAAAC,cAAA,KAAAD,MAAA,CAAAE,wBAAA,CAAAlB,CAAA,EAAAC,CAAA,OAAAM,CAAA,CAAAK,GAAA,IAAAL,CAAA,CAAAM,GAAA,IAAAP,CAAA,CAAAE,CAAA,EAAAP,CAAA,EAAAM,CAAA,IAAAC,CAAA,CAAAP,CAAA,IAAAD,CAAA,CAAAC,CAAA,WAAAO,CAAA,KAAAR,CAAA,EAAAC,CAAA;AAxD3B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAUA;AACO,MAAMkB,kBAAkB,GAAAC,OAAA,CAAAD,kBAAA,GAAG,EAAE;AACpC;AACO,MAAME,eAAe,GAAAD,OAAA,CAAAC,eAAA,GAAG,CAAC;AAChC;AACO,MAAMC,kBAAkB,GAAAF,OAAA,CAAAE,kBAAA,GAAG,CAAC;AAgCnC,MAAMC,qBAAkD,GAAGA,CAAC;EAC1DC,QAAQ;EACRC,MAAM;EACNC,gBAAgB;EAChBC,YAAY;EACZC,gBAAgB;EAChBC,YAAY;EACZC,eAAe;EACfC;AACF,CAAC,KAAK;EACJ;EACA;EACA,IAAAC,2CAA2B,EAAC,CAAC;EAC7B,MAAM;IAAEC;EAAO,CAAC,GAAG,IAAAC,kBAAQ,EAAC,CAAC;;EAE7B;EACA;EACA,MAAMC,UAAU,GAAGV,MAAM,KAAKW,SAAS;EACvC,MAAMC,YAAY,GAAGZ,MAAM,KAAK,KAAK;;EAErC;EACA;EACA;EACA;EACA,MAAMa,WAAW,GAAGH,UAAU,GAC1B,6BAA6B,GAC7BV,MAAM,GACJ,0BAA0B,GAC1B,QAAQ;EACd,MAAMc,WAAW,GAAGJ,UAAU,GAC1B,oDAAoD,GACpDV,MAAM,GACJ,8CAA8C,GAC9C,QAAQ;EACd,MAAMe,YAAY,GAAG,CAACF,WAAW,EAAEZ,gBAAgB,IAAI,SAAS,CAAC,CAACe,IAAI,CAAC,GAAG,CAAC;EAC3E,MAAMC,YAAY,GAAG,CAACH,WAAW,EAAEX,gBAAgB,CAAC,CAACe,MAAM,CAACC,OAAO,CAAC,CAACH,IAAI,CAAC,GAAG,CAAC;EAE9E,oBACE,IAAA1C,WAAA,CAAA8C,GAAA,EAAC/C,eAAA,CAAAgD,0BAA0B,CAACC,QAAQ;IAACC,KAAK,EAAE,IAAK;IAAAxB,QAAA,eAC/C,IAAAzB,WAAA,CAAAkD,IAAA,EAACrD,YAAA,CAAAsD,IAAI;MACIC,SAAS,EAAEX,YAAY;MAC9BY,KAAK,EAAEzB,YAAa;MAAAH,QAAA,GAKnBa,YAAY,iBACX,IAAAtC,WAAA,CAAA8C,GAAA,EAACjD,YAAA,CAAAsD,IAAI;QAEHG,aAAa,EAAC,MAAM;QAElBF,SAAS,EAAEhB,UAAU,GACjB,4JAA4J,GAC5J,8IAA8I;QAEpJiB,KAAK,EAAE;UAAEE,SAAS,EAAE,SAASnC,kBAAkB,MAAMY,SAAS,IAAIE,MAAM,CAACsB,UAAU;QAAG;MAAE,GAPpF,YAQL,CACF,EAGAlB,YAAY,IAAIP,eAAe,KAAK,KAAK,iBACxC,IAAA/B,WAAA,CAAA8C,GAAA,EAACjD,YAAA,CAAAsD,IAAI;QAEHG,aAAa,EAAC,MAAM;QAElBF,SAAS,EAAEhB,UAAU,GACjB,uJAAuJ,GACvJ;MAAyI,GAL3I,cAOL,CACF,eAKD,IAAApC,WAAA,CAAA8C,GAAA,EAACjD,YAAA,CAAAsD,IAAI;QAEIC,SAAS,EAAET,YAAY;QAC9BU,KAAK,EAAEvB,YAAa;QAAAL,QAAA,EAEnBA;MAAQ,GAJL,SAKA,CAAC;IAAA,CACH;EAAC,CAC4B,CAAC;AAE1C,CAAC;AAEM,MAAMgC,YAAY,GAAApC,OAAA,CAAAoC,YAAA,gBAAG,IAAAC,WAAI,EAAClC,qBAAqB,CAAC;AACvDiC,YAAY,CAACE,WAAW,GAAG,cAAc","ignoreList":[]}
|
|
@@ -9,11 +9,20 @@
|
|
|
9
9
|
* the rounded corners / lateral gutters is masked while a single seamless border
|
|
10
10
|
* is drawn around the panel — see `index.web.tsx`.
|
|
11
11
|
*
|
|
12
|
-
* On NATIVE none of
|
|
13
|
-
* positioning, and no bleed to mask, so the panel is simply a
|
|
14
|
-
* surface wrapping its content. The `framed`
|
|
15
|
-
*
|
|
16
|
-
* (
|
|
12
|
+
* On NATIVE none of the WEB overlay machinery applies: there is no document
|
|
13
|
+
* scroll, no sticky positioning, and no bleed to mask, so the panel is simply a
|
|
14
|
+
* surface wrapping its content. The `framed` prop still drives whether that
|
|
15
|
+
* surface is rounded + bordered, tri-state and resolved with pure NativeWind
|
|
16
|
+
* (`md:` evaluates against the window width on native too — no JS breakpoint
|
|
17
|
+
* hook needed):
|
|
18
|
+
*
|
|
19
|
+
* - `undefined` (DEFAULT) → responsive: full-bleed below `md`, rounded +
|
|
20
|
+
* bordered at `md`+ (`md:rounded-radius-28 md:border md:border-border`).
|
|
21
|
+
* - `false` → never framed (plain full-bleed at every size).
|
|
22
|
+
* - `true` → always rounded + bordered.
|
|
23
|
+
*
|
|
24
|
+
* `showStickyFrame` and `maskColor` are accepted for cross-platform API parity
|
|
25
|
+
* but are no-ops here (there are no sticky overlays on native).
|
|
17
26
|
*
|
|
18
27
|
* Web bundlers select `./index.web` via the `"browser"` export condition in
|
|
19
28
|
* `package.json`; native bundlers fall through to this file.
|
|
@@ -38,6 +47,7 @@ export const PANEL_TOP_INSET = 8;
|
|
|
38
47
|
export const PANEL_BOTTOM_INSET = 8;
|
|
39
48
|
const ContentPanelComponent = ({
|
|
40
49
|
children,
|
|
50
|
+
framed,
|
|
41
51
|
surfaceClassName,
|
|
42
52
|
surfaceStyle,
|
|
43
53
|
contentClassName,
|
|
@@ -45,7 +55,13 @@ const ContentPanelComponent = ({
|
|
|
45
55
|
}) => {
|
|
46
56
|
// Dev-only invariant — a ContentPanel must never be nested inside another.
|
|
47
57
|
useContentPanelNestingGuard();
|
|
48
|
-
|
|
58
|
+
|
|
59
|
+
// Tri-state: `undefined` → responsive (md:-gated), `true` → always framed,
|
|
60
|
+
// `false` → never framed (plain full-bleed). Whole literal class strings are
|
|
61
|
+
// selected per mode so the Tailwind content-scan over `src/**` picks up every
|
|
62
|
+
// `md:` / `rounded-radius-28` token verbatim (no dynamic concatenation).
|
|
63
|
+
const surfaceBase = framed === undefined ? 'flex-1 md:overflow-hidden md:rounded-radius-28 md:border md:border-border' : framed ? 'flex-1 overflow-hidden rounded-radius-28 border border-border' : 'flex-1';
|
|
64
|
+
const surfaceClass = [surfaceBase, surfaceClassName ?? 'bg-card'].join(' ');
|
|
49
65
|
const contentClass = ['flex-1', contentClassName].filter(Boolean).join(' ');
|
|
50
66
|
return /*#__PURE__*/_jsx(ContentPanelNestingContext.Provider, {
|
|
51
67
|
value: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","memo","View","ContentPanelNestingContext","useContentPanelNestingGuard","jsx","_jsx","GUTTER_MASK_SPREAD","PANEL_TOP_INSET","PANEL_BOTTOM_INSET","ContentPanelComponent","children","surfaceClassName","surfaceStyle","contentClassName","contentStyle","surfaceClass","join","contentClass","filter","Boolean","Provider","value","className","style","ContentPanel","displayName"],"sourceRoot":"../../../src","sources":["content-panel/index.tsx"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAOA,KAAK,IAAIC,IAAI,QAAQ,OAAO;AACnC,SAASC,IAAI,QAAwC,cAAc;AAEnE,SACEC,0BAA0B,EAC1BC,2BAA2B,QACtB,sBAAmB;;AAE1B;AACA;AACA;AACA;AAHA,SAAAC,GAAA,IAAAC,IAAA;AAIA,OAAO,MAAMC,kBAAkB,GAAG,EAAE;AACpC;AACA,OAAO,MAAMC,eAAe,GAAG,CAAC;AAChC;AACA,OAAO,MAAMC,kBAAkB,GAAG,CAAC;
|
|
1
|
+
{"version":3,"names":["React","memo","View","ContentPanelNestingContext","useContentPanelNestingGuard","jsx","_jsx","GUTTER_MASK_SPREAD","PANEL_TOP_INSET","PANEL_BOTTOM_INSET","ContentPanelComponent","children","framed","surfaceClassName","surfaceStyle","contentClassName","contentStyle","surfaceBase","undefined","surfaceClass","join","contentClass","filter","Boolean","Provider","value","className","style","ContentPanel","displayName"],"sourceRoot":"../../../src","sources":["content-panel/index.tsx"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAOA,KAAK,IAAIC,IAAI,QAAQ,OAAO;AACnC,SAASC,IAAI,QAAwC,cAAc;AAEnE,SACEC,0BAA0B,EAC1BC,2BAA2B,QACtB,sBAAmB;;AAE1B;AACA;AACA;AACA;AAHA,SAAAC,GAAA,IAAAC,IAAA;AAIA,OAAO,MAAMC,kBAAkB,GAAG,EAAE;AACpC;AACA,OAAO,MAAMC,eAAe,GAAG,CAAC;AAChC;AACA,OAAO,MAAMC,kBAAkB,GAAG,CAAC;AA+BnC,MAAMC,qBAAkD,GAAGA,CAAC;EAC1DC,QAAQ;EACRC,MAAM;EACNC,gBAAgB;EAChBC,YAAY;EACZC,gBAAgB;EAChBC;AACF,CAAC,KAAK;EACJ;EACAZ,2BAA2B,CAAC,CAAC;;EAE7B;EACA;EACA;EACA;EACA,MAAMa,WAAW,GACfL,MAAM,KAAKM,SAAS,GAChB,2EAA2E,GAC3EN,MAAM,GACJ,+DAA+D,GAC/D,QAAQ;EAChB,MAAMO,YAAY,GAAG,CAACF,WAAW,EAAEJ,gBAAgB,IAAI,SAAS,CAAC,CAACO,IAAI,CAAC,GAAG,CAAC;EAC3E,MAAMC,YAAY,GAAG,CAAC,QAAQ,EAAEN,gBAAgB,CAAC,CAACO,MAAM,CAACC,OAAO,CAAC,CAACH,IAAI,CAAC,GAAG,CAAC;EAE3E,oBACEd,IAAA,CAACH,0BAA0B,CAACqB,QAAQ;IAACC,KAAK,EAAE,IAAK;IAAAd,QAAA,eAC/CL,IAAA,CAACJ,IAAI;MACIwB,SAAS,EAAEP,YAAY;MAC9BQ,KAAK,EAAEb,YAAa;MAAAH,QAAA,eAEpBL,IAAA,CAACJ,IAAI;QACIwB,SAAS,EAAEL,YAAY;QAC9BM,KAAK,EAAEX,YAAa;QAAAL,QAAA,EAEnBA;MAAQ,CACL;IAAC,CACH;EAAC,CAC4B,CAAC;AAE1C,CAAC;AAED,OAAO,MAAMiB,YAAY,gBAAG3B,IAAI,CAACS,qBAAqB,CAAC;AACvDkB,YAAY,CAACC,WAAW,GAAG,cAAc","ignoreList":[]}
|
|
@@ -25,16 +25,29 @@
|
|
|
25
25
|
* content rather than displacing it). They render BEFORE the content wrapper so
|
|
26
26
|
* z-index — not DOM order — decides layering.
|
|
27
27
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
28
|
+
* Framing is tri-state via the `framed` prop:
|
|
29
|
+
*
|
|
30
|
+
* - `undefined` (DEFAULT) → RESPONSIVE, driven purely by NativeWind: full-bleed
|
|
31
|
+
* below `md`, framed at `md`+. The rounding is `md:`-gated and both overlays
|
|
32
|
+
* are always rendered but carry `max-md:hidden` (`display:none` below `md`),
|
|
33
|
+
* so the breakpoint is decided in CSS — no consumer JS breakpoint hook.
|
|
34
|
+
* - `false` → NEVER framed (full-bleed at every size): a single flat surface,
|
|
35
|
+
* no rounding, no overlays.
|
|
36
|
+
* - `true` → ALWAYS framed (rounded + overlays at every size).
|
|
37
|
+
*
|
|
38
|
+
* The overlays are gated by VISIBILITY (a `max-md:hidden` literal) rather than
|
|
39
|
+
* by conditional mounting for the responsive case, so crossing the breakpoint
|
|
40
|
+
* never remounts them. The content wrapper likewise keeps a stable `key` so
|
|
41
|
+
* `{children}` reconciles in place across the breakpoint instead of remounting
|
|
42
|
+
* (which would reset feed scroll / the virtualizer + refetch).
|
|
30
43
|
*
|
|
31
44
|
* Native bundlers use `./index.tsx` (a plain rounded surface); web bundlers
|
|
32
45
|
* select this file via the `"browser"` export condition in `package.json`.
|
|
33
46
|
*
|
|
34
47
|
* Styling is NativeWind-className-first; the literal class strings below MUST
|
|
35
48
|
* stay literal so a consumer's Tailwind content-scan over `lib/**` picks them up
|
|
36
|
-
* (no dynamic concatenation of the arbitrary `web:[…]` / `rounded-radius-28`
|
|
37
|
-
* parts).
|
|
49
|
+
* (no dynamic concatenation of the arbitrary `web:[…]` / `rounded-radius-28` /
|
|
50
|
+
* `md:` parts — whole class strings are selected per mode instead).
|
|
38
51
|
*/
|
|
39
52
|
import React, { memo } from 'react';
|
|
40
53
|
import { View } from 'react-native';
|
|
@@ -58,28 +71,40 @@ const ContentPanelComponent = ({
|
|
|
58
71
|
showStickyFrame,
|
|
59
72
|
maskColor
|
|
60
73
|
}) => {
|
|
61
|
-
// Dev-only invariant — must run unconditionally before
|
|
62
|
-
//
|
|
74
|
+
// Dev-only invariant — must run unconditionally (before deriving any
|
|
75
|
+
// mode-specific branch) so the hook order stays stable (rules of hooks).
|
|
63
76
|
useContentPanelNestingGuard();
|
|
64
77
|
const {
|
|
65
78
|
colors
|
|
66
79
|
} = useTheme();
|
|
67
|
-
|
|
68
|
-
|
|
80
|
+
|
|
81
|
+
// Tri-state: `undefined` → responsive (md:-gated), `true` → always framed,
|
|
82
|
+
// `false` → never framed (full-bleed).
|
|
83
|
+
const responsive = framed === undefined;
|
|
84
|
+
const showOverlays = framed !== false;
|
|
85
|
+
|
|
86
|
+
// Whole literal class strings selected per mode (the Tailwind content-scan
|
|
87
|
+
// over `lib/**` requires each arbitrary/`md:`/`web:` token stay literal).
|
|
88
|
+
// `web:md:overflow-x-clip` is platform-first-then-breakpoint, matching the
|
|
89
|
+
// consumer convention (`web:sm:flex` in `@mercaria/ui`).
|
|
90
|
+
const surfaceBase = responsive ? 'flex-1 md:rounded-radius-28' : framed ? 'flex-1 rounded-radius-28' : 'flex-1';
|
|
91
|
+
const contentBase = responsive ? 'flex-1 md:rounded-radius-28 web:md:overflow-x-clip' : framed ? 'flex-1 rounded-radius-28 web:overflow-x-clip' : 'flex-1';
|
|
92
|
+
const surfaceClass = [surfaceBase, surfaceClassName ?? 'bg-card'].join(' ');
|
|
93
|
+
const contentClass = [contentBase, contentClassName].filter(Boolean).join(' ');
|
|
69
94
|
return /*#__PURE__*/_jsx(ContentPanelNestingContext.Provider, {
|
|
70
95
|
value: true,
|
|
71
96
|
children: /*#__PURE__*/_jsxs(View, {
|
|
72
97
|
className: surfaceClass,
|
|
73
98
|
style: surfaceStyle,
|
|
74
|
-
children: [
|
|
99
|
+
children: [showOverlays && /*#__PURE__*/_jsx(View, {
|
|
75
100
|
pointerEvents: "none",
|
|
76
|
-
className: 'web:sticky web:top-2 z-30 h-[calc(100dvh-16px)] w-full rounded-radius-28 web:[margin-bottom:calc(-100dvh+16px)] web:[clip-path:inset(-12px)]',
|
|
101
|
+
className: responsive ? 'web:sticky web:top-2 z-30 h-[calc(100dvh-16px)] w-full rounded-radius-28 max-md:hidden web:[margin-bottom:calc(-100dvh+16px)] web:[clip-path:inset(-12px)]' : 'web:sticky web:top-2 z-30 h-[calc(100dvh-16px)] w-full rounded-radius-28 web:[margin-bottom:calc(-100dvh+16px)] web:[clip-path:inset(-12px)]',
|
|
77
102
|
style: {
|
|
78
103
|
boxShadow: `0 0 0 ${GUTTER_MASK_SPREAD}px ${maskColor ?? colors.background}`
|
|
79
104
|
}
|
|
80
|
-
}, "bleed-mask"),
|
|
105
|
+
}, "bleed-mask"), showOverlays && showStickyFrame !== false && /*#__PURE__*/_jsx(View, {
|
|
81
106
|
pointerEvents: "none",
|
|
82
|
-
className: 'web:sticky web:top-2 z-[120] h-[calc(100dvh-16px)] w-full rounded-radius-28 border border-border web:[margin-bottom:calc(-100dvh+16px)]'
|
|
107
|
+
className: responsive ? 'web:sticky web:top-2 z-[120] h-[calc(100dvh-16px)] w-full rounded-radius-28 border border-border max-md:hidden web:[margin-bottom:calc(-100dvh+16px)]' : 'web:sticky web:top-2 z-[120] h-[calc(100dvh-16px)] w-full rounded-radius-28 border border-border web:[margin-bottom:calc(-100dvh+16px)]'
|
|
83
108
|
}, "border-frame"), /*#__PURE__*/_jsx(View, {
|
|
84
109
|
className: contentClass,
|
|
85
110
|
style: contentStyle,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","memo","View","useTheme","ContentPanelNestingContext","useContentPanelNestingGuard","jsx","_jsx","jsxs","_jsxs","GUTTER_MASK_SPREAD","PANEL_TOP_INSET","PANEL_BOTTOM_INSET","ContentPanelComponent","children","framed","surfaceClassName","surfaceStyle","contentClassName","contentStyle","showStickyFrame","maskColor","colors","surfaceClass","join","contentClass","filter","Boolean","Provider","value","className","style","pointerEvents","boxShadow","background","ContentPanel","displayName"],"sourceRoot":"../../../src","sources":["content-panel/index.web.tsx"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAOA,KAAK,IAAIC,IAAI,QAAQ,OAAO;AACnC,SAASC,IAAI,QAAwC,cAAc;AAEnE,SAASC,QAAQ,QAAQ,uBAAoB;AAC7C,SACEC,0BAA0B,EAC1BC,2BAA2B,QACtB,sBAAmB;;AAE1B;AAAA,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AACA,OAAO,MAAMC,kBAAkB,GAAG,EAAE;AACpC;AACA,OAAO,MAAMC,eAAe,GAAG,CAAC;AAChC;AACA,OAAO,MAAMC,kBAAkB,GAAG,CAAC;
|
|
1
|
+
{"version":3,"names":["React","memo","View","useTheme","ContentPanelNestingContext","useContentPanelNestingGuard","jsx","_jsx","jsxs","_jsxs","GUTTER_MASK_SPREAD","PANEL_TOP_INSET","PANEL_BOTTOM_INSET","ContentPanelComponent","children","framed","surfaceClassName","surfaceStyle","contentClassName","contentStyle","showStickyFrame","maskColor","colors","responsive","undefined","showOverlays","surfaceBase","contentBase","surfaceClass","join","contentClass","filter","Boolean","Provider","value","className","style","pointerEvents","boxShadow","background","ContentPanel","displayName"],"sourceRoot":"../../../src","sources":["content-panel/index.web.tsx"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAOA,KAAK,IAAIC,IAAI,QAAQ,OAAO;AACnC,SAASC,IAAI,QAAwC,cAAc;AAEnE,SAASC,QAAQ,QAAQ,uBAAoB;AAC7C,SACEC,0BAA0B,EAC1BC,2BAA2B,QACtB,sBAAmB;;AAE1B;AAAA,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AACA,OAAO,MAAMC,kBAAkB,GAAG,EAAE;AACpC;AACA,OAAO,MAAMC,eAAe,GAAG,CAAC;AAChC;AACA,OAAO,MAAMC,kBAAkB,GAAG,CAAC;AAgCnC,MAAMC,qBAAkD,GAAGA,CAAC;EAC1DC,QAAQ;EACRC,MAAM;EACNC,gBAAgB;EAChBC,YAAY;EACZC,gBAAgB;EAChBC,YAAY;EACZC,eAAe;EACfC;AACF,CAAC,KAAK;EACJ;EACA;EACAhB,2BAA2B,CAAC,CAAC;EAC7B,MAAM;IAAEiB;EAAO,CAAC,GAAGnB,QAAQ,CAAC,CAAC;;EAE7B;EACA;EACA,MAAMoB,UAAU,GAAGR,MAAM,KAAKS,SAAS;EACvC,MAAMC,YAAY,GAAGV,MAAM,KAAK,KAAK;;EAErC;EACA;EACA;EACA;EACA,MAAMW,WAAW,GAAGH,UAAU,GAC1B,6BAA6B,GAC7BR,MAAM,GACJ,0BAA0B,GAC1B,QAAQ;EACd,MAAMY,WAAW,GAAGJ,UAAU,GAC1B,oDAAoD,GACpDR,MAAM,GACJ,8CAA8C,GAC9C,QAAQ;EACd,MAAMa,YAAY,GAAG,CAACF,WAAW,EAAEV,gBAAgB,IAAI,SAAS,CAAC,CAACa,IAAI,CAAC,GAAG,CAAC;EAC3E,MAAMC,YAAY,GAAG,CAACH,WAAW,EAAET,gBAAgB,CAAC,CAACa,MAAM,CAACC,OAAO,CAAC,CAACH,IAAI,CAAC,GAAG,CAAC;EAE9E,oBACEtB,IAAA,CAACH,0BAA0B,CAAC6B,QAAQ;IAACC,KAAK,EAAE,IAAK;IAAApB,QAAA,eAC/CL,KAAA,CAACP,IAAI;MACIiC,SAAS,EAAEP,YAAY;MAC9BQ,KAAK,EAAEnB,YAAa;MAAAH,QAAA,GAKnBW,YAAY,iBACXlB,IAAA,CAACL,IAAI;QAEHmC,aAAa,EAAC,MAAM;QAElBF,SAAS,EAAEZ,UAAU,GACjB,4JAA4J,GAC5J,8IAA8I;QAEpJa,KAAK,EAAE;UAAEE,SAAS,EAAE,SAAS5B,kBAAkB,MAAMW,SAAS,IAAIC,MAAM,CAACiB,UAAU;QAAG;MAAE,GAPpF,YAQL,CACF,EAGAd,YAAY,IAAIL,eAAe,KAAK,KAAK,iBACxCb,IAAA,CAACL,IAAI;QAEHmC,aAAa,EAAC,MAAM;QAElBF,SAAS,EAAEZ,UAAU,GACjB,uJAAuJ,GACvJ;MAAyI,GAL3I,cAOL,CACF,eAKDhB,IAAA,CAACL,IAAI;QAEIiC,SAAS,EAAEL,YAAY;QAC9BM,KAAK,EAAEjB,YAAa;QAAAL,QAAA,EAEnBA;MAAQ,GAJL,SAKA,CAAC;IAAA,CACH;EAAC,CAC4B,CAAC;AAE1C,CAAC;AAED,OAAO,MAAM0B,YAAY,gBAAGvC,IAAI,CAACY,qBAAqB,CAAC;AACvD2B,YAAY,CAACC,WAAW,GAAG,cAAc","ignoreList":[]}
|
|
@@ -7,11 +7,20 @@
|
|
|
7
7
|
* the rounded corners / lateral gutters is masked while a single seamless border
|
|
8
8
|
* is drawn around the panel — see `index.web.tsx`.
|
|
9
9
|
*
|
|
10
|
-
* On NATIVE none of
|
|
11
|
-
* positioning, and no bleed to mask, so the panel is simply a
|
|
12
|
-
* surface wrapping its content. The `framed`
|
|
13
|
-
*
|
|
14
|
-
* (
|
|
10
|
+
* On NATIVE none of the WEB overlay machinery applies: there is no document
|
|
11
|
+
* scroll, no sticky positioning, and no bleed to mask, so the panel is simply a
|
|
12
|
+
* surface wrapping its content. The `framed` prop still drives whether that
|
|
13
|
+
* surface is rounded + bordered, tri-state and resolved with pure NativeWind
|
|
14
|
+
* (`md:` evaluates against the window width on native too — no JS breakpoint
|
|
15
|
+
* hook needed):
|
|
16
|
+
*
|
|
17
|
+
* - `undefined` (DEFAULT) → responsive: full-bleed below `md`, rounded +
|
|
18
|
+
* bordered at `md`+ (`md:rounded-radius-28 md:border md:border-border`).
|
|
19
|
+
* - `false` → never framed (plain full-bleed at every size).
|
|
20
|
+
* - `true` → always rounded + bordered.
|
|
21
|
+
*
|
|
22
|
+
* `showStickyFrame` and `maskColor` are accepted for cross-platform API parity
|
|
23
|
+
* but are no-ops here (there are no sticky overlays on native).
|
|
15
24
|
*
|
|
16
25
|
* Web bundlers select `./index.web` via the `"browser"` export condition in
|
|
17
26
|
* `package.json`; native bundlers fall through to this file.
|
|
@@ -34,10 +43,14 @@ export declare const PANEL_BOTTOM_INSET = 8;
|
|
|
34
43
|
export interface ContentPanelProps {
|
|
35
44
|
children: React.ReactNode;
|
|
36
45
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
46
|
+
* Framing mode. Tri-state, resolved purely with NativeWind — no consumer
|
|
47
|
+
* breakpoint hook needed:
|
|
48
|
+
* - `undefined` (DEFAULT) → responsive: full-bleed below `md`, rounded +
|
|
49
|
+
* bordered at `md`+.
|
|
50
|
+
* - `false` → never framed (plain full-bleed at every size).
|
|
51
|
+
* - `true` → always rounded + bordered.
|
|
39
52
|
*/
|
|
40
|
-
framed
|
|
53
|
+
framed?: boolean;
|
|
41
54
|
/** Override the surface background utility (defaults to `bg-card`). */
|
|
42
55
|
surfaceClassName?: string;
|
|
43
56
|
surfaceStyle?: StyleProp<ViewStyle>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/content-panel/index.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/content-panel/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,KAAe,MAAM,OAAO,CAAC;AACpC,OAAO,EAAQ,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAOpE;;;GAGG;AACH,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC,wDAAwD;AACxD,eAAO,MAAM,eAAe,IAAI,CAAC;AACjC,2DAA2D;AAC3D,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACpC,qDAAqD;IACrD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACpC;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA2CD,eAAO,MAAM,YAAY,+CAA8B,CAAC"}
|
|
@@ -23,16 +23,29 @@
|
|
|
23
23
|
* content rather than displacing it). They render BEFORE the content wrapper so
|
|
24
24
|
* z-index — not DOM order — decides layering.
|
|
25
25
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
26
|
+
* Framing is tri-state via the `framed` prop:
|
|
27
|
+
*
|
|
28
|
+
* - `undefined` (DEFAULT) → RESPONSIVE, driven purely by NativeWind: full-bleed
|
|
29
|
+
* below `md`, framed at `md`+. The rounding is `md:`-gated and both overlays
|
|
30
|
+
* are always rendered but carry `max-md:hidden` (`display:none` below `md`),
|
|
31
|
+
* so the breakpoint is decided in CSS — no consumer JS breakpoint hook.
|
|
32
|
+
* - `false` → NEVER framed (full-bleed at every size): a single flat surface,
|
|
33
|
+
* no rounding, no overlays.
|
|
34
|
+
* - `true` → ALWAYS framed (rounded + overlays at every size).
|
|
35
|
+
*
|
|
36
|
+
* The overlays are gated by VISIBILITY (a `max-md:hidden` literal) rather than
|
|
37
|
+
* by conditional mounting for the responsive case, so crossing the breakpoint
|
|
38
|
+
* never remounts them. The content wrapper likewise keeps a stable `key` so
|
|
39
|
+
* `{children}` reconciles in place across the breakpoint instead of remounting
|
|
40
|
+
* (which would reset feed scroll / the virtualizer + refetch).
|
|
28
41
|
*
|
|
29
42
|
* Native bundlers use `./index.tsx` (a plain rounded surface); web bundlers
|
|
30
43
|
* select this file via the `"browser"` export condition in `package.json`.
|
|
31
44
|
*
|
|
32
45
|
* Styling is NativeWind-className-first; the literal class strings below MUST
|
|
33
46
|
* stay literal so a consumer's Tailwind content-scan over `lib/**` picks them up
|
|
34
|
-
* (no dynamic concatenation of the arbitrary `web:[…]` / `rounded-radius-28`
|
|
35
|
-
* parts).
|
|
47
|
+
* (no dynamic concatenation of the arbitrary `web:[…]` / `rounded-radius-28` /
|
|
48
|
+
* `md:` parts — whole class strings are selected per mode instead).
|
|
36
49
|
*/
|
|
37
50
|
import React from 'react';
|
|
38
51
|
import { type StyleProp, type ViewStyle } from 'react-native';
|
|
@@ -44,8 +57,15 @@ export declare const PANEL_TOP_INSET = 8;
|
|
|
44
57
|
export declare const PANEL_BOTTOM_INSET = 8;
|
|
45
58
|
export interface ContentPanelProps {
|
|
46
59
|
children: React.ReactNode;
|
|
47
|
-
/**
|
|
48
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Framing mode. Tri-state, resolved purely with NativeWind — no consumer
|
|
62
|
+
* breakpoint hook needed:
|
|
63
|
+
* - `undefined` (DEFAULT) → responsive: full-bleed below `md`, framed at
|
|
64
|
+
* `md`+ (rounded corners + sticky bleed-mask/border overlays).
|
|
65
|
+
* - `false` → never framed (full-bleed at every size).
|
|
66
|
+
* - `true` → always framed (rounded + overlays at every size).
|
|
67
|
+
*/
|
|
68
|
+
framed?: boolean;
|
|
49
69
|
/** Override the surface background utility (defaults to `bg-card`). */
|
|
50
70
|
surfaceClassName?: string;
|
|
51
71
|
surfaceStyle?: StyleProp<ViewStyle>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.web.d.ts","sourceRoot":"","sources":["../../../../src/content-panel/index.web.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.web.d.ts","sourceRoot":"","sources":["../../../../src/content-panel/index.web.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,OAAO,KAAe,MAAM,OAAO,CAAC;AACpC,OAAO,EAAQ,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAQpE,+DAA+D;AAC/D,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC,6DAA6D;AAC7D,eAAO,MAAM,eAAe,IAAI,CAAC;AACjC,2DAA2D;AAC3D,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACpC,qDAAqD;IACrD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACpC,qEAAqE;IACrE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAyFD,eAAO,MAAM,YAAY,+CAA8B,CAAC"}
|
|
@@ -7,11 +7,20 @@
|
|
|
7
7
|
* the rounded corners / lateral gutters is masked while a single seamless border
|
|
8
8
|
* is drawn around the panel — see `index.web.tsx`.
|
|
9
9
|
*
|
|
10
|
-
* On NATIVE none of
|
|
11
|
-
* positioning, and no bleed to mask, so the panel is simply a
|
|
12
|
-
* surface wrapping its content. The `framed`
|
|
13
|
-
*
|
|
14
|
-
* (
|
|
10
|
+
* On NATIVE none of the WEB overlay machinery applies: there is no document
|
|
11
|
+
* scroll, no sticky positioning, and no bleed to mask, so the panel is simply a
|
|
12
|
+
* surface wrapping its content. The `framed` prop still drives whether that
|
|
13
|
+
* surface is rounded + bordered, tri-state and resolved with pure NativeWind
|
|
14
|
+
* (`md:` evaluates against the window width on native too — no JS breakpoint
|
|
15
|
+
* hook needed):
|
|
16
|
+
*
|
|
17
|
+
* - `undefined` (DEFAULT) → responsive: full-bleed below `md`, rounded +
|
|
18
|
+
* bordered at `md`+ (`md:rounded-radius-28 md:border md:border-border`).
|
|
19
|
+
* - `false` → never framed (plain full-bleed at every size).
|
|
20
|
+
* - `true` → always rounded + bordered.
|
|
21
|
+
*
|
|
22
|
+
* `showStickyFrame` and `maskColor` are accepted for cross-platform API parity
|
|
23
|
+
* but are no-ops here (there are no sticky overlays on native).
|
|
15
24
|
*
|
|
16
25
|
* Web bundlers select `./index.web` via the `"browser"` export condition in
|
|
17
26
|
* `package.json`; native bundlers fall through to this file.
|
|
@@ -34,10 +43,14 @@ export declare const PANEL_BOTTOM_INSET = 8;
|
|
|
34
43
|
export interface ContentPanelProps {
|
|
35
44
|
children: React.ReactNode;
|
|
36
45
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
46
|
+
* Framing mode. Tri-state, resolved purely with NativeWind — no consumer
|
|
47
|
+
* breakpoint hook needed:
|
|
48
|
+
* - `undefined` (DEFAULT) → responsive: full-bleed below `md`, rounded +
|
|
49
|
+
* bordered at `md`+.
|
|
50
|
+
* - `false` → never framed (plain full-bleed at every size).
|
|
51
|
+
* - `true` → always rounded + bordered.
|
|
39
52
|
*/
|
|
40
|
-
framed
|
|
53
|
+
framed?: boolean;
|
|
41
54
|
/** Override the surface background utility (defaults to `bg-card`). */
|
|
42
55
|
surfaceClassName?: string;
|
|
43
56
|
surfaceStyle?: StyleProp<ViewStyle>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/content-panel/index.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/content-panel/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,KAAe,MAAM,OAAO,CAAC;AACpC,OAAO,EAAQ,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAOpE;;;GAGG;AACH,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC,wDAAwD;AACxD,eAAO,MAAM,eAAe,IAAI,CAAC;AACjC,2DAA2D;AAC3D,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACpC,qDAAqD;IACrD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACpC;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA2CD,eAAO,MAAM,YAAY,+CAA8B,CAAC"}
|
|
@@ -23,16 +23,29 @@
|
|
|
23
23
|
* content rather than displacing it). They render BEFORE the content wrapper so
|
|
24
24
|
* z-index — not DOM order — decides layering.
|
|
25
25
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
26
|
+
* Framing is tri-state via the `framed` prop:
|
|
27
|
+
*
|
|
28
|
+
* - `undefined` (DEFAULT) → RESPONSIVE, driven purely by NativeWind: full-bleed
|
|
29
|
+
* below `md`, framed at `md`+. The rounding is `md:`-gated and both overlays
|
|
30
|
+
* are always rendered but carry `max-md:hidden` (`display:none` below `md`),
|
|
31
|
+
* so the breakpoint is decided in CSS — no consumer JS breakpoint hook.
|
|
32
|
+
* - `false` → NEVER framed (full-bleed at every size): a single flat surface,
|
|
33
|
+
* no rounding, no overlays.
|
|
34
|
+
* - `true` → ALWAYS framed (rounded + overlays at every size).
|
|
35
|
+
*
|
|
36
|
+
* The overlays are gated by VISIBILITY (a `max-md:hidden` literal) rather than
|
|
37
|
+
* by conditional mounting for the responsive case, so crossing the breakpoint
|
|
38
|
+
* never remounts them. The content wrapper likewise keeps a stable `key` so
|
|
39
|
+
* `{children}` reconciles in place across the breakpoint instead of remounting
|
|
40
|
+
* (which would reset feed scroll / the virtualizer + refetch).
|
|
28
41
|
*
|
|
29
42
|
* Native bundlers use `./index.tsx` (a plain rounded surface); web bundlers
|
|
30
43
|
* select this file via the `"browser"` export condition in `package.json`.
|
|
31
44
|
*
|
|
32
45
|
* Styling is NativeWind-className-first; the literal class strings below MUST
|
|
33
46
|
* stay literal so a consumer's Tailwind content-scan over `lib/**` picks them up
|
|
34
|
-
* (no dynamic concatenation of the arbitrary `web:[…]` / `rounded-radius-28`
|
|
35
|
-
* parts).
|
|
47
|
+
* (no dynamic concatenation of the arbitrary `web:[…]` / `rounded-radius-28` /
|
|
48
|
+
* `md:` parts — whole class strings are selected per mode instead).
|
|
36
49
|
*/
|
|
37
50
|
import React from 'react';
|
|
38
51
|
import { type StyleProp, type ViewStyle } from 'react-native';
|
|
@@ -44,8 +57,15 @@ export declare const PANEL_TOP_INSET = 8;
|
|
|
44
57
|
export declare const PANEL_BOTTOM_INSET = 8;
|
|
45
58
|
export interface ContentPanelProps {
|
|
46
59
|
children: React.ReactNode;
|
|
47
|
-
/**
|
|
48
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Framing mode. Tri-state, resolved purely with NativeWind — no consumer
|
|
62
|
+
* breakpoint hook needed:
|
|
63
|
+
* - `undefined` (DEFAULT) → responsive: full-bleed below `md`, framed at
|
|
64
|
+
* `md`+ (rounded corners + sticky bleed-mask/border overlays).
|
|
65
|
+
* - `false` → never framed (full-bleed at every size).
|
|
66
|
+
* - `true` → always framed (rounded + overlays at every size).
|
|
67
|
+
*/
|
|
68
|
+
framed?: boolean;
|
|
49
69
|
/** Override the surface background utility (defaults to `bg-card`). */
|
|
50
70
|
surfaceClassName?: string;
|
|
51
71
|
surfaceStyle?: StyleProp<ViewStyle>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.web.d.ts","sourceRoot":"","sources":["../../../../src/content-panel/index.web.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.web.d.ts","sourceRoot":"","sources":["../../../../src/content-panel/index.web.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,OAAO,KAAe,MAAM,OAAO,CAAC;AACpC,OAAO,EAAQ,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAQpE,+DAA+D;AAC/D,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC,6DAA6D;AAC7D,eAAO,MAAM,eAAe,IAAI,CAAC;AACjC,2DAA2D;AAC3D,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACpC,qDAAqD;IACrD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACpC,qEAAqE;IACrE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAyFD,eAAO,MAAM,YAAY,+CAA8B,CAAC"}
|
package/package.json
CHANGED
|
@@ -7,11 +7,20 @@
|
|
|
7
7
|
* the rounded corners / lateral gutters is masked while a single seamless border
|
|
8
8
|
* is drawn around the panel — see `index.web.tsx`.
|
|
9
9
|
*
|
|
10
|
-
* On NATIVE none of
|
|
11
|
-
* positioning, and no bleed to mask, so the panel is simply a
|
|
12
|
-
* surface wrapping its content. The `framed`
|
|
13
|
-
*
|
|
14
|
-
* (
|
|
10
|
+
* On NATIVE none of the WEB overlay machinery applies: there is no document
|
|
11
|
+
* scroll, no sticky positioning, and no bleed to mask, so the panel is simply a
|
|
12
|
+
* surface wrapping its content. The `framed` prop still drives whether that
|
|
13
|
+
* surface is rounded + bordered, tri-state and resolved with pure NativeWind
|
|
14
|
+
* (`md:` evaluates against the window width on native too — no JS breakpoint
|
|
15
|
+
* hook needed):
|
|
16
|
+
*
|
|
17
|
+
* - `undefined` (DEFAULT) → responsive: full-bleed below `md`, rounded +
|
|
18
|
+
* bordered at `md`+ (`md:rounded-radius-28 md:border md:border-border`).
|
|
19
|
+
* - `false` → never framed (plain full-bleed at every size).
|
|
20
|
+
* - `true` → always rounded + bordered.
|
|
21
|
+
*
|
|
22
|
+
* `showStickyFrame` and `maskColor` are accepted for cross-platform API parity
|
|
23
|
+
* but are no-ops here (there are no sticky overlays on native).
|
|
15
24
|
*
|
|
16
25
|
* Web bundlers select `./index.web` via the `"browser"` export condition in
|
|
17
26
|
* `package.json`; native bundlers fall through to this file.
|
|
@@ -41,10 +50,14 @@ export const PANEL_BOTTOM_INSET = 8;
|
|
|
41
50
|
export interface ContentPanelProps {
|
|
42
51
|
children: React.ReactNode;
|
|
43
52
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
53
|
+
* Framing mode. Tri-state, resolved purely with NativeWind — no consumer
|
|
54
|
+
* breakpoint hook needed:
|
|
55
|
+
* - `undefined` (DEFAULT) → responsive: full-bleed below `md`, rounded +
|
|
56
|
+
* bordered at `md`+.
|
|
57
|
+
* - `false` → never framed (plain full-bleed at every size).
|
|
58
|
+
* - `true` → always rounded + bordered.
|
|
46
59
|
*/
|
|
47
|
-
framed
|
|
60
|
+
framed?: boolean;
|
|
48
61
|
/** Override the surface background utility (defaults to `bg-card`). */
|
|
49
62
|
surfaceClassName?: string;
|
|
50
63
|
surfaceStyle?: StyleProp<ViewStyle>;
|
|
@@ -65,6 +78,7 @@ export interface ContentPanelProps {
|
|
|
65
78
|
|
|
66
79
|
const ContentPanelComponent: React.FC<ContentPanelProps> = ({
|
|
67
80
|
children,
|
|
81
|
+
framed,
|
|
68
82
|
surfaceClassName,
|
|
69
83
|
surfaceStyle,
|
|
70
84
|
contentClassName,
|
|
@@ -73,12 +87,17 @@ const ContentPanelComponent: React.FC<ContentPanelProps> = ({
|
|
|
73
87
|
// Dev-only invariant — a ContentPanel must never be nested inside another.
|
|
74
88
|
useContentPanelNestingGuard();
|
|
75
89
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
90
|
+
// Tri-state: `undefined` → responsive (md:-gated), `true` → always framed,
|
|
91
|
+
// `false` → never framed (plain full-bleed). Whole literal class strings are
|
|
92
|
+
// selected per mode so the Tailwind content-scan over `src/**` picks up every
|
|
93
|
+
// `md:` / `rounded-radius-28` token verbatim (no dynamic concatenation).
|
|
94
|
+
const surfaceBase =
|
|
95
|
+
framed === undefined
|
|
96
|
+
? 'flex-1 md:overflow-hidden md:rounded-radius-28 md:border md:border-border'
|
|
97
|
+
: framed
|
|
98
|
+
? 'flex-1 overflow-hidden rounded-radius-28 border border-border'
|
|
99
|
+
: 'flex-1';
|
|
100
|
+
const surfaceClass = [surfaceBase, surfaceClassName ?? 'bg-card'].join(' ');
|
|
82
101
|
const contentClass = ['flex-1', contentClassName].filter(Boolean).join(' ');
|
|
83
102
|
|
|
84
103
|
return (
|
|
@@ -23,16 +23,29 @@
|
|
|
23
23
|
* content rather than displacing it). They render BEFORE the content wrapper so
|
|
24
24
|
* z-index — not DOM order — decides layering.
|
|
25
25
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
26
|
+
* Framing is tri-state via the `framed` prop:
|
|
27
|
+
*
|
|
28
|
+
* - `undefined` (DEFAULT) → RESPONSIVE, driven purely by NativeWind: full-bleed
|
|
29
|
+
* below `md`, framed at `md`+. The rounding is `md:`-gated and both overlays
|
|
30
|
+
* are always rendered but carry `max-md:hidden` (`display:none` below `md`),
|
|
31
|
+
* so the breakpoint is decided in CSS — no consumer JS breakpoint hook.
|
|
32
|
+
* - `false` → NEVER framed (full-bleed at every size): a single flat surface,
|
|
33
|
+
* no rounding, no overlays.
|
|
34
|
+
* - `true` → ALWAYS framed (rounded + overlays at every size).
|
|
35
|
+
*
|
|
36
|
+
* The overlays are gated by VISIBILITY (a `max-md:hidden` literal) rather than
|
|
37
|
+
* by conditional mounting for the responsive case, so crossing the breakpoint
|
|
38
|
+
* never remounts them. The content wrapper likewise keeps a stable `key` so
|
|
39
|
+
* `{children}` reconciles in place across the breakpoint instead of remounting
|
|
40
|
+
* (which would reset feed scroll / the virtualizer + refetch).
|
|
28
41
|
*
|
|
29
42
|
* Native bundlers use `./index.tsx` (a plain rounded surface); web bundlers
|
|
30
43
|
* select this file via the `"browser"` export condition in `package.json`.
|
|
31
44
|
*
|
|
32
45
|
* Styling is NativeWind-className-first; the literal class strings below MUST
|
|
33
46
|
* stay literal so a consumer's Tailwind content-scan over `lib/**` picks them up
|
|
34
|
-
* (no dynamic concatenation of the arbitrary `web:[…]` / `rounded-radius-28`
|
|
35
|
-
* parts).
|
|
47
|
+
* (no dynamic concatenation of the arbitrary `web:[…]` / `rounded-radius-28` /
|
|
48
|
+
* `md:` parts — whole class strings are selected per mode instead).
|
|
36
49
|
*/
|
|
37
50
|
import React, { memo } from 'react';
|
|
38
51
|
import { View, type StyleProp, type ViewStyle } from 'react-native';
|
|
@@ -52,8 +65,15 @@ export const PANEL_BOTTOM_INSET = 8;
|
|
|
52
65
|
|
|
53
66
|
export interface ContentPanelProps {
|
|
54
67
|
children: React.ReactNode;
|
|
55
|
-
/**
|
|
56
|
-
|
|
68
|
+
/**
|
|
69
|
+
* Framing mode. Tri-state, resolved purely with NativeWind — no consumer
|
|
70
|
+
* breakpoint hook needed:
|
|
71
|
+
* - `undefined` (DEFAULT) → responsive: full-bleed below `md`, framed at
|
|
72
|
+
* `md`+ (rounded corners + sticky bleed-mask/border overlays).
|
|
73
|
+
* - `false` → never framed (full-bleed at every size).
|
|
74
|
+
* - `true` → always framed (rounded + overlays at every size).
|
|
75
|
+
*/
|
|
76
|
+
framed?: boolean;
|
|
57
77
|
/** Override the surface background utility (defaults to `bg-card`). */
|
|
58
78
|
surfaceClassName?: string;
|
|
59
79
|
surfaceStyle?: StyleProp<ViewStyle>;
|
|
@@ -83,17 +103,32 @@ const ContentPanelComponent: React.FC<ContentPanelProps> = ({
|
|
|
83
103
|
showStickyFrame,
|
|
84
104
|
maskColor,
|
|
85
105
|
}) => {
|
|
86
|
-
// Dev-only invariant — must run unconditionally before
|
|
87
|
-
//
|
|
106
|
+
// Dev-only invariant — must run unconditionally (before deriving any
|
|
107
|
+
// mode-specific branch) so the hook order stays stable (rules of hooks).
|
|
88
108
|
useContentPanelNestingGuard();
|
|
89
109
|
const { colors } = useTheme();
|
|
90
110
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
111
|
+
// Tri-state: `undefined` → responsive (md:-gated), `true` → always framed,
|
|
112
|
+
// `false` → never framed (full-bleed).
|
|
113
|
+
const responsive = framed === undefined;
|
|
114
|
+
const showOverlays = framed !== false;
|
|
115
|
+
|
|
116
|
+
// Whole literal class strings selected per mode (the Tailwind content-scan
|
|
117
|
+
// over `lib/**` requires each arbitrary/`md:`/`web:` token stay literal).
|
|
118
|
+
// `web:md:overflow-x-clip` is platform-first-then-breakpoint, matching the
|
|
119
|
+
// consumer convention (`web:sm:flex` in `@mercaria/ui`).
|
|
120
|
+
const surfaceBase = responsive
|
|
121
|
+
? 'flex-1 md:rounded-radius-28'
|
|
122
|
+
: framed
|
|
123
|
+
? 'flex-1 rounded-radius-28'
|
|
124
|
+
: 'flex-1';
|
|
125
|
+
const contentBase = responsive
|
|
126
|
+
? 'flex-1 md:rounded-radius-28 web:md:overflow-x-clip'
|
|
127
|
+
: framed
|
|
128
|
+
? 'flex-1 rounded-radius-28 web:overflow-x-clip'
|
|
129
|
+
: 'flex-1';
|
|
130
|
+
const surfaceClass = [surfaceBase, surfaceClassName ?? 'bg-card'].join(' ');
|
|
131
|
+
const contentClass = [contentBase, contentClassName].filter(Boolean).join(' ');
|
|
97
132
|
|
|
98
133
|
return (
|
|
99
134
|
<ContentPanelNestingContext.Provider value={true}>
|
|
@@ -101,26 +136,31 @@ const ContentPanelComponent: React.FC<ContentPanelProps> = ({
|
|
|
101
136
|
{...({ className: surfaceClass } as Record<string, string>)}
|
|
102
137
|
style={surfaceStyle}
|
|
103
138
|
>
|
|
104
|
-
{/* (1) Bleed-mask overlay — gutter box-shadow ring, below chrome.
|
|
105
|
-
|
|
139
|
+
{/* (1) Bleed-mask overlay — gutter box-shadow ring, below chrome. Not
|
|
140
|
+
rendered when never-framed; `max-md:hidden` (display:none <md) when
|
|
141
|
+
responsive, so the breakpoint is decided in CSS, not by remounting. */}
|
|
142
|
+
{showOverlays && (
|
|
106
143
|
<View
|
|
107
144
|
key="bleed-mask"
|
|
108
145
|
pointerEvents="none"
|
|
109
146
|
{...({
|
|
110
|
-
className:
|
|
111
|
-
'web:sticky web:top-2 z-30 h-[calc(100dvh-16px)] w-full rounded-radius-28 web:[margin-bottom:calc(-100dvh+16px)] web:[clip-path:inset(-12px)]'
|
|
147
|
+
className: responsive
|
|
148
|
+
? 'web:sticky web:top-2 z-30 h-[calc(100dvh-16px)] w-full rounded-radius-28 max-md:hidden web:[margin-bottom:calc(-100dvh+16px)] web:[clip-path:inset(-12px)]'
|
|
149
|
+
: 'web:sticky web:top-2 z-30 h-[calc(100dvh-16px)] w-full rounded-radius-28 web:[margin-bottom:calc(-100dvh+16px)] web:[clip-path:inset(-12px)]',
|
|
112
150
|
} as Record<string, string>)}
|
|
113
151
|
style={{ boxShadow: `0 0 0 ${GUTTER_MASK_SPREAD}px ${maskColor ?? colors.background}` }}
|
|
114
152
|
/>
|
|
115
153
|
)}
|
|
116
|
-
{/* (2) Border-frame overlay — one continuous rounded border, above all.
|
|
117
|
-
|
|
154
|
+
{/* (2) Border-frame overlay — one continuous rounded border, above all.
|
|
155
|
+
Same visibility gating as the bleed-mask. */}
|
|
156
|
+
{showOverlays && showStickyFrame !== false && (
|
|
118
157
|
<View
|
|
119
158
|
key="border-frame"
|
|
120
159
|
pointerEvents="none"
|
|
121
160
|
{...({
|
|
122
|
-
className:
|
|
123
|
-
'web:sticky web:top-2 z-[120] h-[calc(100dvh-16px)] w-full rounded-radius-28 border border-border web:[margin-bottom:calc(-100dvh+16px)]'
|
|
161
|
+
className: responsive
|
|
162
|
+
? 'web:sticky web:top-2 z-[120] h-[calc(100dvh-16px)] w-full rounded-radius-28 border border-border max-md:hidden web:[margin-bottom:calc(-100dvh+16px)]'
|
|
163
|
+
: 'web:sticky web:top-2 z-[120] h-[calc(100dvh-16px)] w-full rounded-radius-28 border border-border web:[margin-bottom:calc(-100dvh+16px)]',
|
|
124
164
|
} as Record<string, string>)}
|
|
125
165
|
/>
|
|
126
166
|
)}
|