@hzblj/kara-components 0.23.1 → 0.25.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 (28) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/lib/module/atoms/icon/icon.android.js +29 -4
  3. package/lib/module/atoms/icon/icon.android.js.map +1 -1
  4. package/lib/module/atoms/icon/icon.ios.js +35 -10
  5. package/lib/module/atoms/icon/icon.ios.js.map +1 -1
  6. package/lib/module/atoms/list/list.ios.js +2 -1
  7. package/lib/module/atoms/list/list.ios.js.map +1 -1
  8. package/lib/module/atoms/rn-icon/rn-icon.js +9 -8
  9. package/lib/module/atoms/rn-icon/rn-icon.js.map +1 -1
  10. package/lib/module/molecules/scroll-edge-container/scroll-edge-container.android.js +4 -0
  11. package/lib/module/molecules/scroll-edge-container/scroll-edge-container.android.js.map +1 -1
  12. package/lib/module/molecules/scroll-edge-container/scroll-edge-container.ios.js +8 -0
  13. package/lib/module/molecules/scroll-edge-container/scroll-edge-container.ios.js.map +1 -1
  14. package/lib/typescript/atoms/icon/icon.ios.d.ts +3 -2
  15. package/lib/typescript/atoms/icon/icon.types.d.ts +38 -4
  16. package/lib/typescript/atoms/list/list.types.d.ts +2 -0
  17. package/lib/typescript/atoms/rn-icon/rn-icon.d.ts +3 -2
  18. package/lib/typescript/molecules/scroll-edge-container/scroll-edge-container.types.d.ts +8 -0
  19. package/package.json +5 -5
  20. package/src/atoms/icon/icon.android.tsx +33 -3
  21. package/src/atoms/icon/icon.ios.tsx +47 -7
  22. package/src/atoms/icon/icon.types.ts +47 -4
  23. package/src/atoms/list/list.ios.tsx +2 -1
  24. package/src/atoms/list/list.types.ts +2 -0
  25. package/src/atoms/rn-icon/rn-icon.tsx +9 -8
  26. package/src/molecules/scroll-edge-container/scroll-edge-container.android.tsx +4 -0
  27. package/src/molecules/scroll-edge-container/scroll-edge-container.ios.tsx +8 -0
  28. package/src/molecules/scroll-edge-container/scroll-edge-container.types.ts +8 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @hzblj/kara-components
2
2
 
3
+ ## 0.25.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#80](https://github.com/hzblj/kara-ui/pull/80) [`e9d4c23`](https://github.com/hzblj/kara-ui/commit/e9d4c23328a2e72e0fb124621cc4f491b3f86335) Thanks [@hzblj](https://github.com/hzblj)! - `ScrollEdgeContainer` catches up with Footshop's: it sets the scroll view's top inset natively as soon as the top bar is laid out, so a list no longer starts under its bar for a few frames and then jumps (most visible on a tab rendered before it is first shown); `initialTopBarHeight` / `initialBottomBarHeight` give the first frame its insets; `contentScrollView` lets the iOS 26 tab bar minimise with this scroll view; `topEdgeEffectHidden` drops the top blur. A list remounted by `key` keeps its inset and edge effects, and a bottom bar no longer jumps while the keyboard animates. On iOS a `List` is its screen's content scroll view, so a large title in the header collapses as the list scrolls. Run a prebuild after upgrading.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [[`e9d4c23`](https://github.com/hzblj/kara-ui/commit/e9d4c23328a2e72e0fb124621cc4f491b3f86335)]:
12
+ - @hzblj/kara-native@0.25.0
13
+ - @hzblj/kara-sx@0.25.0
14
+ - @hzblj/kara-theme@0.25.0
15
+
16
+ ## 0.24.0
17
+
18
+ ### Minor Changes
19
+
20
+ - [#78](https://github.com/hzblj/kara-ui/pull/78) [`f13e538`](https://github.com/hzblj/kara-ui/commit/f13e538dec32f9a0ce21d86a64a0ad708dc9335e) Thanks [@hzblj](https://github.com/hzblj)! - `Icon` and `RnIcon` play SF Symbols effects (`effect`, once per `effectTrigger` or while `effectActive`), animate a new `name` with a `transition`, and draw `hierarchical`, `palette` and `multicolor` rendering modes (`secondaryColor`, `tertiaryColor`), a `variableValue` and a `gradient`, on both platforms. On iOS `Icon` now draws the custom SF Symbol `@hzblj/expo-native-icons` writes per icon, through the new `symbolStyle` modifier; on Android it hands the icon to expo-native-icons' view when one of these is set. Run a prebuild after upgrading.
21
+
22
+ ### Patch Changes
23
+
24
+ - Updated dependencies [[`f13e538`](https://github.com/hzblj/kara-ui/commit/f13e538dec32f9a0ce21d86a64a0ad708dc9335e)]:
25
+ - @hzblj/kara-native@0.24.0
26
+ - @hzblj/kara-sx@0.24.0
27
+ - @hzblj/kara-theme@0.24.0
28
+
3
29
  ## 0.23.1
4
30
 
5
31
  ### Patch Changes
@@ -1,24 +1,49 @@
1
1
  "use strict";
2
2
 
3
- import { iconResourceName } from '@hzblj/expo-native-icons';
3
+ import { iconResourceName, nativeIconEffectRecord, nativeIconTriggerKey } from '@hzblj/expo-native-icons';
4
4
  import { DrawableIcon } from '@hzblj/kara-native/jetpack-compose';
5
5
  import { spacing, useAppTheme } from '@hzblj/kara-theme';
6
+ import { useMemo } from 'react';
6
7
  import { useHostGuard } from "../../hooks/host-context.js";
7
8
  import { jsx as _jsx } from "react/jsx-runtime";
8
- /** The app's icon as the vector drawable the config plugin generated from the SVG, drawn by Material's `Icon`. */
9
+ /**
10
+ * The app's icon as the vector drawable the config plugin generated from the SVG, drawn by Material's `Icon`; with an
11
+ * effect, a transition, a rendering mode, a variable value or a gradient, by `@hzblj/expo-native-icons`' view, which
12
+ * plays them.
13
+ */
9
14
  export const Icon = ({
10
15
  accessibilityLabel,
11
16
  color = 'content.primary',
17
+ effect,
18
+ effectActive,
19
+ effectTrigger,
20
+ gradient,
12
21
  name,
13
- size = 's24'
22
+ renderingMode,
23
+ secondaryColor,
24
+ size = 's24',
25
+ tertiaryColor,
26
+ transition,
27
+ variableValue
14
28
  }) => {
15
29
  useHostGuard('Icon');
16
30
  const theme = useAppTheme();
31
+ const effectKey = effect ? JSON.stringify(effect) : undefined;
32
+ const record = useMemo(() => effectKey ? nativeIconEffectRecord(JSON.parse(effectKey)) : undefined, [effectKey]);
17
33
  return /*#__PURE__*/_jsx(DrawableIcon, {
18
34
  accessibilityLabel: accessibilityLabel,
35
+ effect: record,
36
+ effectActive: effectActive,
37
+ effectTrigger: nativeIconTriggerKey(effectTrigger),
38
+ gradient: gradient,
19
39
  iconColor: theme.color(color),
20
40
  iconSize: spacing[size],
21
- resourceName: iconResourceName(name)
41
+ renderingMode: renderingMode,
42
+ resourceName: iconResourceName(name),
43
+ secondaryColor: secondaryColor ? theme.color(secondaryColor) : undefined,
44
+ tertiaryColor: tertiaryColor ? theme.color(tertiaryColor) : undefined,
45
+ transition: transition,
46
+ variableValue: variableValue
22
47
  });
23
48
  };
24
49
  //# sourceMappingURL=icon.android.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["iconResourceName","DrawableIcon","spacing","useAppTheme","useHostGuard","jsx","_jsx","Icon","accessibilityLabel","color","name","size","theme","iconColor","iconSize","resourceName"],"sourceRoot":"../../../../src","sources":["atoms/icon/icon.android.tsx"],"mappings":";;AAAA,SAAQA,gBAAgB,QAAO,0BAA0B;AACzD,SAAQC,YAAY,QAAO,oCAAoC;AAC/D,SAAQC,OAAO,EAAEC,WAAW,QAAO,mBAAmB;AAEtD,SAAQC,YAAY,QAAO,6BAA0B;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAGrD;AACA,OAAO,MAAMC,IAAmB,GAAGA,CAAC;EAACC,kBAAkB;EAAEC,KAAK,GAAG,iBAAiB;EAAEC,IAAI;EAAEC,IAAI,GAAG;AAAgB,CAAC,KAAK;EACrHP,YAAY,CAAC,MAAM,CAAC;EACpB,MAAMQ,KAAK,GAAGT,WAAW,CAAC,CAAC;EAE3B,oBACEG,IAAA,CAACL,YAAY;IACXO,kBAAkB,EAAEA,kBAAmB;IACvCK,SAAS,EAAED,KAAK,CAACH,KAAK,CAACA,KAAK,CAAE;IAC9BK,QAAQ,EAAEZ,OAAO,CAACS,IAAI,CAAE;IACxBI,YAAY,EAAEf,gBAAgB,CAACU,IAAI;EAAE,CACtC,CAAC;AAEN,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["iconResourceName","nativeIconEffectRecord","nativeIconTriggerKey","DrawableIcon","spacing","useAppTheme","useMemo","useHostGuard","jsx","_jsx","Icon","accessibilityLabel","color","effect","effectActive","effectTrigger","gradient","name","renderingMode","secondaryColor","size","tertiaryColor","transition","variableValue","theme","effectKey","JSON","stringify","undefined","record","parse","iconColor","iconSize","resourceName"],"sourceRoot":"../../../../src","sources":["atoms/icon/icon.android.tsx"],"mappings":";;AAAA,SAAQA,gBAAgB,EAAEC,sBAAsB,EAAEC,oBAAoB,QAAO,0BAA0B;AACvG,SAAQC,YAAY,QAAO,oCAAoC;AAC/D,SAAQC,OAAO,EAAEC,WAAW,QAAO,mBAAmB;AACtD,SAAQC,OAAO,QAAO,OAAO;AAE7B,SAAQC,YAAY,QAAO,6BAA0B;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAGrD;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,IAAmB,GAAGA,CAAC;EAClCC,kBAAkB;EAClBC,KAAK,GAAG,iBAAiB;EACzBC,MAAM;EACNC,YAAY;EACZC,aAAa;EACbC,QAAQ;EACRC,IAAI;EACJC,aAAa;EACbC,cAAc;EACdC,IAAI,GAAG,KAAK;EACZC,aAAa;EACbC,UAAU;EACVC;AACS,CAAC,KAAK;EACfhB,YAAY,CAAC,MAAM,CAAC;EACpB,MAAMiB,KAAK,GAAGnB,WAAW,CAAC,CAAC;EAC3B,MAAMoB,SAAS,GAAGZ,MAAM,GAAGa,IAAI,CAACC,SAAS,CAACd,MAAM,CAAC,GAAGe,SAAS;EAC7D,MAAMC,MAAM,GAAGvB,OAAO,CAAC,MAAOmB,SAAS,GAAGxB,sBAAsB,CAACyB,IAAI,CAACI,KAAK,CAACL,SAAS,CAAC,CAAC,GAAGG,SAAU,EAAE,CAACH,SAAS,CAAC,CAAC;EAElH,oBACEhB,IAAA,CAACN,YAAY;IACXQ,kBAAkB,EAAEA,kBAAmB;IACvCE,MAAM,EAAEgB,MAAO;IACff,YAAY,EAAEA,YAAa;IAC3BC,aAAa,EAAEb,oBAAoB,CAACa,aAAa,CAAE;IACnDC,QAAQ,EAAEA,QAAS;IACnBe,SAAS,EAAEP,KAAK,CAACZ,KAAK,CAACA,KAAK,CAAE;IAC9BoB,QAAQ,EAAE5B,OAAO,CAACgB,IAAI,CAAE;IACxBF,aAAa,EAAEA,aAAc;IAC7Be,YAAY,EAAEjC,gBAAgB,CAACiB,IAAI,CAAE;IACrCE,cAAc,EAAEA,cAAc,GAAGK,KAAK,CAACZ,KAAK,CAACO,cAAc,CAAC,GAAGS,SAAU;IACzEP,aAAa,EAAEA,aAAa,GAAGG,KAAK,CAACZ,KAAK,CAACS,aAAa,CAAC,GAAGO,SAAU;IACtEN,UAAU,EAAEA,UAAW;IACvBC,aAAa,EAAEA;EAAc,CAC9B,CAAC;AAEN,CAAC","ignoreList":[]}
@@ -1,35 +1,60 @@
1
1
  "use strict";
2
2
 
3
3
  import { Image } from '@expo/ui/swift-ui';
4
- import { accessibilityHidden, frame, accessibilityLabel as labelModifier, resizable } from '@expo/ui/swift-ui/modifiers';
5
- import { iconResourceName } from '@hzblj/expo-native-icons';
4
+ import { accessibilityHidden, frame, imageScale, accessibilityLabel as labelModifier } from '@expo/ui/swift-ui/modifiers';
5
+ import { iconSymbolName, nativeIconEffectRecord, nativeIconTriggerKey } from '@hzblj/expo-native-icons';
6
+ import { symbolStyle } from '@hzblj/kara-native/swift-ui';
6
7
  import { spacing, useAppTheme } from '@hzblj/kara-theme';
7
8
  import { useMemo } from 'react';
8
9
  import { useHostGuard } from "../../hooks/host-context.js";
9
10
  import { jsx as _jsx } from "react/jsx-runtime";
10
11
  /**
11
- * The app's icon from its asset catalog — the template image set the config plugin generated from the SVG, vector data
12
- * kept, so `resizable()` scales it crisply to the token size and the platform tints it.
12
+ * The app's icon as the custom SF Symbol the config plugin generated from the SVG. At the small symbol scale its box is
13
+ * its point size, so the token size is the font size and the box fills the frame, the same size the image was. The
14
+ * `symbolStyle` modifier colours it and plays its effects and transitions, the way `NativeIconView` does in UIKit.
13
15
  */
14
16
  export const Icon = ({
15
17
  accessibilityLabel,
16
18
  color = 'content.primary',
19
+ effect,
20
+ effectActive,
21
+ effectTrigger,
22
+ gradient,
17
23
  name,
24
+ renderingMode,
25
+ secondaryColor,
18
26
  size = 's24',
19
- testID
27
+ tertiaryColor,
28
+ testID,
29
+ transition,
30
+ variableValue
20
31
  }) => {
21
32
  useHostGuard('Icon');
22
33
  const theme = useAppTheme();
23
34
  const side = spacing[size];
24
- const modifiers = useMemo(() => [resizable(), frame({
35
+ const symbol = iconSymbolName(name);
36
+ const effectKey = effect ? JSON.stringify(effect) : undefined;
37
+ const modifiers = useMemo(() => [imageScale('small'), symbolStyle({
38
+ color: theme.color(color),
39
+ effect: effectKey ? nativeIconEffectRecord(JSON.parse(effectKey)) : undefined,
40
+ effectActive,
41
+ effectTrigger: nativeIconTriggerKey(effectTrigger),
42
+ gradient,
43
+ renderingMode,
44
+ secondaryColor: secondaryColor ? theme.color(secondaryColor) : undefined,
45
+ tertiaryColor: tertiaryColor ? theme.color(tertiaryColor) : undefined,
46
+ transition,
47
+ transitionValue: `${symbol}:${variableValue ?? ''}`
48
+ }), frame({
25
49
  height: side,
26
50
  width: side
27
- }), accessibilityLabel ? labelModifier(accessibilityLabel) : accessibilityHidden(true)], [accessibilityLabel, side]);
51
+ }), accessibilityLabel ? labelModifier(accessibilityLabel) : accessibilityHidden(true)], [accessibilityLabel, color, effectActive, effectKey, effectTrigger, gradient, renderingMode, secondaryColor, side, symbol, tertiaryColor, theme, transition, variableValue]);
28
52
  return /*#__PURE__*/_jsx(Image, {
29
- assetName: iconResourceName(name),
30
- color: theme.color(color),
53
+ assetName: symbol,
31
54
  modifiers: modifiers,
32
- testID: testID
55
+ size: side,
56
+ testID: testID,
57
+ variableValue: variableValue
33
58
  });
34
59
  };
35
60
  //# sourceMappingURL=icon.ios.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["Image","accessibilityHidden","frame","accessibilityLabel","labelModifier","resizable","iconResourceName","spacing","useAppTheme","useMemo","useHostGuard","jsx","_jsx","Icon","color","name","size","testID","theme","side","modifiers","height","width","assetName"],"sourceRoot":"../../../../src","sources":["atoms/icon/icon.ios.tsx"],"mappings":";;AAAA,SAAQA,KAAK,QAAO,mBAAmB;AACvC,SAAQC,mBAAmB,EAAEC,KAAK,EAAEC,kBAAkB,IAAIC,aAAa,EAAEC,SAAS,QAAO,6BAA6B;AACtH,SAAQC,gBAAgB,QAAO,0BAA0B;AACzD,SAAQC,OAAO,EAAEC,WAAW,QAAO,mBAAmB;AACtD,SAAQC,OAAO,QAAO,OAAO;AAE7B,SAAQC,YAAY,QAAO,6BAA0B;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAGrD;AACA;AACA;AACA;AACA,OAAO,MAAMC,IAAmB,GAAGA,CAAC;EAClCV,kBAAkB;EAClBW,KAAK,GAAG,iBAAiB;EACzBC,IAAI;EACJC,IAAI,GAAG,KAAK;EACZC;AACS,CAAC,KAAK;EACfP,YAAY,CAAC,MAAM,CAAC;EACpB,MAAMQ,KAAK,GAAGV,WAAW,CAAC,CAAC;EAC3B,MAAMW,IAAI,GAAGZ,OAAO,CAACS,IAAI,CAAC;EAE1B,MAAMI,SAAS,GAAGX,OAAO,CACvB,MAAM,CACJJ,SAAS,CAAC,CAAC,EACXH,KAAK,CAAC;IAACmB,MAAM,EAAEF,IAAI;IAAEG,KAAK,EAAEH;EAAI,CAAC,CAAC,EAClChB,kBAAkB,GAAGC,aAAa,CAACD,kBAAkB,CAAC,GAAGF,mBAAmB,CAAC,IAAI,CAAC,CACnF,EACD,CAACE,kBAAkB,EAAEgB,IAAI,CAC3B,CAAC;EAED,oBAAOP,IAAA,CAACZ,KAAK;IAACuB,SAAS,EAAEjB,gBAAgB,CAACS,IAAI,CAAE;IAACD,KAAK,EAAEI,KAAK,CAACJ,KAAK,CAACA,KAAK,CAAE;IAACM,SAAS,EAAEA,SAAU;IAACH,MAAM,EAAEA;EAAO,CAAE,CAAC;AACtH,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["Image","accessibilityHidden","frame","imageScale","accessibilityLabel","labelModifier","iconSymbolName","nativeIconEffectRecord","nativeIconTriggerKey","symbolStyle","spacing","useAppTheme","useMemo","useHostGuard","jsx","_jsx","Icon","color","effect","effectActive","effectTrigger","gradient","name","renderingMode","secondaryColor","size","tertiaryColor","testID","transition","variableValue","theme","side","symbol","effectKey","JSON","stringify","undefined","modifiers","parse","transitionValue","height","width","assetName"],"sourceRoot":"../../../../src","sources":["atoms/icon/icon.ios.tsx"],"mappings":";;AAAA,SAAQA,KAAK,QAAO,mBAAmB;AACvC,SAAQC,mBAAmB,EAAEC,KAAK,EAAEC,UAAU,EAAEC,kBAAkB,IAAIC,aAAa,QAAO,6BAA6B;AACvH,SAAQC,cAAc,EAAEC,sBAAsB,EAAEC,oBAAoB,QAAO,0BAA0B;AACrG,SAAQC,WAAW,QAAO,6BAA6B;AACvD,SAAQC,OAAO,EAAEC,WAAW,QAAO,mBAAmB;AACtD,SAAQC,OAAO,QAAO,OAAO;AAE7B,SAAQC,YAAY,QAAO,6BAA0B;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAGrD;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,IAAmB,GAAGA,CAAC;EAClCZ,kBAAkB;EAClBa,KAAK,GAAG,iBAAiB;EACzBC,MAAM;EACNC,YAAY;EACZC,aAAa;EACbC,QAAQ;EACRC,IAAI;EACJC,aAAa;EACbC,cAAc;EACdC,IAAI,GAAG,KAAK;EACZC,aAAa;EACbC,MAAM;EACNC,UAAU;EACVC;AACS,CAAC,KAAK;EACfhB,YAAY,CAAC,MAAM,CAAC;EACpB,MAAMiB,KAAK,GAAGnB,WAAW,CAAC,CAAC;EAC3B,MAAMoB,IAAI,GAAGrB,OAAO,CAACe,IAAI,CAAC;EAC1B,MAAMO,MAAM,GAAG1B,cAAc,CAACgB,IAAI,CAAC;EACnC,MAAMW,SAAS,GAAGf,MAAM,GAAGgB,IAAI,CAACC,SAAS,CAACjB,MAAM,CAAC,GAAGkB,SAAS;EAE7D,MAAMC,SAAS,GAAGzB,OAAO,CACvB,MAAM,CACJT,UAAU,CAAC,OAAO,CAAC,EACnBM,WAAW,CAAC;IACVQ,KAAK,EAAEa,KAAK,CAACb,KAAK,CAACA,KAAK,CAAC;IACzBC,MAAM,EAAEe,SAAS,GAAG1B,sBAAsB,CAAC2B,IAAI,CAACI,KAAK,CAACL,SAAS,CAAC,CAAC,GAAGG,SAAS;IAC7EjB,YAAY;IACZC,aAAa,EAAEZ,oBAAoB,CAACY,aAAa,CAAC;IAClDC,QAAQ;IACRE,aAAa;IACbC,cAAc,EAAEA,cAAc,GAAGM,KAAK,CAACb,KAAK,CAACO,cAAc,CAAC,GAAGY,SAAS;IACxEV,aAAa,EAAEA,aAAa,GAAGI,KAAK,CAACb,KAAK,CAACS,aAAa,CAAC,GAAGU,SAAS;IACrER,UAAU;IACVW,eAAe,EAAE,GAAGP,MAAM,IAAIH,aAAa,IAAI,EAAE;EACnD,CAAC,CAAC,EACF3B,KAAK,CAAC;IAACsC,MAAM,EAAET,IAAI;IAAEU,KAAK,EAAEV;EAAI,CAAC,CAAC,EAClC3B,kBAAkB,GAAGC,aAAa,CAACD,kBAAkB,CAAC,GAAGH,mBAAmB,CAAC,IAAI,CAAC,CACnF,EACD,CACEG,kBAAkB,EAClBa,KAAK,EACLE,YAAY,EACZc,SAAS,EACTb,aAAa,EACbC,QAAQ,EACRE,aAAa,EACbC,cAAc,EACdO,IAAI,EACJC,MAAM,EACNN,aAAa,EACbI,KAAK,EACLF,UAAU,EACVC,aAAa,CAEjB,CAAC;EAED,oBAAOd,IAAA,CAACf,KAAK;IAAC0C,SAAS,EAAEV,MAAO;IAACK,SAAS,EAAEA,SAAU;IAACZ,IAAI,EAAEM,IAAK;IAACJ,MAAM,EAAEA,MAAO;IAACE,aAAa,EAAEA;EAAc,CAAE,CAAC;AACrH,CAAC","ignoreList":[]}
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { Group, List as SwiftUIList } from '@expo/ui/swift-ui';
4
4
  import { listRowSeparator, listStyle, refreshable } from '@expo/ui/swift-ui/modifiers';
5
+ import { contentScrollView } from '@hzblj/kara-native/swift-ui';
5
6
  import { useMemo } from 'react';
6
7
  import { useHostGuard } from "../../hooks/host-context.js";
7
8
  import { jsx as _jsx } from "react/jsx-runtime";
@@ -18,7 +19,7 @@ export const List = ({
18
19
  variant = 'insetGrouped'
19
20
  }) => {
20
21
  useHostGuard('List');
21
- const modifiers = useMemo(() => [listStyle(variant), ...(onRefresh ? [refreshable(onRefresh)] : [])], [onRefresh, variant]);
22
+ const modifiers = useMemo(() => [listStyle(variant), contentScrollView(), ...(onRefresh ? [refreshable(onRefresh)] : [])], [onRefresh, variant]);
22
23
  return /*#__PURE__*/_jsx(SwiftUIList, {
23
24
  modifiers: modifiers,
24
25
  testID: testID,
@@ -1 +1 @@
1
- {"version":3,"names":["Group","List","SwiftUIList","listRowSeparator","listStyle","refreshable","useMemo","useHostGuard","jsx","_jsx","NO_SEPARATORS","children","onRefresh","separators","testID","variant","modifiers"],"sourceRoot":"../../../../src","sources":["atoms/list/list.ios.tsx"],"mappings":";;AAAA,SAAQA,KAAK,EAAEC,IAAI,IAAIC,WAAW,QAAO,mBAAmB;AAC5D,SAAQC,gBAAgB,EAAEC,SAAS,EAAuBC,WAAW,QAAO,6BAA6B;AACzG,SAAQC,OAAO,QAAO,OAAO;AAE7B,SAAQC,YAAY,QAAO,6BAA0B;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAGrD;AACA;AACA;AACA;AACA,MAAMC,aAAa,GAAG,CAACP,gBAAgB,CAAC,QAAQ,CAAC,CAAC;AAElD,OAAO,MAAMF,IAAmB,GAAGA,CAAC;EAClCU,QAAQ;EACRC,SAAS;EACTC,UAAU,GAAG,IAAI;EACjBC,MAAM;EACNC,OAAO,GAAG;AACD,CAAC,KAAK;EACfR,YAAY,CAAC,MAAM,CAAC;EAEpB,MAAMS,SAAS,GAAGV,OAAO,CACvB,MAAM,CAACF,SAAS,CAACW,OAAO,CAAC,EAAE,IAAIH,SAAS,GAAG,CAACP,WAAW,CAACO,SAAS,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAC1E,CAACA,SAAS,EAAEG,OAAO,CACrB,CAAC;EAED,oBACEN,IAAA,CAACP,WAAW;IAACc,SAAS,EAAEA,SAAU;IAACF,MAAM,EAAEA,MAAO;IAAAH,QAAA,EAC/CE,UAAU,GAAGF,QAAQ,gBAAGF,IAAA,CAACT,KAAK;MAACgB,SAAS,EAAEN,aAAc;MAAAC,QAAA,EAAEA;IAAQ,CAAQ;EAAC,CACjE,CAAC;AAElB,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["Group","List","SwiftUIList","listRowSeparator","listStyle","refreshable","contentScrollView","useMemo","useHostGuard","jsx","_jsx","NO_SEPARATORS","children","onRefresh","separators","testID","variant","modifiers"],"sourceRoot":"../../../../src","sources":["atoms/list/list.ios.tsx"],"mappings":";;AAAA,SAAQA,KAAK,EAAEC,IAAI,IAAIC,WAAW,QAAO,mBAAmB;AAC5D,SAAQC,gBAAgB,EAAEC,SAAS,EAAuBC,WAAW,QAAO,6BAA6B;AACzG,SAAQC,iBAAiB,QAAO,6BAA6B;AAC7D,SAAQC,OAAO,QAAO,OAAO;AAE7B,SAAQC,YAAY,QAAO,6BAA0B;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAGrD;AACA;AACA;AACA;AACA,MAAMC,aAAa,GAAG,CAACR,gBAAgB,CAAC,QAAQ,CAAC,CAAC;AAElD,OAAO,MAAMF,IAAmB,GAAGA,CAAC;EAClCW,QAAQ;EACRC,SAAS;EACTC,UAAU,GAAG,IAAI;EACjBC,MAAM;EACNC,OAAO,GAAG;AACD,CAAC,KAAK;EACfR,YAAY,CAAC,MAAM,CAAC;EAEpB,MAAMS,SAAS,GAAGV,OAAO,CACvB,MAAM,CAACH,SAAS,CAACY,OAAO,CAAC,EAAEV,iBAAiB,CAAC,CAAC,EAAE,IAAIO,SAAS,GAAG,CAACR,WAAW,CAACQ,SAAS,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAC/F,CAACA,SAAS,EAAEG,OAAO,CACrB,CAAC;EAED,oBACEN,IAAA,CAACR,WAAW;IAACe,SAAS,EAAEA,SAAU;IAACF,MAAM,EAAEA,MAAO;IAAAH,QAAA,EAC/CE,UAAU,GAAGF,QAAQ,gBAAGF,IAAA,CAACV,KAAK;MAACiB,SAAS,EAAEN,aAAc;MAAAC,QAAA,EAAEA;IAAQ,CAAQ;EAAC,CACjE,CAAC;AAElB,CAAC","ignoreList":[]}
@@ -4,23 +4,24 @@ import { NativeIcon } from '@hzblj/expo-native-icons';
4
4
  import { spacing, useAppTheme } from '@hzblj/kara-theme';
5
5
  import { jsx as _jsx } from "react/jsx-runtime";
6
6
  /**
7
- * `@hzblj/expo-native-icons`' `NativeIcon`: a `UIImageView` over the app's asset-catalog icon on iOS, one view drawing
8
- * its vector drawable on Android. What a list row wants, rather than a SwiftUI or Compose host per row.
7
+ * `@hzblj/expo-native-icons`' `NativeIcon`: a `UIImageView` over the app's custom SF Symbol on iOS, one view drawing
8
+ * its vector drawable on Android, with the effects, transitions and rendering modes on both. What a list row wants,
9
+ * rather than a SwiftUI or Compose host per row.
9
10
  */
10
11
  export const RnIcon = ({
11
- accessibilityLabel,
12
12
  color = 'content.primary',
13
- name,
13
+ secondaryColor,
14
14
  size = 's24',
15
- testID
15
+ tertiaryColor,
16
+ ...props
16
17
  }) => {
17
18
  const theme = useAppTheme();
18
19
  return /*#__PURE__*/_jsx(NativeIcon, {
19
- accessibilityLabel: accessibilityLabel,
20
+ ...props,
20
21
  color: theme.color(color),
21
- name: name,
22
+ secondaryColor: secondaryColor ? theme.color(secondaryColor) : undefined,
22
23
  size: spacing[size],
23
- testID: testID
24
+ tertiaryColor: tertiaryColor ? theme.color(tertiaryColor) : undefined
24
25
  });
25
26
  };
26
27
  //# sourceMappingURL=rn-icon.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["NativeIcon","spacing","useAppTheme","jsx","_jsx","RnIcon","accessibilityLabel","color","name","size","testID","theme"],"sourceRoot":"../../../../src","sources":["atoms/rn-icon/rn-icon.tsx"],"mappings":";;AAAA,SAAQA,UAAU,QAAO,0BAA0B;AACnD,SAAQC,OAAO,EAAEC,WAAW,QAAO,mBAAmB;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAItD;AACA;AACA;AACA;AACA,OAAO,MAAMC,MAAuB,GAAGA,CAAC;EACtCC,kBAAkB;EAClBC,KAAK,GAAG,iBAAiB;EACzBC,IAAI;EACJC,IAAI,GAAG,KAAK;EACZC;AACW,CAAC,KAAK;EACjB,MAAMC,KAAK,GAAGT,WAAW,CAAC,CAAC;EAE3B,oBACEE,IAAA,CAACJ,UAAU;IACTM,kBAAkB,EAAEA,kBAAmB;IACvCC,KAAK,EAAEI,KAAK,CAACJ,KAAK,CAACA,KAAK,CAAE;IAC1BC,IAAI,EAAEA,IAAK;IACXC,IAAI,EAAER,OAAO,CAACQ,IAAI,CAAE;IACpBC,MAAM,EAAEA;EAAO,CAChB,CAAC;AAEN,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["NativeIcon","spacing","useAppTheme","jsx","_jsx","RnIcon","color","secondaryColor","size","tertiaryColor","props","theme","undefined"],"sourceRoot":"../../../../src","sources":["atoms/rn-icon/rn-icon.tsx"],"mappings":";;AAAA,SAAQA,UAAU,QAAO,0BAA0B;AACnD,SAAQC,OAAO,EAAEC,WAAW,QAAO,mBAAmB;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAItD;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,MAAuB,GAAGA,CAAC;EACtCC,KAAK,GAAG,iBAAiB;EACzBC,cAAc;EACdC,IAAI,GAAG,KAAK;EACZC,aAAa;EACb,GAAGC;AACQ,CAAC,KAAK;EACjB,MAAMC,KAAK,GAAGT,WAAW,CAAC,CAAC;EAE3B,oBACEE,IAAA,CAACJ,UAAU;IAAA,GACLU,KAAK;IACTJ,KAAK,EAAEK,KAAK,CAACL,KAAK,CAACA,KAAK,CAAE;IAC1BC,cAAc,EAAEA,cAAc,GAAGI,KAAK,CAACL,KAAK,CAACC,cAAc,CAAC,GAAGK,SAAU;IACzEJ,IAAI,EAAEP,OAAO,CAACO,IAAI,CAAE;IACpBC,aAAa,EAAEA,aAAa,GAAGE,KAAK,CAACL,KAAK,CAACG,aAAa,CAAC,GAAGG;EAAU,CACvE,CAAC;AAEN,CAAC","ignoreList":[]}
@@ -45,9 +45,13 @@ export const ScrollEdgeContainer = ({
45
45
  automaticInsets: _automaticInsets,
46
46
  bottomBar,
47
47
  children,
48
+ contentScrollView: _contentScrollView,
48
49
  effect: _effect,
50
+ initialBottomBarHeight: _initialBottomBarHeight,
51
+ initialTopBarHeight: _initialTopBarHeight,
49
52
  testID,
50
53
  topBar,
54
+ topEdgeEffectHidden: _topEdgeEffectHidden,
51
55
  ...sx
52
56
  }) => {
53
57
  const topFilled = useSharedValue(opacity.o0);
@@ -1 +1 @@
1
- {"version":3,"names":["timing","opacity","cloneElement","useCallback","useRef","useAnimatedStyle","useSharedValue","withTiming","Box","jsx","_jsx","jsxs","_jsxs","EDGE_SLOP","FILL","EdgeBar","children","filled","fill","value","bg","bottom","left","pointerEvents","position","right","style","top","ScrollEdgeContainer","automaticInsets","_automaticInsets","bottomBar","effect","_effect","testID","topBar","sx","topFilled","o0","bottomFilled","metrics","content","offset","viewport","state","flex","onContentSizeChange","onLayout","onScroll","scrollEventThrottle","props","update","current","o100","scrollable","width","height","event","nativeEvent","layout","contentOffset","y"],"sourceRoot":"../../../../src","sources":["molecules/scroll-edge-container/scroll-edge-container.android.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["timing","opacity","cloneElement","useCallback","useRef","useAnimatedStyle","useSharedValue","withTiming","Box","jsx","_jsx","jsxs","_jsxs","EDGE_SLOP","FILL","EdgeBar","children","filled","fill","value","bg","bottom","left","pointerEvents","position","right","style","top","ScrollEdgeContainer","automaticInsets","_automaticInsets","bottomBar","contentScrollView","_contentScrollView","effect","_effect","initialBottomBarHeight","_initialBottomBarHeight","initialTopBarHeight","_initialTopBarHeight","testID","topBar","topEdgeEffectHidden","_topEdgeEffectHidden","sx","topFilled","o0","bottomFilled","metrics","content","offset","viewport","state","flex","onContentSizeChange","onLayout","onScroll","scrollEventThrottle","props","update","current","o100","scrollable","width","height","event","nativeEvent","layout","contentOffset","y"],"sourceRoot":"../../../../src","sources":["molecules/scroll-edge-container/scroll-edge-container.android.tsx"],"mappings":"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","ignoreList":[]}
@@ -11,19 +11,27 @@ export const ScrollEdgeContainer = ({
11
11
  automaticInsets,
12
12
  bottomBar,
13
13
  children,
14
+ contentScrollView,
14
15
  effect,
16
+ initialBottomBarHeight,
17
+ initialTopBarHeight,
15
18
  testID,
16
19
  topBar,
20
+ topEdgeEffectHidden,
17
21
  ...sx
18
22
  }) => {
19
23
  const style = useSx(sx);
20
24
  return /*#__PURE__*/_jsx(NativeScrollEdgeContainer, {
21
25
  automaticInsets: automaticInsets,
22
26
  bottomBar: bottomBar,
27
+ contentScrollView: contentScrollView,
23
28
  effect: effect,
29
+ initialBottomBarHeight: initialBottomBarHeight,
30
+ initialTopBarHeight: initialTopBarHeight,
24
31
  style: style,
25
32
  testID: testID,
26
33
  topBar: topBar,
34
+ topEdgeEffectHidden: topEdgeEffectHidden,
27
35
  children: children
28
36
  });
29
37
  };
@@ -1 +1 @@
1
- {"version":3,"names":["ScrollEdgeContainer","NativeScrollEdgeContainer","useSx","jsx","_jsx","automaticInsets","bottomBar","children","effect","testID","topBar","sx","style"],"sourceRoot":"../../../../src","sources":["molecules/scroll-edge-container/scroll-edge-container.ios.tsx"],"mappings":";;AAAA,SAAQA,mBAAmB,IAAIC,yBAAyB,QAAO,6BAA6B;AAC5F,SAAQC,KAAK,QAAO,gBAAgB;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAGpC;AACA;AACA;AACA;AACA,OAAO,MAAMJ,mBAAiD,GAAGA,CAAC;EAChEK,eAAe;EACfC,SAAS;EACTC,QAAQ;EACRC,MAAM;EACNC,MAAM;EACNC,MAAM;EACN,GAAGC;AACqB,CAAC,KAAK;EAC9B,MAAMC,KAAK,GAAGV,KAAK,CAACS,EAAE,CAAC;EAEvB,oBACEP,IAAA,CAACH,yBAAyB;IACxBI,eAAe,EAAEA,eAAgB;IACjCC,SAAS,EAAEA,SAAU;IACrBE,MAAM,EAAEA,MAAO;IACfI,KAAK,EAAEA,KAAM;IACbH,MAAM,EAAEA,MAAO;IACfC,MAAM,EAAEA,MAAO;IAAAH,QAAA,EAEdA;EAAQ,CACgB,CAAC;AAEhC,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["ScrollEdgeContainer","NativeScrollEdgeContainer","useSx","jsx","_jsx","automaticInsets","bottomBar","children","contentScrollView","effect","initialBottomBarHeight","initialTopBarHeight","testID","topBar","topEdgeEffectHidden","sx","style"],"sourceRoot":"../../../../src","sources":["molecules/scroll-edge-container/scroll-edge-container.ios.tsx"],"mappings":";;AAAA,SAAQA,mBAAmB,IAAIC,yBAAyB,QAAO,6BAA6B;AAC5F,SAAQC,KAAK,QAAO,gBAAgB;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAGpC;AACA;AACA;AACA;AACA,OAAO,MAAMJ,mBAAiD,GAAGA,CAAC;EAChEK,eAAe;EACfC,SAAS;EACTC,QAAQ;EACRC,iBAAiB;EACjBC,MAAM;EACNC,sBAAsB;EACtBC,mBAAmB;EACnBC,MAAM;EACNC,MAAM;EACNC,mBAAmB;EACnB,GAAGC;AACqB,CAAC,KAAK;EAC9B,MAAMC,KAAK,GAAGd,KAAK,CAACa,EAAE,CAAC;EAEvB,oBACEX,IAAA,CAACH,yBAAyB;IACxBI,eAAe,EAAEA,eAAgB;IACjCC,SAAS,EAAEA,SAAU;IACrBE,iBAAiB,EAAEA,iBAAkB;IACrCC,MAAM,EAAEA,MAAO;IACfC,sBAAsB,EAAEA,sBAAuB;IAC/CC,mBAAmB,EAAEA,mBAAoB;IACzCK,KAAK,EAAEA,KAAM;IACbJ,MAAM,EAAEA,MAAO;IACfC,MAAM,EAAEA,MAAO;IACfC,mBAAmB,EAAEA,mBAAoB;IAAAP,QAAA,EAExCA;EAAQ,CACgB,CAAC;AAEhC,CAAC","ignoreList":[]}
@@ -1,6 +1,7 @@
1
1
  import type { IconComponent } from './icon.types';
2
2
  /**
3
- * The app's icon from its asset catalog — the template image set the config plugin generated from the SVG, vector data
4
- * kept, so `resizable()` scales it crisply to the token size and the platform tints it.
3
+ * The app's icon as the custom SF Symbol the config plugin generated from the SVG. At the small symbol scale its box is
4
+ * its point size, so the token size is the font size and the box fills the frame, the same size the image was. The
5
+ * `symbolStyle` modifier colours it and plays its effects and transitions, the way `NativeIconView` does in UIKit.
5
6
  */
6
7
  export declare const Icon: IconComponent;
@@ -1,4 +1,4 @@
1
- import type { NativeIconName } from '@hzblj/expo-native-icons';
1
+ import type { NativeIconEffect, NativeIconEffectTrigger, NativeIconName, NativeIconRenderingMode, NativeIconTransition } from '@hzblj/expo-native-icons';
2
2
  import type { ColorToken, SpaceSize } from '@hzblj/kara-theme';
3
3
  import type { ReactNode } from 'react';
4
4
  /**
@@ -7,20 +7,54 @@ import type { ReactNode } from 'react';
7
7
  * those names type-check, so an icon removed from the folder fails at every call site; before that, any string.
8
8
  */
9
9
  export type IconName = NativeIconName;
10
+ /** An SF Symbols effect for `Icon` and `RnIcon`: `{type: 'bounce'}`, `{type: 'variableColor', fill: 'iterative'}`… */
11
+ export type IconEffect = NativeIconEffect;
12
+ /** How an icon's layers are coloured. */
13
+ export type IconRenderingMode = NativeIconRenderingMode;
14
+ /** How an icon changes into another when its `name` changes. */
15
+ export type IconTransition = NativeIconTransition;
10
16
  /**
11
- * One of the app's icons, in a host: SwiftUI `Image` from the asset catalog on iOS, Material's `Icon` with the vector
12
- * drawable on Android. `RnIcon` draws the same asset outside one.
17
+ * One of the app's icons, in a host: SwiftUI `Image` of its custom SF Symbol on iOS, Material's `Icon` with the vector
18
+ * drawable on Android. `RnIcon` draws the same asset outside one. Both play the SF Symbols effects and transitions and
19
+ * draw the rendering modes and variable values, on both platforms.
13
20
  */
14
21
  export type IconProps = {
15
22
  /** What a screen reader says. Unset, the icon is decorative and hidden from it. */
16
23
  accessibilityLabel?: string;
17
- /** The icon's tint. `content.primary` by default. */
24
+ /** The icon's tint, and the primary colour of the other rendering modes. `content.primary` by default. */
18
25
  color?: ColorToken;
26
+ /**
27
+ * An SF Symbols effect: `bounce`, `pulse`, `variableColor`, `wiggle`, `rotate`, `breathe`, and the states `scale`,
28
+ * `appear` and `disappear`. Plays once per change of `effectTrigger`, or while `effectActive`.
29
+ */
30
+ effect?: IconEffect;
31
+ /** Runs `effect` while true; without an `effectTrigger`, true by default. */
32
+ effectActive?: boolean;
33
+ /** Plays `effect` once whenever this value changes, never on mount. */
34
+ effectTrigger?: NativeIconEffectTrigger;
35
+ /** Shades each layer's colour into a soft gradient, as SF Symbols does on iOS 26. iOS 26 and Android. */
36
+ gradient?: boolean;
19
37
  /** Which of the app's icons: a key of `NativeIcons`, one per SVG in the icon folder. */
20
38
  name: IconName;
39
+ /**
40
+ * How the layers are coloured: `monochrome` (the default) tints them all, `hierarchical` draws secondary and tertiary
41
+ * layers fainter, `palette` gives them `secondaryColor` and `tertiaryColor`, `multicolor` keeps the SVG's own fills.
42
+ */
43
+ renderingMode?: IconRenderingMode;
44
+ /** The `palette` mode's colour for secondary layers. `color` by default. */
45
+ secondaryColor?: ColorToken;
21
46
  /** Its width and height, a spacing token. `s24` by default. */
22
47
  size?: SpaceSize;
48
+ /** The `palette` mode's colour for tertiary layers. `secondaryColor` by default. */
49
+ tertiaryColor?: ColorToken;
23
50
  /** Test identifier, forwarded to the native view on iOS. Android ignores it. */
24
51
  testID?: string;
52
+ /**
53
+ * Animates a change of `name`: `replace`, `replaceUpUp`, `replaceOffUp`, `magicReplace` or `automatic`. With one set,
54
+ * a new `variableValue` eases in too. Unset, the icon swaps at once.
55
+ */
56
+ transition?: IconTransition;
57
+ /** From 0 to 1: switches on the SVG's `data-variable` layers whose threshold it passes, the rest dimmed. */
58
+ variableValue?: number;
25
59
  };
26
60
  export type IconComponent = (props: IconProps) => ReactNode;
@@ -9,6 +9,8 @@ export type ListVariant = 'insetGrouped' | 'plain';
9
9
  *
10
10
  * Rows are separated for you (SwiftUI's own separators, a `Divider` between rows on Android), so a `Divider` among
11
11
  * the children is one too many: on iOS it becomes an empty row of its own.
12
+ *
13
+ * On iOS the list is its screen's content scroll view, so a native-stack large title collapses as it scrolls.
12
14
  */
13
15
  export type ListProps = {
14
16
  /** The rows: native views, one row each. */
@@ -1,6 +1,7 @@
1
1
  import type { RnIconComponent } from './rn-icon.types';
2
2
  /**
3
- * `@hzblj/expo-native-icons`' `NativeIcon`: a `UIImageView` over the app's asset-catalog icon on iOS, one view drawing
4
- * its vector drawable on Android. What a list row wants, rather than a SwiftUI or Compose host per row.
3
+ * `@hzblj/expo-native-icons`' `NativeIcon`: a `UIImageView` over the app's custom SF Symbol on iOS, one view drawing
4
+ * its vector drawable on Android, with the effects, transitions and rendering modes on both. What a list row wants,
5
+ * rather than a SwiftUI or Compose host per row.
5
6
  */
6
7
  export declare const RnIcon: RnIconComponent;
@@ -21,11 +21,19 @@ export type ScrollEdgeContainerProps = ResponsiveViewSx & {
21
21
  bottomBar?: ReactNode;
22
22
  /** Exactly one React Native scroll view: `RnScrollView`, `RnFlatList`, `RnSectionList`. */
23
23
  children: ReactElement<ScrollEdgeScrollableProps>;
24
+ /** iOS 26: the tab bar minimises as this scroll view scrolls, not as the screen's first one does. */
25
+ contentScrollView?: boolean;
24
26
  /** iOS 26: how hard the edge cuts. `soft` by default. */
25
27
  effect?: ScrollEdgeEffect;
28
+ /** iOS: the bottom bar's height before it is measured, so the first frame already has the inset. */
29
+ initialBottomBarHeight?: number;
30
+ /** iOS: the top bar's height before it is measured, so the first frame's content starts below the bar. */
31
+ initialTopBarHeight?: number;
26
32
  /** Test identifier, forwarded to the container view. */
27
33
  testID?: string;
28
34
  /** Laid over the scroll view's top edge on iOS; stacked above it on Android, filled once content scrolls under it. */
29
35
  topBar?: ReactNode;
36
+ /** iOS 26: hides the top edge effect, e.g. while a cover image sits under the top bar. */
37
+ topEdgeEffectHidden?: boolean;
30
38
  };
31
39
  export type ScrollEdgeContainerComponent = (props: ScrollEdgeContainerProps) => ReactNode;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hzblj/kara-components",
3
- "version": "0.23.1",
3
+ "version": "0.25.0",
4
4
  "description": "The atoms, molecules, organisms and templates of @hzblj/kara-ui — real SwiftUI and Jetpack Compose views through @expo/ui.",
5
5
  "author": "Jan Blazej",
6
6
  "license": "MIT",
@@ -64,11 +64,11 @@
64
64
  ]
65
65
  },
66
66
  "dependencies": {
67
- "@hzblj/expo-native-icons": "^0.1.0",
67
+ "@hzblj/expo-native-icons": "^0.2.0",
68
68
  "@hzblj/expo-rich-haptics": "^0.1.0",
69
- "@hzblj/kara-native": "^0.23.1",
70
- "@hzblj/kara-sx": "^0.23.1",
71
- "@hzblj/kara-theme": "^0.23.1",
69
+ "@hzblj/kara-native": "^0.25.0",
70
+ "@hzblj/kara-sx": "^0.25.0",
71
+ "@hzblj/kara-theme": "^0.25.0",
72
72
  "sf-symbols-typescript": "^2.2.0"
73
73
  },
74
74
  "peerDependencies": {
@@ -1,21 +1,51 @@
1
- import {iconResourceName} from '@hzblj/expo-native-icons'
1
+ import {iconResourceName, nativeIconEffectRecord, nativeIconTriggerKey} from '@hzblj/expo-native-icons'
2
2
  import {DrawableIcon} from '@hzblj/kara-native/jetpack-compose'
3
3
  import {spacing, useAppTheme} from '@hzblj/kara-theme'
4
+ import {useMemo} from 'react'
4
5
 
5
6
  import {useHostGuard} from '../../hooks/host-context'
6
7
  import type {IconComponent, IconProps} from './icon.types'
7
8
 
8
- /** The app's icon as the vector drawable the config plugin generated from the SVG, drawn by Material's `Icon`. */
9
- export const Icon: IconComponent = ({accessibilityLabel, color = 'content.primary', name, size = 's24'}: IconProps) => {
9
+ /**
10
+ * The app's icon as the vector drawable the config plugin generated from the SVG, drawn by Material's `Icon`; with an
11
+ * effect, a transition, a rendering mode, a variable value or a gradient, by `@hzblj/expo-native-icons`' view, which
12
+ * plays them.
13
+ */
14
+ export const Icon: IconComponent = ({
15
+ accessibilityLabel,
16
+ color = 'content.primary',
17
+ effect,
18
+ effectActive,
19
+ effectTrigger,
20
+ gradient,
21
+ name,
22
+ renderingMode,
23
+ secondaryColor,
24
+ size = 's24',
25
+ tertiaryColor,
26
+ transition,
27
+ variableValue,
28
+ }: IconProps) => {
10
29
  useHostGuard('Icon')
11
30
  const theme = useAppTheme()
31
+ const effectKey = effect ? JSON.stringify(effect) : undefined
32
+ const record = useMemo(() => (effectKey ? nativeIconEffectRecord(JSON.parse(effectKey)) : undefined), [effectKey])
12
33
 
13
34
  return (
14
35
  <DrawableIcon
15
36
  accessibilityLabel={accessibilityLabel}
37
+ effect={record}
38
+ effectActive={effectActive}
39
+ effectTrigger={nativeIconTriggerKey(effectTrigger)}
40
+ gradient={gradient}
16
41
  iconColor={theme.color(color)}
17
42
  iconSize={spacing[size]}
43
+ renderingMode={renderingMode}
18
44
  resourceName={iconResourceName(name)}
45
+ secondaryColor={secondaryColor ? theme.color(secondaryColor) : undefined}
46
+ tertiaryColor={tertiaryColor ? theme.color(tertiaryColor) : undefined}
47
+ transition={transition}
48
+ variableValue={variableValue}
19
49
  />
20
50
  )
21
51
  }
@@ -1,6 +1,7 @@
1
1
  import {Image} from '@expo/ui/swift-ui'
2
- import {accessibilityHidden, frame, accessibilityLabel as labelModifier, resizable} from '@expo/ui/swift-ui/modifiers'
3
- import {iconResourceName} from '@hzblj/expo-native-icons'
2
+ import {accessibilityHidden, frame, imageScale, accessibilityLabel as labelModifier} from '@expo/ui/swift-ui/modifiers'
3
+ import {iconSymbolName, nativeIconEffectRecord, nativeIconTriggerKey} from '@hzblj/expo-native-icons'
4
+ import {symbolStyle} from '@hzblj/kara-native/swift-ui'
4
5
  import {spacing, useAppTheme} from '@hzblj/kara-theme'
5
6
  import {useMemo} from 'react'
6
7
 
@@ -8,28 +9,67 @@ import {useHostGuard} from '../../hooks/host-context'
8
9
  import type {IconComponent, IconProps} from './icon.types'
9
10
 
10
11
  /**
11
- * The app's icon from its asset catalog — the template image set the config plugin generated from the SVG, vector data
12
- * kept, so `resizable()` scales it crisply to the token size and the platform tints it.
12
+ * The app's icon as the custom SF Symbol the config plugin generated from the SVG. At the small symbol scale its box is
13
+ * its point size, so the token size is the font size and the box fills the frame, the same size the image was. The
14
+ * `symbolStyle` modifier colours it and plays its effects and transitions, the way `NativeIconView` does in UIKit.
13
15
  */
14
16
  export const Icon: IconComponent = ({
15
17
  accessibilityLabel,
16
18
  color = 'content.primary',
19
+ effect,
20
+ effectActive,
21
+ effectTrigger,
22
+ gradient,
17
23
  name,
24
+ renderingMode,
25
+ secondaryColor,
18
26
  size = 's24',
27
+ tertiaryColor,
19
28
  testID,
29
+ transition,
30
+ variableValue,
20
31
  }: IconProps) => {
21
32
  useHostGuard('Icon')
22
33
  const theme = useAppTheme()
23
34
  const side = spacing[size]
35
+ const symbol = iconSymbolName(name)
36
+ const effectKey = effect ? JSON.stringify(effect) : undefined
24
37
 
25
38
  const modifiers = useMemo(
26
39
  () => [
27
- resizable(),
40
+ imageScale('small'),
41
+ symbolStyle({
42
+ color: theme.color(color),
43
+ effect: effectKey ? nativeIconEffectRecord(JSON.parse(effectKey)) : undefined,
44
+ effectActive,
45
+ effectTrigger: nativeIconTriggerKey(effectTrigger),
46
+ gradient,
47
+ renderingMode,
48
+ secondaryColor: secondaryColor ? theme.color(secondaryColor) : undefined,
49
+ tertiaryColor: tertiaryColor ? theme.color(tertiaryColor) : undefined,
50
+ transition,
51
+ transitionValue: `${symbol}:${variableValue ?? ''}`,
52
+ }),
28
53
  frame({height: side, width: side}),
29
54
  accessibilityLabel ? labelModifier(accessibilityLabel) : accessibilityHidden(true),
30
55
  ],
31
- [accessibilityLabel, side]
56
+ [
57
+ accessibilityLabel,
58
+ color,
59
+ effectActive,
60
+ effectKey,
61
+ effectTrigger,
62
+ gradient,
63
+ renderingMode,
64
+ secondaryColor,
65
+ side,
66
+ symbol,
67
+ tertiaryColor,
68
+ theme,
69
+ transition,
70
+ variableValue,
71
+ ]
32
72
  )
33
73
 
34
- return <Image assetName={iconResourceName(name)} color={theme.color(color)} modifiers={modifiers} testID={testID} />
74
+ return <Image assetName={symbol} modifiers={modifiers} size={side} testID={testID} variableValue={variableValue} />
35
75
  }
@@ -1,4 +1,10 @@
1
- import type {NativeIconName} from '@hzblj/expo-native-icons'
1
+ import type {
2
+ NativeIconEffect,
3
+ NativeIconEffectTrigger,
4
+ NativeIconName,
5
+ NativeIconRenderingMode,
6
+ NativeIconTransition,
7
+ } from '@hzblj/expo-native-icons'
2
8
  import type {ColorToken, SpaceSize} from '@hzblj/kara-theme'
3
9
  import type {ReactNode} from 'react'
4
10
 
@@ -9,21 +15,58 @@ import type {ReactNode} from 'react'
9
15
  */
10
16
  export type IconName = NativeIconName
11
17
 
18
+ /** An SF Symbols effect for `Icon` and `RnIcon`: `{type: 'bounce'}`, `{type: 'variableColor', fill: 'iterative'}`… */
19
+ export type IconEffect = NativeIconEffect
20
+
21
+ /** How an icon's layers are coloured. */
22
+ export type IconRenderingMode = NativeIconRenderingMode
23
+
24
+ /** How an icon changes into another when its `name` changes. */
25
+ export type IconTransition = NativeIconTransition
26
+
12
27
  /**
13
- * One of the app's icons, in a host: SwiftUI `Image` from the asset catalog on iOS, Material's `Icon` with the vector
14
- * drawable on Android. `RnIcon` draws the same asset outside one.
28
+ * One of the app's icons, in a host: SwiftUI `Image` of its custom SF Symbol on iOS, Material's `Icon` with the vector
29
+ * drawable on Android. `RnIcon` draws the same asset outside one. Both play the SF Symbols effects and transitions and
30
+ * draw the rendering modes and variable values, on both platforms.
15
31
  */
16
32
  export type IconProps = {
17
33
  /** What a screen reader says. Unset, the icon is decorative and hidden from it. */
18
34
  accessibilityLabel?: string
19
- /** The icon's tint. `content.primary` by default. */
35
+ /** The icon's tint, and the primary colour of the other rendering modes. `content.primary` by default. */
20
36
  color?: ColorToken
37
+ /**
38
+ * An SF Symbols effect: `bounce`, `pulse`, `variableColor`, `wiggle`, `rotate`, `breathe`, and the states `scale`,
39
+ * `appear` and `disappear`. Plays once per change of `effectTrigger`, or while `effectActive`.
40
+ */
41
+ effect?: IconEffect
42
+ /** Runs `effect` while true; without an `effectTrigger`, true by default. */
43
+ effectActive?: boolean
44
+ /** Plays `effect` once whenever this value changes, never on mount. */
45
+ effectTrigger?: NativeIconEffectTrigger
46
+ /** Shades each layer's colour into a soft gradient, as SF Symbols does on iOS 26. iOS 26 and Android. */
47
+ gradient?: boolean
21
48
  /** Which of the app's icons: a key of `NativeIcons`, one per SVG in the icon folder. */
22
49
  name: IconName
50
+ /**
51
+ * How the layers are coloured: `monochrome` (the default) tints them all, `hierarchical` draws secondary and tertiary
52
+ * layers fainter, `palette` gives them `secondaryColor` and `tertiaryColor`, `multicolor` keeps the SVG's own fills.
53
+ */
54
+ renderingMode?: IconRenderingMode
55
+ /** The `palette` mode's colour for secondary layers. `color` by default. */
56
+ secondaryColor?: ColorToken
23
57
  /** Its width and height, a spacing token. `s24` by default. */
24
58
  size?: SpaceSize
59
+ /** The `palette` mode's colour for tertiary layers. `secondaryColor` by default. */
60
+ tertiaryColor?: ColorToken
25
61
  /** Test identifier, forwarded to the native view on iOS. Android ignores it. */
26
62
  testID?: string
63
+ /**
64
+ * Animates a change of `name`: `replace`, `replaceUpUp`, `replaceOffUp`, `magicReplace` or `automatic`. With one set,
65
+ * a new `variableValue` eases in too. Unset, the icon swaps at once.
66
+ */
67
+ transition?: IconTransition
68
+ /** From 0 to 1: switches on the SVG's `data-variable` layers whose threshold it passes, the rest dimmed. */
69
+ variableValue?: number
27
70
  }
28
71
 
29
72
  export type IconComponent = (props: IconProps) => ReactNode
@@ -1,5 +1,6 @@
1
1
  import {Group, List as SwiftUIList} from '@expo/ui/swift-ui'
2
2
  import {listRowSeparator, listStyle, type ModifierConfig, refreshable} from '@expo/ui/swift-ui/modifiers'
3
+ import {contentScrollView} from '@hzblj/kara-native/swift-ui'
3
4
  import {useMemo} from 'react'
4
5
 
5
6
  import {useHostGuard} from '../../hooks/host-context'
@@ -21,7 +22,7 @@ export const List: ListComponent = ({
21
22
  useHostGuard('List')
22
23
 
23
24
  const modifiers = useMemo<ModifierConfig[]>(
24
- () => [listStyle(variant), ...(onRefresh ? [refreshable(onRefresh)] : [])],
25
+ () => [listStyle(variant), contentScrollView(), ...(onRefresh ? [refreshable(onRefresh)] : [])],
25
26
  [onRefresh, variant]
26
27
  )
27
28
 
@@ -11,6 +11,8 @@ export type ListVariant = 'insetGrouped' | 'plain'
11
11
  *
12
12
  * Rows are separated for you (SwiftUI's own separators, a `Divider` between rows on Android), so a `Divider` among
13
13
  * the children is one too many: on iOS it becomes an empty row of its own.
14
+ *
15
+ * On iOS the list is its screen's content scroll view, so a native-stack large title collapses as it scrolls.
14
16
  */
15
17
  export type ListProps = {
16
18
  /** The rows: native views, one row each. */
@@ -4,25 +4,26 @@ import {spacing, useAppTheme} from '@hzblj/kara-theme'
4
4
  import type {RnIconComponent, RnIconProps} from './rn-icon.types'
5
5
 
6
6
  /**
7
- * `@hzblj/expo-native-icons`' `NativeIcon`: a `UIImageView` over the app's asset-catalog icon on iOS, one view drawing
8
- * its vector drawable on Android. What a list row wants, rather than a SwiftUI or Compose host per row.
7
+ * `@hzblj/expo-native-icons`' `NativeIcon`: a `UIImageView` over the app's custom SF Symbol on iOS, one view drawing
8
+ * its vector drawable on Android, with the effects, transitions and rendering modes on both. What a list row wants,
9
+ * rather than a SwiftUI or Compose host per row.
9
10
  */
10
11
  export const RnIcon: RnIconComponent = ({
11
- accessibilityLabel,
12
12
  color = 'content.primary',
13
- name,
13
+ secondaryColor,
14
14
  size = 's24',
15
- testID,
15
+ tertiaryColor,
16
+ ...props
16
17
  }: RnIconProps) => {
17
18
  const theme = useAppTheme()
18
19
 
19
20
  return (
20
21
  <NativeIcon
21
- accessibilityLabel={accessibilityLabel}
22
+ {...props}
22
23
  color={theme.color(color)}
23
- name={name}
24
+ secondaryColor={secondaryColor ? theme.color(secondaryColor) : undefined}
24
25
  size={spacing[size]}
25
- testID={testID}
26
+ tertiaryColor={tertiaryColor ? theme.color(tertiaryColor) : undefined}
26
27
  />
27
28
  )
28
29
  }
@@ -50,9 +50,13 @@ export const ScrollEdgeContainer: ScrollEdgeContainerComponent = ({
50
50
  automaticInsets: _automaticInsets,
51
51
  bottomBar,
52
52
  children,
53
+ contentScrollView: _contentScrollView,
53
54
  effect: _effect,
55
+ initialBottomBarHeight: _initialBottomBarHeight,
56
+ initialTopBarHeight: _initialTopBarHeight,
54
57
  testID,
55
58
  topBar,
59
+ topEdgeEffectHidden: _topEdgeEffectHidden,
56
60
  ...sx
57
61
  }: ScrollEdgeContainerProps) => {
58
62
  const topFilled = useSharedValue<number>(opacity.o0)
@@ -10,9 +10,13 @@ export const ScrollEdgeContainer: ScrollEdgeContainerComponent = ({
10
10
  automaticInsets,
11
11
  bottomBar,
12
12
  children,
13
+ contentScrollView,
13
14
  effect,
15
+ initialBottomBarHeight,
16
+ initialTopBarHeight,
14
17
  testID,
15
18
  topBar,
19
+ topEdgeEffectHidden,
16
20
  ...sx
17
21
  }: ScrollEdgeContainerProps) => {
18
22
  const style = useSx(sx)
@@ -21,10 +25,14 @@ export const ScrollEdgeContainer: ScrollEdgeContainerComponent = ({
21
25
  <NativeScrollEdgeContainer
22
26
  automaticInsets={automaticInsets}
23
27
  bottomBar={bottomBar}
28
+ contentScrollView={contentScrollView}
24
29
  effect={effect}
30
+ initialBottomBarHeight={initialBottomBarHeight}
31
+ initialTopBarHeight={initialTopBarHeight}
25
32
  style={style}
26
33
  testID={testID}
27
34
  topBar={topBar}
35
+ topEdgeEffectHidden={topEdgeEffectHidden}
28
36
  >
29
37
  {children}
30
38
  </NativeScrollEdgeContainer>
@@ -23,12 +23,20 @@ export type ScrollEdgeContainerProps = ResponsiveViewSx & {
23
23
  bottomBar?: ReactNode
24
24
  /** Exactly one React Native scroll view: `RnScrollView`, `RnFlatList`, `RnSectionList`. */
25
25
  children: ReactElement<ScrollEdgeScrollableProps>
26
+ /** iOS 26: the tab bar minimises as this scroll view scrolls, not as the screen's first one does. */
27
+ contentScrollView?: boolean
26
28
  /** iOS 26: how hard the edge cuts. `soft` by default. */
27
29
  effect?: ScrollEdgeEffect
30
+ /** iOS: the bottom bar's height before it is measured, so the first frame already has the inset. */
31
+ initialBottomBarHeight?: number
32
+ /** iOS: the top bar's height before it is measured, so the first frame's content starts below the bar. */
33
+ initialTopBarHeight?: number
28
34
  /** Test identifier, forwarded to the container view. */
29
35
  testID?: string
30
36
  /** Laid over the scroll view's top edge on iOS; stacked above it on Android, filled once content scrolls under it. */
31
37
  topBar?: ReactNode
38
+ /** iOS 26: hides the top edge effect, e.g. while a cover image sits under the top bar. */
39
+ topEdgeEffectHidden?: boolean
32
40
  }
33
41
 
34
42
  export type ScrollEdgeContainerComponent = (props: ScrollEdgeContainerProps) => ReactNode