react-native-terra-ui 0.3.0 → 0.4.1
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/CHANGELOG.md +26 -0
- package/lib/module/components/screen/Screen.js +4 -1
- package/lib/module/components/screen/Screen.js.map +1 -1
- package/lib/module/components/screen/ScreenFlashList.js +31 -12
- package/lib/module/components/screen/ScreenFlashList.js.map +1 -1
- package/lib/module/components/screen/ScreenFlatList.js +42 -27
- package/lib/module/components/screen/ScreenFlatList.js.map +1 -1
- package/lib/module/components/screen/ScreenList.js +160 -0
- package/lib/module/components/screen/ScreenList.js.map +1 -0
- package/lib/module/components/screen/ScreenScrollView.js +34 -16
- package/lib/module/components/screen/ScreenScrollView.js.map +1 -1
- package/lib/module/components/screen/index.js +1 -0
- package/lib/module/components/screen/index.js.map +1 -1
- package/lib/module/context/ThemeProvider.js +15 -0
- package/lib/module/context/ThemeProvider.js.map +1 -1
- package/lib/module/context/index.js +1 -1
- package/lib/module/context/index.js.map +1 -1
- package/lib/module/theme/breakpoints.js +29 -0
- package/lib/module/theme/breakpoints.js.map +1 -0
- package/lib/module/theme/index.js +4 -0
- package/lib/module/theme/index.js.map +1 -1
- package/lib/module/theme/registry.js +3 -1
- package/lib/module/theme/registry.js.map +1 -1
- package/lib/module/theme/screen-margin.js +17 -0
- package/lib/module/theme/screen-margin.js.map +1 -0
- package/lib/module/theme/tokens/primitives.js +13 -3
- package/lib/module/theme/tokens/primitives.js.map +1 -1
- package/lib/typescript/src/components/screen/Screen.d.ts +2 -0
- package/lib/typescript/src/components/screen/Screen.d.ts.map +1 -1
- package/lib/typescript/src/components/screen/ScreenFlashList.d.ts.map +1 -1
- package/lib/typescript/src/components/screen/ScreenFlatList.d.ts.map +1 -1
- package/lib/typescript/src/components/screen/ScreenList.d.ts +64 -0
- package/lib/typescript/src/components/screen/ScreenList.d.ts.map +1 -0
- package/lib/typescript/src/components/screen/ScreenScrollView.d.ts.map +1 -1
- package/lib/typescript/src/components/screen/index.d.ts +2 -0
- package/lib/typescript/src/components/screen/index.d.ts.map +1 -1
- package/lib/typescript/src/context/ThemeProvider.d.ts +8 -0
- package/lib/typescript/src/context/ThemeProvider.d.ts.map +1 -1
- package/lib/typescript/src/context/index.d.ts +1 -1
- package/lib/typescript/src/context/index.d.ts.map +1 -1
- package/lib/typescript/src/theme/breakpoints.d.ts +32 -0
- package/lib/typescript/src/theme/breakpoints.d.ts.map +1 -0
- package/lib/typescript/src/theme/index.d.ts +4 -0
- package/lib/typescript/src/theme/index.d.ts.map +1 -1
- package/lib/typescript/src/theme/registry.d.ts.map +1 -1
- package/lib/typescript/src/theme/screen-margin.d.ts +15 -0
- package/lib/typescript/src/theme/screen-margin.d.ts.map +1 -0
- package/lib/typescript/src/theme/tokens/primitives.d.ts +10 -2
- package/lib/typescript/src/theme/tokens/primitives.d.ts.map +1 -1
- package/lib/typescript/src/theme/types.d.ts +9 -3
- package/lib/typescript/src/theme/types.d.ts.map +1 -1
- package/package.json +1 -2
- package/src/components/screen/Screen.tsx +5 -1
- package/src/components/screen/ScreenFlashList.tsx +30 -10
- package/src/components/screen/ScreenFlatList.tsx +43 -25
- package/src/components/screen/ScreenList.tsx +269 -0
- package/src/components/screen/ScreenScrollView.tsx +31 -16
- package/src/components/screen/index.ts +2 -0
- package/src/context/ThemeProvider.tsx +15 -0
- package/src/context/index.ts +1 -1
- package/src/theme/breakpoints.ts +41 -0
- package/src/theme/index.ts +5 -0
- package/src/theme/registry.ts +2 -1
- package/src/theme/screen-margin.ts +26 -0
- package/src/theme/tokens/primitives.ts +13 -3
- package/src/theme/types.ts +12 -2
- package/skills/terra-ui/SKILL.md +0 -193
- package/skills/terra-ui/references/recipes.md +0 -198
- package/skills/terra-ui/references/troubleshooting.md +0 -112
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/theme/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/theme/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAe,CAAC;AAIpD,8EAA8E;AAC9E,MAAM,MAAM,UAAU,GAClB,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,CAAC;AAET,gCAAgC;AAChC,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,KAAK,GACL,KAAK,GACL,MAAM,CAAC;AAEX;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;AAEpE,6DAA6D;AAC7D,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,SAAS,CAAC;AAInD,oEAAoE;AACpE,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAChD,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE9D,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;AAIlE,MAAM,MAAM,eAAe,GACvB,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,aAAa,GACb,aAAa,GACb,aAAa,GACb,UAAU,GACV,UAAU,GACV,UAAU,GACV,SAAS,GACT,SAAS,GACT,SAAS,GACT,UAAU,GACV,UAAU,GACV,UAAU,GACV,SAAS,CAAC;AAEd,MAAM,MAAM,kBAAkB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEzE,MAAM,MAAM,WAAW,GAAG,eAAe,GAAG,kBAAkB,CAAC;AAE/D,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;AAEzE,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,eAAe,CAAC;IAC5B,oBAAoB;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,UAAU;IACzB;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IACvC;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC;IACvD,QAAQ,EAAE,MAAM,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;CAC9C;AAID;;;GAGG;AACH,MAAM,WAAW,UAAU;IAEzB,UAAU,EAAE,MAAM,CAAC;IAEnB,MAAM,EAAE,MAAM,CAAC;IAEf,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,uBAAuB,EAAE,MAAM,CAAC;IAEhC,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,uBAAuB,EAAE,MAAM,CAAC;IAEhC,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IAExB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,yBAAyB,EAAE,MAAM,CAAC;IAClC,0BAA0B,EAAE,MAAM,CAAC;IACnC,4BAA4B,EAAE,MAAM,CAAC;IACrC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,0BAA0B,EAAE,MAAM,CAAC;IACnC,gCAAgC,EAAE,MAAM,CAAC;IACzC,iCAAiC,EAAE,MAAM,CAAC;IAC1C,mCAAmC,EAAE,MAAM,CAAC;IAC5C,0BAA0B,EAAE,MAAM,CAAC;IACnC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,4BAA4B,EAAE,MAAM,CAAC;IACrC,kCAAkC,EAAE,MAAM,CAAC;IAC3C,mCAAmC,EAAE,MAAM,CAAC;IAC5C,qCAAqC,EAAE,MAAM,CAAC;IAC9C,4BAA4B,EAAE,MAAM,CAAC;IAErC,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,0BAA0B,EAAE,MAAM,CAAC;IACnC,uBAAuB,EAAE,MAAM,CAAC;IAChC,8BAA8B,EAAE,MAAM,CAAC;IACvC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,0BAA0B,EAAE,MAAM,CAAC;IAEnC,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,0BAA0B,EAAE,MAAM,CAAC;IACnC,uBAAuB,EAAE,MAAM,CAAC;IAChC,8BAA8B,EAAE,MAAM,CAAC;IACvC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,0BAA0B,EAAE,MAAM,CAAC;IAEnC,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,yBAAyB,EAAE,MAAM,CAAC;IAClC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,6BAA6B,EAAE,MAAM,CAAC;IACtC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,yBAAyB,EAAE,MAAM,CAAC;IAElC,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,uBAAuB,EAAE,MAAM,CAAC;IAChC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,2BAA2B,EAAE,MAAM,CAAC;IACpC,gBAAgB,EAAE,MAAM,CAAC;IACzB,uBAAuB,EAAE,MAAM,CAAC;CACjC;AAID,6DAA6D;AAC7D,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,kCAAkC;AAClC,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE;QACN;;;;;WAKG;QACH,MAAM,EAAE;YACN,CAAC,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;YAClC,CAAC,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;SACnC,CAAC;KACH,CAAC;IACF,MAAM,EAAE;QACN,kFAAkF;QAClF,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,yEAAyE;AACzE,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACpC,MAAM,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAClC,UAAU,EAAE,UAAU,CAAC;IACvB,SAAS,EAAE,cAAc,CAAC;IAC1B,OAAO,EAAE,aAAa,CAAC;IACvB,MAAM,EAAE,YAAY,CAAC;CACtB;AAID,MAAM,MAAM,oBAAoB,GAAG,YAAY,CAAC;AAChD,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC,MAAM,UAAU,EAAE,WAAW,MAAM,EAAE,CAAC,CAAC;AAC/E,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,UAAU,EAAE,QAAQ,MAAM,EAAE,CAAC,CAAC;AACzE,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAAC,MAAM,UAAU,EAAE,UAAU,MAAM,EAAE,CAAC,CAAC;AAC7E,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAAC,MAAM,UAAU,EAAE,UAAU,MAAM,EAAE,CAAC,CAAC;AAC7E,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAAC,MAAM,UAAU,EAAE,UAAU,MAAM,EAAE,CAAC,CAAC;AAE7E,gGAAgG;AAChG,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC;AAE/C;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAClB,oBAAoB,GACpB,iBAAiB,GACjB,cAAc,GACd,gBAAgB,GAChB,gBAAgB,GAChB,gBAAgB,GAEhB,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAIlB,MAAM,MAAM,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAEtC,8EAA8E;AAC9E,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,gDAAgD;AAChD,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;CAChC;AAED,kDAAkD;AAClD,MAAM,MAAM,MAAM,GAAG,eAAe,GAAG,cAAc,CAAC;AAEtD,wEAAwE;AACxE,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;IAC/B,IAAI,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,kBAAkB,GAAG,aAAa,CAAC,cAAc,CAAC,CAAC;AAI/D,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAEhE,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC;IACjC,KAAK,CAAC,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;IAC9B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,UAAU,CAAC,EAAE,oBAAoB,CAAC;IAClC,oEAAoE;IACpE,WAAW,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC;IACvC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,MAAM,MAAM,mBAAmB,GAAG,aAAa,CAAC,eAAe,CAAC,CAAC;AAEjE,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO,CAAC;QAChB,UAAU,YAAY;SAAG;KAC1B;CACF;AAED,MAAM,WAAW,iBAAkB,SAAQ,OAAO,CAAC,YAAY;CAAG;AAElE,MAAM,MAAM,qBAAqB,GAC7B,iBAAiB,GACjB,oBAAoB,GACpB,kBAAkB,GAClB,aAAa,GACb,gBAAgB,GAChB,gBAAgB,GAChB,eAAe,GACf,QAAQ,CAAC;AAEb,MAAM,MAAM,uBAAuB,GAAG,MAAM,iBAAiB,GAAG,MAAM,CAAC;AAEvE,MAAM,MAAM,aAAa,GAAG,qBAAqB,GAAG,uBAAuB,CAAC;AAE5E,MAAM,MAAM,mBAAmB,GAAG,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,GAAG;IACpE;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,WAAW,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,GAAG;IACtE;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,iDAAiD;AACjD,MAAM,MAAM,kBAAkB,GAAG,WAAW,CAC1C,IAAI,CAAC,UAAU,EAAE,QAAQ,GAAG,SAAS,CAAC,CACvC,GAAG;IACF,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,OAAO,CAAC,EAAE,oBAAoB,CAAC;CAChC,CAAC;AAEF,8EAA8E;AAC9E,MAAM,WAAW,cAAc;IAC7B,iDAAiD;IACjD,MAAM,CAAC,EAAE,kBAAkB,CAAC;CAC7B;AAED,+EAA+E;AAC/E,MAAM,WAAW,eAAe;IAC9B,iDAAiD;IACjD,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,8EAA8E;IAC9E,SAAS,CAAC,EAAE,YAAY,CAAC;CAC1B;AAED,6DAA6D;AAC7D,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,OAAO,CAAC,EAAE,eAAe,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,8EAA8E;IAC9E,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,0DAA0D;IAC1D,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,kBAAkB,CAAC;QAAC,IAAI,CAAC,EAAE,kBAAkB,CAAA;KAAE,CAAC;IACpE,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,kBAAkB,CAAC,CAAC,CAAC;IAC3D;;;;OAIG;IACH,KAAK,CAAC,EAAE,mBAAmB,CAAC;IAC5B,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,sDAAsD;IACtD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,2DAA2D;IAC3D,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-terra-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Themeable React Native UI components built on react-native-unistyles",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
"files": [
|
|
22
22
|
"src",
|
|
23
23
|
"lib",
|
|
24
|
-
"skills",
|
|
25
24
|
"CHANGELOG.md",
|
|
26
25
|
"!**/__tests__",
|
|
27
26
|
"!**/__fixtures__",
|
|
@@ -19,6 +19,7 @@ import { PortalProvider } from '../portal';
|
|
|
19
19
|
import { ScreenScrollProvider } from './ScreenContext';
|
|
20
20
|
import { ScreenFlashList } from './ScreenFlashList';
|
|
21
21
|
import { ScreenFlatList } from './ScreenFlatList';
|
|
22
|
+
import { ScreenList } from './ScreenList';
|
|
22
23
|
import { ScreenScrollView } from './ScreenScrollView';
|
|
23
24
|
import type { ScreenMargins } from './types';
|
|
24
25
|
|
|
@@ -96,12 +97,14 @@ type ScreenComponent = ReturnType<
|
|
|
96
97
|
ScrollView: typeof ScreenScrollView;
|
|
97
98
|
FlatList: typeof ScreenFlatList;
|
|
98
99
|
FlashList: typeof ScreenFlashList;
|
|
100
|
+
List: typeof ScreenList;
|
|
99
101
|
};
|
|
100
102
|
|
|
101
103
|
/**
|
|
102
104
|
* Themed page container: solid themed background, safe-area handling, and a
|
|
103
105
|
* shared scroll context for headers. Pair with `Screen.ScrollView` /
|
|
104
|
-
* `Screen.
|
|
106
|
+
* `Screen.List` (or `Screen.FlatList` / `Screen.FlashList` directly) and a
|
|
107
|
+
* `Header.LargeTitle` / `Header.Title`.
|
|
105
108
|
*
|
|
106
109
|
* @example
|
|
107
110
|
* ```tsx
|
|
@@ -139,6 +142,7 @@ ScreenBase.Header = ScreenHeader;
|
|
|
139
142
|
ScreenBase.ScrollView = ScreenScrollView;
|
|
140
143
|
ScreenBase.FlatList = ScreenFlatList;
|
|
141
144
|
ScreenBase.FlashList = ScreenFlashList;
|
|
145
|
+
ScreenBase.List = ScreenList;
|
|
142
146
|
|
|
143
147
|
export const Screen = ScreenBase;
|
|
144
148
|
|
|
@@ -12,6 +12,7 @@ import Animated, {
|
|
|
12
12
|
|
|
13
13
|
import { StyleSheet } from 'react-native-unistyles';
|
|
14
14
|
|
|
15
|
+
import { resolveScreenMargin } from '#theme/screen-margin';
|
|
15
16
|
import { PortalHost } from '../portal';
|
|
16
17
|
import { BottomSafeArea } from './parts/BottomSafeArea';
|
|
17
18
|
import { renderScreenPlaceholder } from './parts/ScreenPlaceholder';
|
|
@@ -136,10 +137,17 @@ export function ScreenFlashList<T>({
|
|
|
136
137
|
);
|
|
137
138
|
|
|
138
139
|
const headerComponent = (
|
|
139
|
-
|
|
140
|
-
|
|
140
|
+
<>
|
|
141
|
+
{/* `headerWrapper`'s negative margin cancels the list's inherited
|
|
142
|
+
content padding for the portaled header (`LargeTitlePortalContent`
|
|
143
|
+
etc. manage their own horizontal padding) — a caller's own
|
|
144
|
+
`ListHeaderComponent` has no such self-padding, so it stays outside
|
|
145
|
+
this wrapper and gets the list's normal item padding instead. */}
|
|
146
|
+
<View style={styles.headerWrapper(resolvedMargins)}>
|
|
147
|
+
<PortalHost name={SCREEN_HEADER_PORTAL_HOST} />
|
|
148
|
+
</View>
|
|
141
149
|
{renderListHeader(ListHeaderComponent)}
|
|
142
|
-
|
|
150
|
+
</>
|
|
143
151
|
);
|
|
144
152
|
|
|
145
153
|
return (
|
|
@@ -164,12 +172,22 @@ export function ScreenFlashList<T>({
|
|
|
164
172
|
);
|
|
165
173
|
}
|
|
166
174
|
|
|
175
|
+
// `resolveScreenMargin` is called *inside* each dynamic function below, not
|
|
176
|
+
// hoisted to the factory's top level — the Babel plugin only attributes a
|
|
177
|
+
// runtime dependency (here, breakpoint) to a style key when the `rt`/
|
|
178
|
+
// `runtime` read it derives from sits inside that key's own value. Hoisting
|
|
179
|
+
// it would silently drop the dependency, so the margin would freeze at
|
|
180
|
+
// whatever breakpoint was active on mount and never update on rotation.
|
|
167
181
|
const styles = StyleSheet.create((theme, runtime) => ({
|
|
168
182
|
content: (
|
|
169
183
|
margins: ScreenMargins,
|
|
170
184
|
hasHeader: boolean,
|
|
171
185
|
bottomInset: number | undefined
|
|
172
186
|
) => {
|
|
187
|
+
const { x: marginX, y: marginY } = resolveScreenMargin(
|
|
188
|
+
theme,
|
|
189
|
+
runtime.breakpoint
|
|
190
|
+
);
|
|
173
191
|
return {
|
|
174
192
|
flexGrow: 1,
|
|
175
193
|
// The header is absolutely positioned, so the list reserves its full
|
|
@@ -179,18 +197,20 @@ const styles = StyleSheet.create((theme, runtime) => ({
|
|
|
179
197
|
// insets are counted twice.
|
|
180
198
|
paddingTop:
|
|
181
199
|
(hasHeader ? theme.layout.header.height + runtime.insets.top : 0) +
|
|
182
|
-
(hasYMargin(margins) ?
|
|
183
|
-
paddingHorizontal: hasXMargin(margins) ?
|
|
200
|
+
(hasYMargin(margins) ? marginY : 0),
|
|
201
|
+
paddingHorizontal: hasXMargin(margins) ? marginX : 0,
|
|
184
202
|
// The safe area is `BottomSafeArea`'s job; counting it here as well
|
|
185
203
|
// would leave a gap the height of the gesture bar.
|
|
186
|
-
paddingBottom:
|
|
187
|
-
bottomInset ?? (hasYMargin(margins) ? theme.layout.screen.margin.y : 0),
|
|
204
|
+
paddingBottom: bottomInset ?? (hasYMargin(margins) ? marginY : 0),
|
|
188
205
|
};
|
|
189
206
|
},
|
|
190
207
|
safeArea: {
|
|
191
208
|
height: runtime.insets.top,
|
|
192
209
|
},
|
|
193
|
-
headerWrapper: (margins: ScreenMargins) =>
|
|
194
|
-
|
|
195
|
-
|
|
210
|
+
headerWrapper: (margins: ScreenMargins) => {
|
|
211
|
+
const { x: marginX } = resolveScreenMargin(theme, runtime.breakpoint);
|
|
212
|
+
return {
|
|
213
|
+
marginHorizontal: hasXMargin(margins) ? -marginX : 0,
|
|
214
|
+
};
|
|
215
|
+
},
|
|
196
216
|
}));
|
|
@@ -12,6 +12,7 @@ import Animated, {
|
|
|
12
12
|
} from 'react-native-reanimated';
|
|
13
13
|
import { StyleSheet } from 'react-native-unistyles';
|
|
14
14
|
|
|
15
|
+
import { resolveScreenMargin } from '#theme/screen-margin';
|
|
15
16
|
import { PortalHost } from '../portal';
|
|
16
17
|
import { BottomSafeArea } from './parts/BottomSafeArea';
|
|
17
18
|
import { renderScreenPlaceholder } from './parts/ScreenPlaceholder';
|
|
@@ -116,11 +117,17 @@ export function ScreenFlatList<T>({
|
|
|
116
117
|
);
|
|
117
118
|
|
|
118
119
|
const headerComponent = (
|
|
119
|
-
|
|
120
|
-
{
|
|
121
|
-
|
|
120
|
+
<>
|
|
121
|
+
{/* `headerWrapper`'s negative margin cancels the list's inherited
|
|
122
|
+
content padding for the portaled header (`LargeTitlePortalContent`
|
|
123
|
+
etc. manage their own horizontal padding) — a caller's own
|
|
124
|
+
`ListHeaderComponent` has no such self-padding, so it stays outside
|
|
125
|
+
this wrapper and gets the list's normal item padding instead. */}
|
|
126
|
+
<View style={styles.headerWrapper(resolvedMargins)}>
|
|
127
|
+
<PortalHost name={SCREEN_HEADER_PORTAL_HOST} />
|
|
128
|
+
</View>
|
|
122
129
|
{renderListHeader(ListHeaderComponent)}
|
|
123
|
-
|
|
130
|
+
</>
|
|
124
131
|
);
|
|
125
132
|
|
|
126
133
|
return (
|
|
@@ -146,6 +153,12 @@ export function ScreenFlatList<T>({
|
|
|
146
153
|
);
|
|
147
154
|
}
|
|
148
155
|
|
|
156
|
+
// `resolveScreenMargin` is called *inside* each dynamic function below, not
|
|
157
|
+
// hoisted to the factory's top level — the Babel plugin only attributes a
|
|
158
|
+
// runtime dependency (here, breakpoint) to a style key when the `rt`/
|
|
159
|
+
// `runtime` read it derives from sits inside that key's own value. Hoisting
|
|
160
|
+
// it would silently drop the dependency, so the margin would freeze at
|
|
161
|
+
// whatever breakpoint was active on mount and never update on rotation.
|
|
149
162
|
const styles = StyleSheet.create((theme, runtime) => ({
|
|
150
163
|
scrollContent: {
|
|
151
164
|
flexGrow: 1,
|
|
@@ -154,29 +167,34 @@ const styles = StyleSheet.create((theme, runtime) => ({
|
|
|
154
167
|
margins: ScreenMargins,
|
|
155
168
|
hasHeader: boolean,
|
|
156
169
|
bottomInset: number | undefined
|
|
157
|
-
) =>
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
170
|
+
) => {
|
|
171
|
+
const { x: marginX, y: marginY } = resolveScreenMargin(
|
|
172
|
+
theme,
|
|
173
|
+
runtime.breakpoint
|
|
174
|
+
);
|
|
175
|
+
return {
|
|
176
|
+
flexGrow: 1,
|
|
177
|
+
// The header is absolutely positioned, so the list reserves its full
|
|
178
|
+
// height — bar plus top safe area. This assumes the scroll view does not
|
|
179
|
+
// also get UIKit's automatic inset adjustment: on a native tab screen
|
|
180
|
+
// that means `disableAutomaticContentInsets` on the tab, or the two
|
|
181
|
+
// insets are counted twice.
|
|
182
|
+
paddingTop:
|
|
183
|
+
(hasHeader ? theme.layout.header.height + runtime.insets.top : 0) +
|
|
184
|
+
(hasYMargin(margins) ? marginY : 0),
|
|
185
|
+
paddingHorizontal: hasXMargin(margins) ? marginX : 0,
|
|
186
|
+
// The safe area is `BottomSafeArea`'s job; counting it here as well
|
|
187
|
+
// would leave a gap the height of the gesture bar.
|
|
188
|
+
paddingBottom: bottomInset ?? (hasYMargin(margins) ? marginY : 0),
|
|
189
|
+
};
|
|
190
|
+
},
|
|
173
191
|
safeArea: {
|
|
174
192
|
height: runtime.insets.top,
|
|
175
193
|
},
|
|
176
|
-
headerWrapper: (margins: ScreenMargins) =>
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
194
|
+
headerWrapper: (margins: ScreenMargins) => {
|
|
195
|
+
const { x: marginX } = resolveScreenMargin(theme, runtime.breakpoint);
|
|
196
|
+
return {
|
|
197
|
+
marginHorizontal: hasXMargin(margins) ? -marginX : 0,
|
|
198
|
+
};
|
|
181
199
|
},
|
|
182
200
|
}));
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type ComponentPropsWithoutRef,
|
|
3
|
+
type ComponentType,
|
|
4
|
+
type ElementType,
|
|
5
|
+
type ReactElement,
|
|
6
|
+
useMemo,
|
|
7
|
+
} from 'react';
|
|
8
|
+
import {
|
|
9
|
+
FlatList,
|
|
10
|
+
type NativeScrollEvent,
|
|
11
|
+
type NativeSyntheticEvent,
|
|
12
|
+
type StyleProp,
|
|
13
|
+
View,
|
|
14
|
+
type ViewStyle,
|
|
15
|
+
} from 'react-native';
|
|
16
|
+
|
|
17
|
+
import Animated, {
|
|
18
|
+
type AnimatedRef,
|
|
19
|
+
useAnimatedScrollHandler,
|
|
20
|
+
useComposedEventHandler,
|
|
21
|
+
} from 'react-native-reanimated';
|
|
22
|
+
import { StyleSheet } from 'react-native-unistyles';
|
|
23
|
+
|
|
24
|
+
import { resolveScreenMargin } from '#theme/screen-margin';
|
|
25
|
+
import { PortalHost } from '../portal';
|
|
26
|
+
import { BottomSafeArea } from './parts/BottomSafeArea';
|
|
27
|
+
import { renderScreenPlaceholder } from './parts/ScreenPlaceholder';
|
|
28
|
+
import { SCREEN_HEADER_PORTAL_HOST, useScreen } from './ScreenContext';
|
|
29
|
+
import type { ScreenMargins, ScreenScrollableProps } from './types';
|
|
30
|
+
import {
|
|
31
|
+
hasXMargin,
|
|
32
|
+
hasYMargin,
|
|
33
|
+
type ListHeaderComponent,
|
|
34
|
+
renderListHeader,
|
|
35
|
+
} from './utils';
|
|
36
|
+
|
|
37
|
+
export interface ScreenListRenderItemInfo<T> {
|
|
38
|
+
item: T;
|
|
39
|
+
index: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export type ScreenListProps<
|
|
43
|
+
T = unknown,
|
|
44
|
+
As extends ElementType = typeof FlatList,
|
|
45
|
+
> = ScreenScrollableProps &
|
|
46
|
+
Omit<
|
|
47
|
+
ComponentPropsWithoutRef<As>,
|
|
48
|
+
| 'data'
|
|
49
|
+
| 'renderItem'
|
|
50
|
+
| 'keyExtractor'
|
|
51
|
+
| 'style'
|
|
52
|
+
| 'contentContainerStyle'
|
|
53
|
+
| 'onScroll'
|
|
54
|
+
| 'ListHeaderComponent'
|
|
55
|
+
| 'ListFooterComponent'
|
|
56
|
+
| 'ListEmptyComponent'
|
|
57
|
+
| keyof ScreenScrollableProps
|
|
58
|
+
> & {
|
|
59
|
+
/**
|
|
60
|
+
* Which list component to render as. Defaults to React Native's
|
|
61
|
+
* `FlatList` — pass any list with a FlatList-shaped prop surface
|
|
62
|
+
* (`data`, `renderItem`, `ListHeaderComponent`, …), e.g. `FlashList`
|
|
63
|
+
* from `@shopify/flash-list`, or a custom virtualized list.
|
|
64
|
+
*
|
|
65
|
+
* Only the default `FlatList` binds the screen's shared imperative
|
|
66
|
+
* scroll ref — a custom `as` is responsible for its own ref if it needs
|
|
67
|
+
* one, since not every list exposes a Reanimated-compatible ref (this is
|
|
68
|
+
* why `Screen.FlashList` doesn't bind it either).
|
|
69
|
+
*/
|
|
70
|
+
as?: As;
|
|
71
|
+
data?: readonly T[] | null;
|
|
72
|
+
renderItem?: (info: ScreenListRenderItemInfo<T>) => ReactElement | null;
|
|
73
|
+
keyExtractor?: (item: T, index: number) => string;
|
|
74
|
+
ListHeaderComponent?: ListHeaderComponent;
|
|
75
|
+
ListFooterComponent?: ListHeaderComponent;
|
|
76
|
+
ListEmptyComponent?: ListHeaderComponent;
|
|
77
|
+
style?: StyleProp<ViewStyle>;
|
|
78
|
+
contentContainerStyle?: StyleProp<ViewStyle>;
|
|
79
|
+
onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
|
|
80
|
+
/**
|
|
81
|
+
* Extra bottom padding on the list content — clearance for a tab bar or
|
|
82
|
+
* home indicator. Defaults to the `layout.screen.margin.y` token when
|
|
83
|
+
* margins are enabled, otherwise `0`.
|
|
84
|
+
*/
|
|
85
|
+
bottomInset?: number;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Polymorphic list container — renders whichever list `as` names (defaults
|
|
90
|
+
* to `FlatList`), applying the same margin/header/safe-area/scroll-handler
|
|
91
|
+
* chrome regardless of which one it is. A screen can swap list
|
|
92
|
+
* implementations by changing `as`, without relearning the surrounding API.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```tsx
|
|
96
|
+
* <Screen.List data={items} renderItem={({ item }) => <Row item={item} />} />
|
|
97
|
+
* ```
|
|
98
|
+
*
|
|
99
|
+
* @example Any other list component
|
|
100
|
+
* ```tsx
|
|
101
|
+
* import { FlashList } from '@shopify/flash-list';
|
|
102
|
+
*
|
|
103
|
+
* <Screen.List
|
|
104
|
+
* as={FlashList}
|
|
105
|
+
* data={items}
|
|
106
|
+
* renderItem={({ item }) => <Row item={item} />}
|
|
107
|
+
* />
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
export function ScreenList<
|
|
111
|
+
T = unknown,
|
|
112
|
+
As extends ElementType = typeof FlatList,
|
|
113
|
+
>({
|
|
114
|
+
as,
|
|
115
|
+
data,
|
|
116
|
+
renderItem,
|
|
117
|
+
style,
|
|
118
|
+
contentContainerStyle,
|
|
119
|
+
ListHeaderComponent,
|
|
120
|
+
ListFooterComponent,
|
|
121
|
+
ListEmptyComponent,
|
|
122
|
+
horizontal = false,
|
|
123
|
+
loading = false,
|
|
124
|
+
LoadingComponent,
|
|
125
|
+
EmptyComponent,
|
|
126
|
+
margins,
|
|
127
|
+
bottomInset,
|
|
128
|
+
onScroll,
|
|
129
|
+
...rest
|
|
130
|
+
}: ScreenListProps<T, As>) {
|
|
131
|
+
const isDefaultFlatList = as === undefined;
|
|
132
|
+
const Component = (as ?? FlatList) as ComponentType<Record<string, unknown>>;
|
|
133
|
+
|
|
134
|
+
// `Animated.createAnimatedComponent` should only run once per component,
|
|
135
|
+
// not on every render — `as` is arbitrary here (not a fixed module-scope
|
|
136
|
+
// reference like `Screen.FlatList`/`Screen.FlashList` use), so it's
|
|
137
|
+
// memoized on the resolved component instead of hoisted to module scope.
|
|
138
|
+
const AnimatedComponent = useMemo(
|
|
139
|
+
() => Animated.createAnimatedComponent(Component),
|
|
140
|
+
[Component]
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
const {
|
|
144
|
+
background,
|
|
145
|
+
scrollRef,
|
|
146
|
+
scrollHandler,
|
|
147
|
+
headerSnapOffsets,
|
|
148
|
+
margins: screenMargins,
|
|
149
|
+
hasHeader,
|
|
150
|
+
} = useScreen();
|
|
151
|
+
|
|
152
|
+
const resolvedMargins = margins ?? screenMargins;
|
|
153
|
+
// The placeholder rides in on `ListEmptyComponent` rather than replacing the
|
|
154
|
+
// list, so the header portal, scroll binding and snap offsets all stay put.
|
|
155
|
+
// While loading the list is fed an empty `data` so that slot is the one that
|
|
156
|
+
// renders.
|
|
157
|
+
const placeholder = renderScreenPlaceholder({
|
|
158
|
+
loading,
|
|
159
|
+
LoadingComponent,
|
|
160
|
+
EmptyComponent,
|
|
161
|
+
isEmpty: !data || data.length === 0,
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
const jsScrollHandler = useAnimatedScrollHandler(
|
|
165
|
+
(event) => {
|
|
166
|
+
if (onScroll)
|
|
167
|
+
onScroll(event as unknown as NativeSyntheticEvent<NativeScrollEvent>);
|
|
168
|
+
},
|
|
169
|
+
[onScroll]
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
const composedHandler = useComposedEventHandler([
|
|
173
|
+
scrollHandler,
|
|
174
|
+
jsScrollHandler,
|
|
175
|
+
]);
|
|
176
|
+
|
|
177
|
+
// A caller naming its own `bottomInset` has taken the bottom over entirely,
|
|
178
|
+
// and a horizontal list has no bottom edge to clear.
|
|
179
|
+
const needsBottomSafeArea = bottomInset === undefined && !horizontal;
|
|
180
|
+
|
|
181
|
+
const footerComponent = (
|
|
182
|
+
<>
|
|
183
|
+
{renderListHeader(ListFooterComponent)}
|
|
184
|
+
{needsBottomSafeArea ? <BottomSafeArea /> : null}
|
|
185
|
+
</>
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
const headerComponent = (
|
|
189
|
+
<>
|
|
190
|
+
{/* `headerWrapper`'s negative margin cancels the list's inherited
|
|
191
|
+
content padding for the portaled header (`LargeTitlePortalContent`
|
|
192
|
+
etc. manage their own horizontal padding) — a caller's own
|
|
193
|
+
`ListHeaderComponent` has no such self-padding, so it stays outside
|
|
194
|
+
this wrapper and gets the list's normal item padding instead. */}
|
|
195
|
+
<View style={styles.headerWrapper(resolvedMargins)}>
|
|
196
|
+
<PortalHost name={SCREEN_HEADER_PORTAL_HOST} />
|
|
197
|
+
</View>
|
|
198
|
+
{renderListHeader(ListHeaderComponent)}
|
|
199
|
+
</>
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
return (
|
|
203
|
+
<AnimatedComponent
|
|
204
|
+
ref={
|
|
205
|
+
isDefaultFlatList
|
|
206
|
+
? (scrollRef as unknown as AnimatedRef<never>)
|
|
207
|
+
: undefined
|
|
208
|
+
}
|
|
209
|
+
data={loading ? [] : data}
|
|
210
|
+
renderItem={renderItem}
|
|
211
|
+
style={[{ backgroundColor: background }, style]}
|
|
212
|
+
horizontal={horizontal}
|
|
213
|
+
contentInsetAdjustmentBehavior={hasHeader ? 'never' : undefined}
|
|
214
|
+
contentContainerStyle={[
|
|
215
|
+
styles.content(resolvedMargins, hasHeader, bottomInset),
|
|
216
|
+
contentContainerStyle,
|
|
217
|
+
]}
|
|
218
|
+
ListHeaderComponent={headerComponent}
|
|
219
|
+
ListFooterComponent={footerComponent}
|
|
220
|
+
ListEmptyComponent={placeholder ?? ListEmptyComponent}
|
|
221
|
+
showsVerticalScrollIndicator={false}
|
|
222
|
+
scrollEventThrottle={16}
|
|
223
|
+
snapToOffsets={headerSnapOffsets}
|
|
224
|
+
{...rest}
|
|
225
|
+
onScroll={composedHandler}
|
|
226
|
+
/>
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
ScreenList.displayName = 'Screen.List';
|
|
230
|
+
|
|
231
|
+
// `resolveScreenMargin` is called *inside* each dynamic function below, not
|
|
232
|
+
// hoisted to the factory's top level — the Babel plugin only attributes a
|
|
233
|
+
// runtime dependency (here, breakpoint) to a style key when the `rt`/
|
|
234
|
+
// `runtime` read it derives from sits inside that key's own value. Hoisting
|
|
235
|
+
// it would silently drop the dependency, so the margin would freeze at
|
|
236
|
+
// whatever breakpoint was active on mount and never update on rotation.
|
|
237
|
+
const styles = StyleSheet.create((theme, runtime) => ({
|
|
238
|
+
content: (
|
|
239
|
+
margins: ScreenMargins,
|
|
240
|
+
hasHeader: boolean,
|
|
241
|
+
bottomInset: number | undefined
|
|
242
|
+
) => {
|
|
243
|
+
const { x: marginX, y: marginY } = resolveScreenMargin(
|
|
244
|
+
theme,
|
|
245
|
+
runtime.breakpoint
|
|
246
|
+
);
|
|
247
|
+
return {
|
|
248
|
+
flexGrow: 1,
|
|
249
|
+
// The header is absolutely positioned, so the list reserves its full
|
|
250
|
+
// height — bar plus top safe area. This assumes the scroll view does not
|
|
251
|
+
// also get UIKit's automatic inset adjustment: on a native tab screen
|
|
252
|
+
// that means `disableAutomaticContentInsets` on the tab, or the two
|
|
253
|
+
// insets are counted twice.
|
|
254
|
+
paddingTop:
|
|
255
|
+
(hasHeader ? theme.layout.header.height + runtime.insets.top : 0) +
|
|
256
|
+
(hasYMargin(margins) ? marginY : 0),
|
|
257
|
+
paddingHorizontal: hasXMargin(margins) ? marginX : 0,
|
|
258
|
+
// The safe area is `BottomSafeArea`'s job; counting it here as well
|
|
259
|
+
// would leave a gap the height of the gesture bar.
|
|
260
|
+
paddingBottom: bottomInset ?? (hasYMargin(margins) ? marginY : 0),
|
|
261
|
+
};
|
|
262
|
+
},
|
|
263
|
+
headerWrapper: (margins: ScreenMargins) => {
|
|
264
|
+
const { x: marginX } = resolveScreenMargin(theme, runtime.breakpoint);
|
|
265
|
+
return {
|
|
266
|
+
marginHorizontal: hasXMargin(margins) ? -marginX : 0,
|
|
267
|
+
};
|
|
268
|
+
},
|
|
269
|
+
}));
|
|
@@ -13,6 +13,8 @@ import Animated, {
|
|
|
13
13
|
} from 'react-native-reanimated';
|
|
14
14
|
import { StyleSheet } from 'react-native-unistyles';
|
|
15
15
|
import { scheduleOnRN } from 'react-native-worklets';
|
|
16
|
+
|
|
17
|
+
import { resolveScreenMargin } from '#theme/screen-margin';
|
|
16
18
|
import { PortalHost } from '../portal';
|
|
17
19
|
import { BottomSafeArea } from './parts/BottomSafeArea';
|
|
18
20
|
import { renderScreenPlaceholder } from './parts/ScreenPlaceholder';
|
|
@@ -171,21 +173,34 @@ export function ScreenScrollView({
|
|
|
171
173
|
}
|
|
172
174
|
|
|
173
175
|
const styles = StyleSheet.create((theme, rt) => ({
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
176
|
+
// `resolveScreenMargin` is called *inside* each dynamic function, not
|
|
177
|
+
// hoisted above `return` — the Babel plugin only attributes a runtime
|
|
178
|
+
// dependency (here, breakpoint) to a style key when the `rt` read it
|
|
179
|
+
// derives from sits inside that key's own value. Hoisting it to the
|
|
180
|
+
// factory's top level silently drops the dependency, so the margin would
|
|
181
|
+
// freeze at whatever breakpoint was active on mount and never update on
|
|
182
|
+
// rotation.
|
|
183
|
+
scrollContent: (hasHeader: boolean, margins: ScreenMargins) => {
|
|
184
|
+
const { y: marginY } = resolveScreenMargin(theme, rt.breakpoint);
|
|
185
|
+
return {
|
|
186
|
+
flexGrow: 1,
|
|
187
|
+
// The header inset and the safe area are structural — they apply
|
|
188
|
+
// whether or not margins are on; the y margin stacks on top of them.
|
|
189
|
+
paddingTop:
|
|
190
|
+
(hasHeader ? theme.layout.header.height + rt.insets.top : 0) +
|
|
191
|
+
(hasYMargin(margins) ? marginY : 0),
|
|
192
|
+
// The safe area is `BottomSafeArea`'s job; counting it here as well
|
|
193
|
+
// would leave a gap the height of the gesture bar.
|
|
194
|
+
paddingBottom: hasYMargin(margins) ? marginY : 0,
|
|
195
|
+
};
|
|
196
|
+
},
|
|
185
197
|
|
|
186
|
-
content: (horizontal: boolean, margins: ScreenMargins) =>
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
198
|
+
content: (horizontal: boolean, margins: ScreenMargins) => {
|
|
199
|
+
const { x: marginX } = resolveScreenMargin(theme, rt.breakpoint);
|
|
200
|
+
return {
|
|
201
|
+
flexGrow: 1,
|
|
202
|
+
paddingHorizontal: hasXMargin(margins) ? marginX : 0,
|
|
203
|
+
flexDirection: horizontal ? 'row' : 'column',
|
|
204
|
+
};
|
|
205
|
+
},
|
|
191
206
|
}));
|
|
@@ -6,6 +6,8 @@ export type { ScreenFlashListProps } from './ScreenFlashList';
|
|
|
6
6
|
export { ScreenFlashList } from './ScreenFlashList';
|
|
7
7
|
export type { ScreenFlatListProps } from './ScreenFlatList';
|
|
8
8
|
export { ScreenFlatList } from './ScreenFlatList';
|
|
9
|
+
export type { ScreenListProps } from './ScreenList';
|
|
10
|
+
export { ScreenList } from './ScreenList';
|
|
9
11
|
export type { ScreenScrollViewProps } from './ScreenScrollView';
|
|
10
12
|
export { ScreenScrollView } from './ScreenScrollView';
|
|
11
13
|
export type { ScreenMargins, ScreenScrollableProps } from './types';
|
|
@@ -10,6 +10,10 @@ import { SafeAreaProvider } from 'react-native-safe-area-context';
|
|
|
10
10
|
import { useUnistyles } from 'react-native-unistyles';
|
|
11
11
|
import { bootstrapTerraUI } from '../theme/registry';
|
|
12
12
|
import { applyAccent, applyScheme, getCurrentAccent } from '../theme/runtime';
|
|
13
|
+
import {
|
|
14
|
+
type ResolvedScreenMargin,
|
|
15
|
+
resolveScreenMargin,
|
|
16
|
+
} from '../theme/screen-margin';
|
|
13
17
|
import type { Scheme, TerraTheme } from '../theme/types';
|
|
14
18
|
|
|
15
19
|
// Ensure the default theme is registered on first import. An app that calls
|
|
@@ -88,6 +92,17 @@ export function useTheme(): UseThemeResult {
|
|
|
88
92
|
};
|
|
89
93
|
}
|
|
90
94
|
|
|
95
|
+
/**
|
|
96
|
+
* Resolves `theme.layout.screen.margin` for the current runtime breakpoint.
|
|
97
|
+
* For use outside a `StyleSheet.create` factory (e.g. plain-JS layout maths);
|
|
98
|
+
* inside one, call `resolveScreenMargin(theme, rt.breakpoint)` directly so
|
|
99
|
+
* the value stays reactive without a React re-render.
|
|
100
|
+
*/
|
|
101
|
+
export function useScreenMargin(): ResolvedScreenMargin {
|
|
102
|
+
const { theme, rt } = useUnistyles();
|
|
103
|
+
return resolveScreenMargin(theme, rt.breakpoint);
|
|
104
|
+
}
|
|
105
|
+
|
|
91
106
|
const noopSetAccent = (_name: string): void => {
|
|
92
107
|
if (__DEV__) {
|
|
93
108
|
console.warn(
|
package/src/context/index.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export type { UseThemeResult } from './ThemeProvider';
|
|
2
|
-
export { TerraUIProvider, useTheme } from './ThemeProvider';
|
|
2
|
+
export { TerraUIProvider, useScreenMargin, useTheme } from './ThemeProvider';
|