@hzblj/kara-components 0.2.1 → 0.3.0

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.
Files changed (44) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +2 -3
  3. package/lib/module/molecules/navigation-bar/navigation-bar.android.js +65 -35
  4. package/lib/module/molecules/navigation-bar/navigation-bar.android.js.map +1 -1
  5. package/lib/module/molecules/navigation-bar/navigation-bar.ios.js +48 -13
  6. package/lib/module/molecules/navigation-bar/navigation-bar.ios.js.map +1 -1
  7. package/lib/module/organisms/sheet/index.js +2 -1
  8. package/lib/module/organisms/sheet/index.js.map +1 -1
  9. package/lib/module/organisms/sheet/sheet-header.js +7 -0
  10. package/lib/module/organisms/sheet/sheet-header.js.map +1 -0
  11. package/lib/module/organisms/sheet/sheet-scroll.js +62 -0
  12. package/lib/module/organisms/sheet/sheet-scroll.js.map +1 -0
  13. package/lib/module/organisms/sheet/sheet.js +136 -0
  14. package/lib/module/organisms/sheet/sheet.js.map +1 -0
  15. package/lib/module/organisms/sheet/split-sheet-children.js +21 -0
  16. package/lib/module/organisms/sheet/split-sheet-children.js.map +1 -0
  17. package/lib/module/organisms/sheet/use-sheet-header.js +118 -0
  18. package/lib/module/organisms/sheet/use-sheet-header.js.map +1 -0
  19. package/lib/typescript/molecules/navigation-bar/navigation-bar.types.d.ts +56 -17
  20. package/lib/typescript/organisms/sheet/index.d.ts +1 -0
  21. package/lib/typescript/organisms/sheet/sheet-header.d.ts +3 -0
  22. package/lib/typescript/organisms/sheet/sheet-scroll.d.ts +9 -0
  23. package/lib/typescript/organisms/sheet/sheet.d.ts +7 -1
  24. package/lib/typescript/organisms/sheet/sheet.types.d.ts +86 -3
  25. package/lib/typescript/organisms/sheet/split-sheet-children.d.ts +9 -0
  26. package/lib/typescript/organisms/sheet/use-sheet-header.d.ts +24 -0
  27. package/package.json +6 -4
  28. package/src/molecules/navigation-bar/navigation-bar.android.tsx +50 -23
  29. package/src/molecules/navigation-bar/navigation-bar.ios.tsx +54 -15
  30. package/src/molecules/navigation-bar/navigation-bar.types.ts +56 -17
  31. package/src/organisms/sheet/index.ts +1 -0
  32. package/src/organisms/sheet/sheet-header.tsx +6 -0
  33. package/src/organisms/sheet/sheet-scroll.tsx +69 -0
  34. package/src/organisms/sheet/sheet.tsx +140 -0
  35. package/src/organisms/sheet/sheet.types.ts +93 -3
  36. package/src/organisms/sheet/split-sheet-children.ts +23 -0
  37. package/src/organisms/sheet/use-sheet-header.tsx +135 -0
  38. package/lib/module/organisms/sheet/sheet.android.js +0 -26
  39. package/lib/module/organisms/sheet/sheet.android.js.map +0 -1
  40. package/lib/module/organisms/sheet/sheet.ios.js +0 -25
  41. package/lib/module/organisms/sheet/sheet.ios.js.map +0 -1
  42. package/lib/typescript/organisms/sheet/sheet.ios.d.ts +0 -2
  43. package/src/organisms/sheet/sheet.android.tsx +0 -25
  44. package/src/organisms/sheet/sheet.ios.tsx +0 -23
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @hzblj/kara-components
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`f84ffd5`](https://github.com/hzblj/kara-ui/commit/f84ffd52954a5e7052541c8682787137de205a28) Thanks [@hzblj](https://github.com/hzblj)! - Native sheets with a native header. `Sheet` is now a TrueSheet (`@lodev09/react-native-true-sheet`, a new peer dependency) with `<Sheet.Header>` — a real navigation bar with a centred, leading or large title that hands over to the bar as it scrolls away, items on either side, and on iOS 26 the content scrolls under it with the soft edge effect — plus `<Sheet.ScrollView>`, `useSheetScroll`, detents, a footer and a ref (`present`/`dismiss`/`resize`). It is React Native tier now: no host, native atoms inside go in an `Island`. `fitToContents` is replaced by `detents` (`['auto']` by default).
8
+
9
+ `NavigationBar` takes `leadingItems` / `trailingItems` instead of `onBack` / `onClose`: `back`, `close` or an app `icon`, on either side and in any order; on iOS 26 neighbours share a glass capsule unless an item is `separated`. Also `titleAlignment`, `titleVisible`, `inverted` and an iOS `search` field. On Android it is now Material's native top app bar.
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies [[`f84ffd5`](https://github.com/hzblj/kara-ui/commit/f84ffd52954a5e7052541c8682787137de205a28)]:
14
+ - @hzblj/kara-native@0.3.0
15
+ - @hzblj/kara-theme@0.3.0
16
+ - @hzblj/kara-sx@0.3.0
17
+
3
18
  ## 0.2.1
4
19
 
5
20
  ### Patch Changes
package/README.md CHANGED
@@ -1,8 +1,7 @@
1
1
  # @hzblj/kara-components
2
2
 
3
- The atoms, molecules, organisms and templates of kara-ui — real SwiftUI and Jetpack Compose views through `@expo/ui` and the KaraUI module, styled through `sx`.
3
+ The components of kara-ui.
4
4
 
5
- **Install [`@hzblj/kara-ui`](https://www.npmjs.com/package/@hzblj/kara-ui) instead.** This package is one of its building
6
- blocks, published so the umbrella can depend on it; it is versioned together with it and has no standalone docs.
5
+ Install [`@hzblj/kara-ui`](https://www.npmjs.com/package/@hzblj/kara-ui) instead — this is one of its building blocks.
7
6
 
8
7
  MIT
@@ -1,41 +1,71 @@
1
1
  "use strict";
2
2
 
3
- import { HStack } from "../../atoms/h-stack/index.js";
3
+ import { iconResourceName } from '@hzblj/kara-native';
4
+ import { TopAppBar } from '@hzblj/kara-native/jetpack-compose';
5
+ import { useAppTheme } from '@hzblj/kara-theme';
6
+ import { useMemo } from 'react';
7
+ import { StyleSheet } from 'react-native';
4
8
  import { Island } from "../../atoms/island/index.js";
5
- import { Spacer } from "../../atoms/spacer/index.js";
6
- import { Text } from "../../atoms/text/index.js";
7
- import { GlyphButton } from "../../glyph/index.js";
8
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
- /**
10
- * Material's top bar shape — navigation icon, start-aligned title, action at the end — built from the atoms in its own
11
- * island. Compose's icon buttons take no accessibility identifier, so `backTestID`/`closeTestID` are iOS-only.
12
- */
9
+ import { jsx as _jsx } from "react/jsx-runtime";
10
+ /** Material's small top app bar. */
11
+ const BAR_HEIGHT = 64;
12
+ const styles = StyleSheet.create({
13
+ bar: {
14
+ height: BAR_HEIGHT,
15
+ width: '100%'
16
+ }
17
+ });
18
+ const DEFAULT_LABELS = {
19
+ back: 'Back',
20
+ close: 'Close'
21
+ };
22
+ const toNativeItem = ({
23
+ onPress,
24
+ testID,
25
+ ...item
26
+ }) => item.type === 'icon' ? {
27
+ iconName: iconResourceName(item.icon),
28
+ label: item.label,
29
+ onPress,
30
+ testID,
31
+ type: 'icon'
32
+ } : {
33
+ label: item.label ?? DEFAULT_LABELS[item.type],
34
+ onPress,
35
+ testID,
36
+ type: item.type
37
+ };
38
+
39
+ /** Material's top app bar in its own host. `search` is iOS-only for now, and `separated` has no Material counterpart. */
13
40
  export const NavigationBar = ({
14
- backLabel = 'Back',
15
- closeLabel = 'Close',
16
- onBack,
17
- onClose,
41
+ inverted = false,
42
+ leadingItems,
18
43
  testID,
19
- title
20
- }) => /*#__PURE__*/_jsx(Island, {
21
- testID: testID,
22
- children: /*#__PURE__*/_jsxs(HStack, {
23
- align: "center",
24
- px: "s4",
25
- spacing: "s4",
26
- wide: true,
27
- children: [onBack ? /*#__PURE__*/_jsx(GlyphButton, {
28
- accessibilityLabel: backLabel,
29
- name: "back",
30
- onPress: onBack
31
- }) : null, title ? /*#__PURE__*/_jsx(Text, {
32
- variant: "body",
33
- children: title
34
- }) : null, /*#__PURE__*/_jsx(Spacer, {}), onClose ? /*#__PURE__*/_jsx(GlyphButton, {
35
- accessibilityLabel: closeLabel,
36
- name: "close",
37
- onPress: onClose
38
- }) : null]
39
- })
40
- });
44
+ title,
45
+ titleAlignment = 'center',
46
+ titleVisible = true,
47
+ trailingItems
48
+ }) => {
49
+ const theme = useAppTheme();
50
+ const font = theme.typography.headline;
51
+ const color = theme.color(inverted ? 'content.on.bg' : 'content.primary');
52
+ const nativeLeadingItems = useMemo(() => leadingItems?.map(toNativeItem), [leadingItems]);
53
+ const nativeTrailingItems = useMemo(() => trailingItems?.map(toNativeItem), [trailingItems]);
54
+ return /*#__PURE__*/_jsx(Island, {
55
+ matchContents: false,
56
+ style: styles.bar,
57
+ testID: testID,
58
+ children: /*#__PURE__*/_jsx(TopAppBar, {
59
+ fontFamily: font.fontFamily,
60
+ fontSize: font.fontSize,
61
+ itemColor: color,
62
+ leadingItems: nativeLeadingItems,
63
+ title: title,
64
+ titleAlignment: titleAlignment,
65
+ titleColor: color,
66
+ titleVisible: titleVisible,
67
+ trailingItems: nativeTrailingItems
68
+ })
69
+ });
70
+ };
41
71
  //# sourceMappingURL=navigation-bar.android.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["HStack","Island","Spacer","Text","GlyphButton","jsx","_jsx","jsxs","_jsxs","NavigationBar","backLabel","closeLabel","onBack","onClose","testID","title","children","align","px","spacing","wide","accessibilityLabel","name","onPress","variant"],"sourceRoot":"../../../../src","sources":["molecules/navigation-bar/navigation-bar.android.tsx"],"mappings":";;AAAA,SAAQA,MAAM,QAAO,8BAAqB;AAC1C,SAAQC,MAAM,QAAO,6BAAoB;AACzC,SAAQC,MAAM,QAAO,6BAAoB;AACzC,SAAQC,IAAI,QAAO,2BAAkB;AACrC,SAAQC,WAAW,QAAO,sBAAa;AAAA,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAGvC;AACA;AACA;AACA;AACA,OAAO,MAAMC,aAAqC,GAAGA,CAAC;EACpDC,SAAS,GAAG,MAAM;EAClBC,UAAU,GAAG,OAAO;EACpBC,MAAM;EACNC,OAAO;EACPC,MAAM;EACNC;AACkB,CAAC,kBACnBT,IAAA,CAACL,MAAM;EAACa,MAAM,EAAEA,MAAO;EAAAE,QAAA,eACrBR,KAAA,CAACR,MAAM;IAACiB,KAAK,EAAC,QAAQ;IAACC,EAAE,EAAC,IAAI;IAACC,OAAO,EAAC,IAAI;IAACC,IAAI;IAAAJ,QAAA,GAC7CJ,MAAM,gBAAGN,IAAA,CAACF,WAAW;MAACiB,kBAAkB,EAAEX,SAAU;MAACY,IAAI,EAAC,MAAM;MAACC,OAAO,EAAEX;IAAO,CAAE,CAAC,GAAG,IAAI,EAC3FG,KAAK,gBAAGT,IAAA,CAACH,IAAI;MAACqB,OAAO,EAAC,MAAM;MAAAR,QAAA,EAAED;IAAK,CAAO,CAAC,GAAG,IAAI,eACnDT,IAAA,CAACJ,MAAM,IAAE,CAAC,EACTW,OAAO,gBAAGP,IAAA,CAACF,WAAW;MAACiB,kBAAkB,EAAEV,UAAW;MAACW,IAAI,EAAC,OAAO;MAACC,OAAO,EAAEV;IAAQ,CAAE,CAAC,GAAG,IAAI;EAAA,CAC1F;AAAC,CACH,CACT","ignoreList":[]}
1
+ {"version":3,"names":["iconResourceName","TopAppBar","useAppTheme","useMemo","StyleSheet","Island","jsx","_jsx","BAR_HEIGHT","styles","create","bar","height","width","DEFAULT_LABELS","back","close","toNativeItem","onPress","testID","item","type","iconName","icon","label","NavigationBar","inverted","leadingItems","title","titleAlignment","titleVisible","trailingItems","theme","font","typography","headline","color","nativeLeadingItems","map","nativeTrailingItems","matchContents","style","children","fontFamily","fontSize","itemColor","titleColor"],"sourceRoot":"../../../../src","sources":["molecules/navigation-bar/navigation-bar.android.tsx"],"mappings":";;AAAA,SAAQA,gBAAgB,QAAO,oBAAoB;AACnD,SAAQC,SAAS,QAA2B,oCAAoC;AAChF,SAAQC,WAAW,QAAO,mBAAmB;AAC7C,SAAQC,OAAO,QAAO,OAAO;AAC7B,SAAQC,UAAU,QAAO,cAAc;AACvC,SAAQC,MAAM,QAAO,6BAAoB;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAGzC;AACA,MAAMC,UAAU,GAAG,EAAE;AAErB,MAAMC,MAAM,GAAGL,UAAU,CAACM,MAAM,CAAC;EAC/BC,GAAG,EAAE;IAACC,MAAM,EAAEJ,UAAU;IAAEK,KAAK,EAAE;EAAM;AACzC,CAAC,CAAC;AAEF,MAAMC,cAAc,GAAG;EAACC,IAAI,EAAE,MAAM;EAAEC,KAAK,EAAE;AAAO,CAAU;AAE9D,MAAMC,YAAY,GAAGA,CAAC;EAACC,OAAO;EAAEC,MAAM;EAAE,GAAGC;AAAuB,CAAC,KACjEA,IAAI,CAACC,IAAI,KAAK,MAAM,GAChB;EAACC,QAAQ,EAAEtB,gBAAgB,CAACoB,IAAI,CAACG,IAAI,CAAC;EAAEC,KAAK,EAAEJ,IAAI,CAACI,KAAK;EAAEN,OAAO;EAAEC,MAAM;EAAEE,IAAI,EAAE;AAAM,CAAC,GACzF;EAACG,KAAK,EAAEJ,IAAI,CAACI,KAAK,IAAIV,cAAc,CAACM,IAAI,CAACC,IAAI,CAAC;EAAEH,OAAO;EAAEC,MAAM;EAAEE,IAAI,EAAED,IAAI,CAACC;AAAI,CAAC;;AAExF;AACA,OAAO,MAAMI,aAAqC,GAAGA,CAAC;EACpDC,QAAQ,GAAG,KAAK;EAChBC,YAAY;EACZR,MAAM;EACNS,KAAK;EACLC,cAAc,GAAG,QAAQ;EACzBC,YAAY,GAAG,IAAI;EACnBC;AACkB,CAAC,KAAK;EACxB,MAAMC,KAAK,GAAG9B,WAAW,CAAC,CAAC;EAC3B,MAAM+B,IAAI,GAAGD,KAAK,CAACE,UAAU,CAACC,QAAQ;EACtC,MAAMC,KAAK,GAAGJ,KAAK,CAACI,KAAK,CAACV,QAAQ,GAAG,eAAe,GAAG,iBAAiB,CAAC;EAEzE,MAAMW,kBAAkB,GAAGlC,OAAO,CAAC,MAAMwB,YAAY,EAAEW,GAAG,CAACrB,YAAY,CAAC,EAAE,CAACU,YAAY,CAAC,CAAC;EACzF,MAAMY,mBAAmB,GAAGpC,OAAO,CAAC,MAAM4B,aAAa,EAAEO,GAAG,CAACrB,YAAY,CAAC,EAAE,CAACc,aAAa,CAAC,CAAC;EAE5F,oBACExB,IAAA,CAACF,MAAM;IAACmC,aAAa,EAAE,KAAM;IAACC,KAAK,EAAEhC,MAAM,CAACE,GAAI;IAACQ,MAAM,EAAEA,MAAO;IAAAuB,QAAA,eAC9DnC,IAAA,CAACN,SAAS;MACR0C,UAAU,EAAEV,IAAI,CAACU,UAAW;MAC5BC,QAAQ,EAAEX,IAAI,CAACW,QAAS;MACxBC,SAAS,EAAET,KAAM;MACjBT,YAAY,EAAEU,kBAAmB;MACjCT,KAAK,EAAEA,KAAM;MACbC,cAAc,EAAEA,cAAe;MAC/BiB,UAAU,EAAEV,KAAM;MAClBN,YAAY,EAAEA,YAAa;MAC3BC,aAAa,EAAEQ;IAAoB,CACpC;EAAC,CACI,CAAC;AAEb,CAAC","ignoreList":[]}
@@ -1,33 +1,68 @@
1
1
  "use strict";
2
2
 
3
+ import { iconResourceName } from '@hzblj/kara-native';
3
4
  import { NavigationBar as NativeNavigationBar } from '@hzblj/kara-native/swift-ui';
4
5
  import { useAppTheme } from '@hzblj/kara-theme';
6
+ import { useImperativeHandle, useMemo, useRef } from 'react';
5
7
  import { StyleSheet } from 'react-native';
6
8
  import { jsx as _jsx } from "react/jsx-runtime";
7
- /** UIKit's compact bar height. The bar centres itself vertically in whatever it is given. */
8
- const BAR_HEIGHT = 44;
9
+ /** Fits iOS 26's 44 pt glass items with the bar's own margin; the bar centres itself vertically in it. */
10
+ const BAR_HEIGHT = 56;
9
11
  const styles = StyleSheet.create({
10
12
  bar: {
11
13
  height: BAR_HEIGHT,
12
14
  width: '100%'
13
15
  }
14
16
  });
17
+ const DEFAULT_LABELS = {
18
+ back: 'Back',
19
+ close: 'Close'
20
+ };
21
+ const toNativeItem = item => item.type === 'icon' ? {
22
+ ...item,
23
+ imageName: iconResourceName(item.icon),
24
+ type: 'icon'
25
+ } : {
26
+ ...item,
27
+ label: item.label ?? DEFAULT_LABELS[item.type]
28
+ };
29
+ const ignoreDetachedView = () => undefined;
15
30
  export const NavigationBar = ({
16
- backLabel = 'Back',
17
- closeLabel = 'Close',
18
- ...props
31
+ inverted = false,
32
+ leadingItems,
33
+ search,
34
+ testID,
35
+ title,
36
+ titleAlignment = 'center',
37
+ titleVisible = true,
38
+ trailingItems
19
39
  }) => {
20
40
  const theme = useAppTheme();
21
- const title = theme.typography.body;
41
+ const barRef = useRef(null);
42
+ const font = theme.typography.headline;
43
+ const color = theme.color(inverted ? 'content.on.bg' : 'content.primary');
44
+ useImperativeHandle(search?.ref, () => ({
45
+ clear: () => barRef.current?.clearSearchText().catch(ignoreDetachedView)
46
+ }), []);
47
+ const nativeLeadingItems = useMemo(() => leadingItems?.map(toNativeItem), [leadingItems]);
48
+ const nativeTrailingItems = useMemo(() => trailingItems?.map(toNativeItem), [trailingItems]);
22
49
  return /*#__PURE__*/_jsx(NativeNavigationBar, {
23
- ...props,
24
- backLabel: backLabel,
25
- closeLabel: closeLabel,
26
- fontFamily: title.fontFamily,
27
- fontSize: title.fontSize,
28
- itemColor: theme.color('content.primary'),
50
+ fontFamily: font.fontFamily,
51
+ fontSize: font.fontSize,
52
+ itemColor: color,
53
+ leadingItems: nativeLeadingItems,
54
+ onSearchFocusChange: search?.onFocusChange,
55
+ onSearchTextChange: search?.onChangeText,
56
+ ref: barRef,
57
+ searchPlaceholder: search?.placeholder,
58
+ searchTestID: search?.testID,
29
59
  style: styles.bar,
30
- titleColor: theme.color('content.primary')
60
+ testID: testID,
61
+ title: title,
62
+ titleAlignment: titleAlignment,
63
+ titleColor: color,
64
+ titleVisible: titleVisible,
65
+ trailingItems: nativeTrailingItems
31
66
  });
32
67
  };
33
68
  //# sourceMappingURL=navigation-bar.ios.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["NavigationBar","NativeNavigationBar","useAppTheme","StyleSheet","jsx","_jsx","BAR_HEIGHT","styles","create","bar","height","width","backLabel","closeLabel","props","theme","title","typography","body","fontFamily","fontSize","itemColor","color","style","titleColor"],"sourceRoot":"../../../../src","sources":["molecules/navigation-bar/navigation-bar.ios.tsx"],"mappings":";;AAAA,SAAQA,aAAa,IAAIC,mBAAmB,QAAO,6BAA6B;AAChF,SAAQC,WAAW,QAAO,mBAAmB;AAC7C,SAAQC,UAAU,QAAO,cAAc;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAGvC;AACA,MAAMC,UAAU,GAAG,EAAE;AAErB,MAAMC,MAAM,GAAGJ,UAAU,CAACK,MAAM,CAAC;EAC/BC,GAAG,EAAE;IAACC,MAAM,EAAEJ,UAAU;IAAEK,KAAK,EAAE;EAAM;AACzC,CAAC,CAAC;AAEF,OAAO,MAAMX,aAAqC,GAAGA,CAAC;EACpDY,SAAS,GAAG,MAAM;EAClBC,UAAU,GAAG,OAAO;EACpB,GAAGC;AACe,CAAC,KAAK;EACxB,MAAMC,KAAK,GAAGb,WAAW,CAAC,CAAC;EAC3B,MAAMc,KAAK,GAAGD,KAAK,CAACE,UAAU,CAACC,IAAI;EAEnC,oBACEb,IAAA,CAACJ,mBAAmB;IAAA,GACda,KAAK;IACTF,SAAS,EAAEA,SAAU;IACrBC,UAAU,EAAEA,UAAW;IACvBM,UAAU,EAAEH,KAAK,CAACG,UAAW;IAC7BC,QAAQ,EAAEJ,KAAK,CAACI,QAAS;IACzBC,SAAS,EAAEN,KAAK,CAACO,KAAK,CAAC,iBAAiB,CAAE;IAC1CC,KAAK,EAAEhB,MAAM,CAACE,GAAI;IAClBe,UAAU,EAAET,KAAK,CAACO,KAAK,CAAC,iBAAiB;EAAE,CAC5C,CAAC;AAEN,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["iconResourceName","NavigationBar","NativeNavigationBar","useAppTheme","useImperativeHandle","useMemo","useRef","StyleSheet","jsx","_jsx","BAR_HEIGHT","styles","create","bar","height","width","DEFAULT_LABELS","back","close","toNativeItem","item","type","imageName","icon","label","ignoreDetachedView","undefined","inverted","leadingItems","search","testID","title","titleAlignment","titleVisible","trailingItems","theme","barRef","font","typography","headline","color","ref","clear","current","clearSearchText","catch","nativeLeadingItems","map","nativeTrailingItems","fontFamily","fontSize","itemColor","onSearchFocusChange","onFocusChange","onSearchTextChange","onChangeText","searchPlaceholder","placeholder","searchTestID","style","titleColor"],"sourceRoot":"../../../../src","sources":["molecules/navigation-bar/navigation-bar.ios.tsx"],"mappings":"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","ignoreList":[]}
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
 
3
- export * from './sheet';
3
+ export * from "./sheet.js";
4
4
  export * from "./sheet.types.js";
5
+ export { useSheetScroll } from "./sheet-scroll.js";
5
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":[],"sourceRoot":"../../../../src","sources":["organisms/sheet/index.ts"],"mappings":";;AAAA,cAAc,SAAS;AACvB,cAAc,kBAAe","ignoreList":[]}
1
+ {"version":3,"names":["useSheetScroll"],"sourceRoot":"../../../../src","sources":["organisms/sheet/index.ts"],"mappings":";;AAAA,cAAc,YAAS;AACvB,cAAc,kBAAe;AAC7B,SAAQA,cAAc,QAAO,mBAAgB","ignoreList":[]}
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+
3
+ /** A slot, never rendered: `Sheet` reads its props and builds the header into the native sheet's own header area. */
4
+ export const SheetHeader = _props => {
5
+ throw new Error('[kara-ui] <Sheet.Header> must be a direct child of <Sheet>.');
6
+ };
7
+ //# sourceMappingURL=sheet-header.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["SheetHeader","_props","Error"],"sourceRoot":"../../../../src","sources":["organisms/sheet/sheet-header.tsx"],"mappings":";;AAEA;AACA,OAAO,MAAMA,WAAW,GAAIC,MAAwB,IAAY;EAC9D,MAAM,IAAIC,KAAK,CAAC,6DAA6D,CAAC;AAChF,CAAC","ignoreList":[]}
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+
3
+ import { useSx } from '@hzblj/kara-sx';
4
+ import { createContext, useCallback, useContext, useMemo } from 'react';
5
+ import { ScrollView } from 'react-native';
6
+ import { jsxs as _jsxs } from "react/jsx-runtime";
7
+ export const SheetScrollContext = /*#__PURE__*/createContext(null);
8
+
9
+ /**
10
+ * For a scroll view of your own inside a sheet (a `RnFlatList`, say): pad its content by `topInset`, render
11
+ * `largeTitle` first, and forward `onScroll` — which is what `<Sheet.ScrollView>` does.
12
+ */
13
+ export const useSheetScroll = () => {
14
+ const context = useContext(SheetScrollContext);
15
+ if (context === null) {
16
+ throw new Error('[kara-ui] useSheetScroll and <Sheet.ScrollView> must be used inside <Sheet>.');
17
+ }
18
+ return context;
19
+ };
20
+ const NO_SX = {};
21
+
22
+ /** The sheet's scrolling body: starts below the header on iOS 26, carries a large title, and reports its scroll. */
23
+ export const SheetScrollView = ({
24
+ children,
25
+ content,
26
+ keyboardShouldPersistTaps,
27
+ onScroll,
28
+ testID
29
+ }) => {
30
+ const {
31
+ largeTitle,
32
+ onScroll: onSheetScroll,
33
+ topInset
34
+ } = useSheetScroll();
35
+ const contentStyle = useSx(content ?? NO_SX);
36
+ // The header's room goes on top of the content's own top padding, not in place of it.
37
+ const containerStyle = useMemo(() => {
38
+ if (topInset === 0) {
39
+ return contentStyle;
40
+ }
41
+ const ownTop = typeof contentStyle.paddingTop === 'number' ? contentStyle.paddingTop : 0;
42
+ return [contentStyle, {
43
+ paddingTop: topInset + ownTop
44
+ }];
45
+ }, [contentStyle, topInset]);
46
+ const handleScroll = useCallback(event => {
47
+ onSheetScroll?.(event);
48
+ onScroll?.(event);
49
+ }, [onScroll, onSheetScroll]);
50
+ return /*#__PURE__*/_jsxs(ScrollView, {
51
+ contentContainerStyle: containerStyle,
52
+ contentInsetAdjustmentBehavior: "never",
53
+ keyboardShouldPersistTaps: keyboardShouldPersistTaps,
54
+ nestedScrollEnabled: true,
55
+ onScroll: onSheetScroll || onScroll ? handleScroll : undefined,
56
+ overScrollMode: "always",
57
+ scrollEventThrottle: 16,
58
+ testID: testID,
59
+ children: [largeTitle, children]
60
+ });
61
+ };
62
+ //# sourceMappingURL=sheet-scroll.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useSx","createContext","useCallback","useContext","useMemo","ScrollView","jsxs","_jsxs","SheetScrollContext","useSheetScroll","context","Error","NO_SX","SheetScrollView","children","content","keyboardShouldPersistTaps","onScroll","testID","largeTitle","onSheetScroll","topInset","contentStyle","containerStyle","ownTop","paddingTop","handleScroll","event","contentContainerStyle","contentInsetAdjustmentBehavior","nestedScrollEnabled","undefined","overScrollMode","scrollEventThrottle"],"sourceRoot":"../../../../src","sources":["organisms/sheet/sheet-scroll.tsx"],"mappings":";;AAAA,SAAQA,KAAK,QAAO,gBAAgB;AACpC,SAAQC,aAAa,EAAEC,WAAW,EAAEC,UAAU,EAAEC,OAAO,QAAO,OAAO;AACrE,SAAQC,UAAU,QAAO,cAAc;AAAA,SAAAC,IAAA,IAAAC,KAAA;AAIvC,OAAO,MAAMC,kBAAkB,gBAAGP,aAAa,CAAiC,IAAI,CAAC;;AAErF;AACA;AACA;AACA;AACA,OAAO,MAAMQ,cAAc,GAAGA,CAAA,KAA+B;EAC3D,MAAMC,OAAO,GAAGP,UAAU,CAACK,kBAAkB,CAAC;EAE9C,IAAIE,OAAO,KAAK,IAAI,EAAE;IACpB,MAAM,IAAIC,KAAK,CAAC,8EAA8E,CAAC;EACjG;EAEA,OAAOD,OAAO;AAChB,CAAC;AAED,MAAME,KAAK,GAAG,CAAC,CAAC;;AAEhB;AACA,OAAO,MAAMC,eAAe,GAAGA,CAAC;EAC9BC,QAAQ;EACRC,OAAO;EACPC,yBAAyB;EACzBC,QAAQ;EACRC;AACoB,CAAC,KAAK;EAC1B,MAAM;IAACC,UAAU;IAAEF,QAAQ,EAAEG,aAAa;IAAEC;EAAQ,CAAC,GAAGZ,cAAc,CAAC,CAAC;EACxE,MAAMa,YAAY,GAAGtB,KAAK,CAACe,OAAO,IAAIH,KAAK,CAAC;EAC5C;EACA,MAAMW,cAAc,GAAGnB,OAAO,CAAC,MAAM;IACnC,IAAIiB,QAAQ,KAAK,CAAC,EAAE;MAClB,OAAOC,YAAY;IACrB;IAEA,MAAME,MAAM,GAAG,OAAOF,YAAY,CAACG,UAAU,KAAK,QAAQ,GAAGH,YAAY,CAACG,UAAU,GAAG,CAAC;IAExF,OAAO,CAACH,YAAY,EAAE;MAACG,UAAU,EAAEJ,QAAQ,GAAGG;IAAM,CAAC,CAAC;EACxD,CAAC,EAAE,CAACF,YAAY,EAAED,QAAQ,CAAC,CAAC;EAE5B,MAAMK,YAAY,GAAGxB,WAAW,CAC9ByB,KAAK,IAAI;IACPP,aAAa,GAAGO,KAAK,CAAC;IACtBV,QAAQ,GAAGU,KAAK,CAAC;EACnB,CAAC,EACD,CAACV,QAAQ,EAAEG,aAAa,CAC1B,CAAC;EAED,oBACEb,KAAA,CAACF,UAAU;IACTuB,qBAAqB,EAAEL,cAAe;IACtCM,8BAA8B,EAAC,OAAO;IACtCb,yBAAyB,EAAEA,yBAA0B;IACrDc,mBAAmB;IACnBb,QAAQ,EAAEG,aAAa,IAAIH,QAAQ,GAAGS,YAAY,GAAGK,SAAU;IAC/DC,cAAc,EAAC,QAAQ;IACvBC,mBAAmB,EAAE,EAAG;IACxBf,MAAM,EAAEA,MAAO;IAAAJ,QAAA,GAEdK,UAAU,EACVL,QAAQ;EAAA,CACC,CAAC;AAEjB,CAAC","ignoreList":[]}
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+
3
+ import { useAppTheme } from '@hzblj/kara-theme';
4
+ import { TrueSheet } from '@lodev09/react-native-true-sheet';
5
+ import { useCallback, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef } from 'react';
6
+ import { Platform, StyleSheet, View } from 'react-native';
7
+ import { SheetHeader } from "./sheet-header.js";
8
+ import { SheetScrollContext, SheetScrollView } from "./sheet-scroll.js";
9
+ import { splitSheetChildren } from "./split-sheet-children.js";
10
+ import { useSheetHeader } from "./use-sheet-header.js";
11
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
12
+ const FIT_CONTENT = ['auto'];
13
+
14
+ /** Material's extra-large shape for a bottom sheet; iOS keeps the system's own, which follows the device's corners. */
15
+ const CORNER_RADIUS = Platform.OS === 'android' ? 28 : undefined;
16
+
17
+ /** Keeps the sheet's own native view out of the layout it is declared in. */
18
+ const styles = StyleSheet.create({
19
+ host: {
20
+ position: 'absolute'
21
+ }
22
+ });
23
+ const SheetRoot = ({
24
+ bg = 'surface.primary',
25
+ children,
26
+ detents = FIT_CONTENT,
27
+ dimmed = true,
28
+ dismissible = true,
29
+ draggable = true,
30
+ footer,
31
+ grabber = true,
32
+ onDetentChange,
33
+ onDismiss,
34
+ onPresent,
35
+ ref,
36
+ scrollable = false,
37
+ testID,
38
+ visible
39
+ }) => {
40
+ const theme = useAppTheme();
41
+ const {
42
+ content,
43
+ header: headerProps
44
+ } = useMemo(() => splitSheetChildren(children), [children]);
45
+ const sheetHeader = useSheetHeader({
46
+ header: headerProps,
47
+ scrollable
48
+ });
49
+ const sheetRef = useRef(null);
50
+ const presented = useRef(false);
51
+ /** A dismissal we asked for: `onDismiss` reports the user's, never ours. */
52
+ const programmaticDismiss = useRef(false);
53
+ useImperativeHandle(ref, () => ({
54
+ dismiss: () => {
55
+ presented.current = false;
56
+ programmaticDismiss.current = true;
57
+ return sheetRef.current?.dismiss() ?? Promise.resolve();
58
+ },
59
+ present: detentIndex => {
60
+ presented.current = true;
61
+ return sheetRef.current?.present(detentIndex) ?? Promise.resolve();
62
+ },
63
+ resize: detentIndex => sheetRef.current?.resize(detentIndex) ?? Promise.resolve()
64
+ }), []);
65
+ useEffect(() => {
66
+ if (visible && !presented.current) {
67
+ presented.current = true;
68
+ void sheetRef.current?.present();
69
+ } else if (!visible && presented.current) {
70
+ presented.current = false;
71
+ programmaticDismiss.current = true;
72
+ void sheetRef.current?.dismiss();
73
+ }
74
+ }, [visible]);
75
+
76
+ // A sheet unmounted while presented would otherwise stay on screen, blocking everything under it.
77
+ useLayoutEffect(() => {
78
+ const sheet = sheetRef.current;
79
+ return () => {
80
+ if (!presented.current) {
81
+ return;
82
+ }
83
+ presented.current = false;
84
+ programmaticDismiss.current = true;
85
+ void sheet?.dismiss();
86
+ };
87
+ }, []);
88
+ const handleDidDismiss = useCallback(() => {
89
+ presented.current = false;
90
+ if (programmaticDismiss.current) {
91
+ programmaticDismiss.current = false;
92
+ return;
93
+ }
94
+ onDismiss();
95
+ }, [onDismiss]);
96
+ const handleDetentChange = useCallback(event => onDetentChange?.(event.nativeEvent.index), [onDetentChange]);
97
+ return /*#__PURE__*/_jsx(View, {
98
+ collapsable: false,
99
+ pointerEvents: "box-none",
100
+ style: styles.host,
101
+ children: /*#__PURE__*/_jsx(TrueSheet, {
102
+ backgroundColor: theme.color(bg),
103
+ cornerRadius: CORNER_RADIUS,
104
+ detents: detents,
105
+ dimmed: dimmed,
106
+ dismissible: dismissible,
107
+ draggable: draggable,
108
+ footer: footer,
109
+ grabber: grabber,
110
+ header: sheetHeader.header,
111
+ headerStyle: sheetHeader.headerStyle,
112
+ onDetentChange: handleDetentChange,
113
+ onDidDismiss: handleDidDismiss,
114
+ onDidPresent: onPresent,
115
+ ref: sheetRef,
116
+ scrollable: scrollable,
117
+ scrollableOptions: sheetHeader.scrollableOptions,
118
+ testID: testID,
119
+ children: /*#__PURE__*/_jsxs(SheetScrollContext.Provider, {
120
+ value: sheetHeader.scrollContext,
121
+ children: [sheetHeader.staticLargeTitle, content]
122
+ })
123
+ })
124
+ });
125
+ };
126
+
127
+ /**
128
+ * A native sheet with an optional native header. `visible` presents and dismisses it; a swipe or a tap outside calls
129
+ * `onDismiss`, which should set `visible` back. `<Sheet.Header>` (a direct child) gives it a bar with a title and
130
+ * items; `<Sheet.ScrollView>` is the body of a `scrollable` sheet.
131
+ */
132
+ export const Sheet = Object.assign(SheetRoot, {
133
+ Header: SheetHeader,
134
+ ScrollView: SheetScrollView
135
+ });
136
+ //# sourceMappingURL=sheet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useAppTheme","TrueSheet","useCallback","useEffect","useImperativeHandle","useLayoutEffect","useMemo","useRef","Platform","StyleSheet","View","SheetHeader","SheetScrollContext","SheetScrollView","splitSheetChildren","useSheetHeader","jsxs","_jsxs","jsx","_jsx","FIT_CONTENT","CORNER_RADIUS","OS","undefined","styles","create","host","position","SheetRoot","bg","children","detents","dimmed","dismissible","draggable","footer","grabber","onDetentChange","onDismiss","onPresent","ref","scrollable","testID","visible","theme","content","header","headerProps","sheetHeader","sheetRef","presented","programmaticDismiss","dismiss","current","Promise","resolve","present","detentIndex","resize","sheet","handleDidDismiss","handleDetentChange","event","nativeEvent","index","collapsable","pointerEvents","style","backgroundColor","color","cornerRadius","headerStyle","onDidDismiss","onDidPresent","scrollableOptions","Provider","value","scrollContext","staticLargeTitle","Sheet","Object","assign","Header","ScrollView"],"sourceRoot":"../../../../src","sources":["organisms/sheet/sheet.tsx"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+
3
+ import { Children, isValidElement } from 'react';
4
+ import { SheetHeader } from "./sheet-header.js";
5
+ const isSheetHeader = child => /*#__PURE__*/isValidElement(child) && child.type === SheetHeader;
6
+
7
+ /** Takes `<Sheet.Header>` out of the children: its props become the native header, the rest is the content. */
8
+ export const splitSheetChildren = children => {
9
+ const nodes = Children.toArray(children);
10
+ const header = nodes.find(isSheetHeader);
11
+ if (!header) {
12
+ return {
13
+ content: children
14
+ };
15
+ }
16
+ return {
17
+ content: nodes.filter(node => node !== header),
18
+ header: header.props
19
+ };
20
+ };
21
+ //# sourceMappingURL=split-sheet-children.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["Children","isValidElement","SheetHeader","isSheetHeader","child","type","splitSheetChildren","children","nodes","toArray","header","find","content","filter","node","props"],"sourceRoot":"../../../../src","sources":["organisms/sheet/split-sheet-children.ts"],"mappings":";;AAAA,SAAQA,QAAQ,EAAEC,cAAc,QAA0C,OAAO;AAEjF,SAAQC,WAAW,QAAO,mBAAgB;AAO1C,MAAMC,aAAa,GAAIC,KAAgB,IACrC,aAAAH,cAAc,CAACG,KAAK,CAAC,IAAIA,KAAK,CAACC,IAAI,KAAKH,WAAW;;AAErD;AACA,OAAO,MAAMI,kBAAkB,GAAIC,QAAmB,IAAoB;EACxE,MAAMC,KAAK,GAAGR,QAAQ,CAACS,OAAO,CAACF,QAAQ,CAAC;EACxC,MAAMG,MAAM,GAAGF,KAAK,CAACG,IAAI,CAACR,aAAa,CAAC;EAExC,IAAI,CAACO,MAAM,EAAE;IACX,OAAO;MAACE,OAAO,EAAEL;IAAQ,CAAC;EAC5B;EAEA,OAAO;IAACK,OAAO,EAAEJ,KAAK,CAACK,MAAM,CAACC,IAAI,IAAIA,IAAI,KAAKJ,MAAM,CAAC;IAAEA,MAAM,EAAEA,MAAM,CAACK;EAAK,CAAC;AAC/E,CAAC","ignoreList":[]}
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+
3
+ import { isScrollEdgeEffectAvailable } from '@hzblj/kara-native';
4
+ import { spacing } from '@hzblj/kara-theme';
5
+ import { useCallback, useMemo, useRef, useState } from 'react';
6
+ import { Platform } from 'react-native';
7
+ import { Box } from "../../atoms/box/index.js";
8
+ import { RnText } from "../../atoms/rn-text/index.js";
9
+ import { NavigationBar } from "../../molecules/navigation-bar/index.js";
10
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
+ /** The bar's own height (`NavigationBar`) plus the room above it, before the header has been measured. */
12
+ const ESTIMATED_HEADER_HEIGHT = (Platform.OS === 'ios' ? 56 : 64) + spacing.s16;
13
+
14
+ /** Where a large title's bar title appears once it has scrolled away: the platform's own place for it. */
15
+ const COLLAPSED_TITLE_ALIGNMENT = Platform.OS === 'ios' ? 'center' : 'leading';
16
+
17
+ /** Lays the header over the content so the content can scroll under it — the edge effect needs it there. */
18
+ const OVERLAY_HEADER_STYLE = {
19
+ left: 0,
20
+ position: 'absolute',
21
+ right: 0,
22
+ top: 0,
23
+ zIndex: 1
24
+ };
25
+ const SOFT_EDGE_EFFECTS = {
26
+ bottomScrollEdgeEffect: 'soft',
27
+ topScrollEdgeEffect: 'soft'
28
+ };
29
+ const SheetLargeTitle = ({
30
+ onLayout,
31
+ title
32
+ }) => /*#__PURE__*/_jsx(Box, {
33
+ onLayout: onLayout,
34
+ pb: "s8",
35
+ pt: "s8",
36
+ px: "s16",
37
+ children: /*#__PURE__*/_jsx(RnText, {
38
+ accessibilityRole: "header",
39
+ variant: "headingM",
40
+ children: title
41
+ })
42
+ });
43
+
44
+ /**
45
+ * Turns `<Sheet.Header>`'s props into what the native sheet takes: its header element, how that is laid out, the scroll
46
+ * edge effects, and the context a `<Sheet.ScrollView>` reads. On iOS 26 a scrollable sheet's header is laid over the
47
+ * content (which is then inset by the header's measured height) so the system's soft edge blurs what scrolls under it;
48
+ * everywhere else the header simply sits above the content.
49
+ */
50
+ export const useSheetHeader = ({
51
+ header: headerProps,
52
+ scrollable
53
+ }) => {
54
+ const title = headerProps?.title;
55
+ const titleStyle = headerProps?.titleStyle ?? 'center';
56
+ const leadingItems = headerProps?.leadingItems;
57
+ const trailingItems = headerProps?.trailingItems;
58
+ const inverted = headerProps?.inverted;
59
+ const search = headerProps?.search;
60
+ const accessory = headerProps?.children;
61
+ const hasBar = title !== undefined || !!leadingItems?.length || !!trailingItems?.length || !!search;
62
+ const hasHeader = hasBar || !!accessory;
63
+ const isOverlay = isScrollEdgeEffectAvailable() && hasHeader && scrollable;
64
+ const isLargeTitle = titleStyle === 'large' && !!title;
65
+ const [headerHeight, setHeaderHeight] = useState(hasBar ? ESTIMATED_HEADER_HEIGHT : 0);
66
+ const [largeTitleScrolledAway, setLargeTitleScrolledAway] = useState(false);
67
+ const largeTitleHeight = useRef(0);
68
+ const handleHeaderLayout = useCallback(event => {
69
+ setHeaderHeight(event.nativeEvent.layout.height);
70
+ }, []);
71
+ const handleLargeTitleLayout = useCallback(event => {
72
+ largeTitleHeight.current = event.nativeEvent.layout.height;
73
+ }, []);
74
+ const handleScroll = useCallback(event => {
75
+ if (largeTitleHeight.current === 0) {
76
+ return;
77
+ }
78
+ setLargeTitleScrolledAway(event.nativeEvent.contentOffset.y >= largeTitleHeight.current);
79
+ }, []);
80
+ const titleAlignment = titleStyle === 'large' ? COLLAPSED_TITLE_ALIGNMENT : titleStyle;
81
+ const titleVisible = !isLargeTitle || scrollable && largeTitleScrolledAway;
82
+ const headerElement = useMemo(() => {
83
+ if (!hasHeader) {
84
+ return undefined;
85
+ }
86
+ return /*#__PURE__*/_jsxs(Box, {
87
+ onLayout: isOverlay ? handleHeaderLayout : undefined,
88
+ pt: "s16",
89
+ children: [hasBar ? /*#__PURE__*/_jsx(NavigationBar, {
90
+ inverted: inverted,
91
+ leadingItems: leadingItems,
92
+ search: search,
93
+ title: title,
94
+ titleAlignment: titleAlignment,
95
+ titleVisible: titleVisible,
96
+ trailingItems: trailingItems
97
+ }) : null, accessory]
98
+ });
99
+ }, [accessory, handleHeaderLayout, hasBar, hasHeader, inverted, isOverlay, leadingItems, search, title, titleAlignment, titleVisible, trailingItems]);
100
+ const largeTitle = useMemo(() => title && isLargeTitle ? /*#__PURE__*/_jsx(SheetLargeTitle, {
101
+ onLayout: handleLargeTitleLayout,
102
+ title: title
103
+ }) : null, [handleLargeTitleLayout, isLargeTitle, title]);
104
+ const scrollContext = useMemo(() => ({
105
+ largeTitle: scrollable ? largeTitle : null,
106
+ onScroll: scrollable && isLargeTitle ? handleScroll : undefined,
107
+ topInset: isOverlay ? headerHeight : 0
108
+ }), [handleScroll, headerHeight, isLargeTitle, isOverlay, largeTitle, scrollable]);
109
+ return {
110
+ header: headerElement,
111
+ headerStyle: isOverlay ? OVERLAY_HEADER_STYLE : undefined,
112
+ scrollableOptions: isOverlay ? SOFT_EDGE_EFFECTS : undefined,
113
+ scrollContext,
114
+ /** Without a scroll view to carry it, a large title simply leads the content. */
115
+ staticLargeTitle: scrollable ? null : largeTitle
116
+ };
117
+ };
118
+ //# sourceMappingURL=use-sheet-header.js.map