@hzblj/kara-components 0.8.0 → 0.9.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @hzblj/kara-components
2
2
 
3
+ ## 0.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#21](https://github.com/hzblj/kara-ui/pull/21) [`356c00f`](https://github.com/hzblj/kara-ui/commit/356c00f76eee8323c4eb65ed4cbcda121c3af627) Thanks [@hzblj](https://github.com/hzblj)! - `TextField`'s `error` takes a message: `error="A postcode has five digits."` shows it under the field — Material's supporting text beside its error icon on Android — so an error never rests on colour alone, which in dark mode Material draws a pale red. `error` alone still marks the field. kara's glyphs gain `error` for it.
8
+
9
+ `Tabs` on iOS tint their icons: the selected one takes the accent and the rest the label colour. Expo Router tints an asset-catalog icon only when both states have an icon colour, so with the accent alone every icon kept its SVG's black, selected or not, in dark mode too.
10
+
11
+ `Surface` on iOS sits on `surface.primary` unless told otherwise, as it does on Android; a plain one drew nothing behind its content. `Progress` with `circular` and a `value` is a ring that fills on iOS — a SwiftUI capacity `Gauge` — where a circular `ProgressView` ignored the value and spun.
12
+
13
+ ### Patch Changes
14
+
15
+ - Updated dependencies [[`356c00f`](https://github.com/hzblj/kara-ui/commit/356c00f76eee8323c4eb65ed4cbcda121c3af627)]:
16
+ - @hzblj/kara-native@0.9.0
17
+ - @hzblj/kara-theme@0.9.0
18
+ - @hzblj/kara-sx@0.9.0
19
+
3
20
  ## 0.8.0
4
21
 
5
22
  ### Minor Changes
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
 
3
- import { ProgressView } from '@expo/ui/swift-ui';
4
- import { progressViewStyle, tint } from '@expo/ui/swift-ui/modifiers';
3
+ import { Gauge, ProgressView } from '@expo/ui/swift-ui';
4
+ import { gaugeStyle, progressViewStyle, tint } from '@expo/ui/swift-ui/modifiers';
5
5
  import { useAppTheme } from '@hzblj/kara-theme';
6
6
  import { useMemo } from 'react';
7
7
  import { useHostGuard } from "../../host-context.js";
@@ -12,8 +12,14 @@ export const Progress = ({
12
12
  }) => {
13
13
  useHostGuard('Progress');
14
14
  const theme = useAppTheme();
15
- const modifiers = useMemo(() => [progressViewStyle(circular ? 'circular' : 'linear'), tint(theme.color('fill.accent.primary'))], [circular, theme]);
16
- return /*#__PURE__*/_jsx(ProgressView, {
15
+ const ring = circular && value !== undefined;
16
+ const modifiers = useMemo(() => [ring ? gaugeStyle('circularCapacity') : progressViewStyle(circular ? 'circular' : 'linear'), tint(theme.color('fill.accent.primary'))], [circular, ring, theme]);
17
+
18
+ // SwiftUI's circular `ProgressView` ignores its value on iOS and spins; a ring that fills is a capacity `Gauge`.
19
+ return ring ? /*#__PURE__*/_jsx(Gauge, {
20
+ modifiers: modifiers,
21
+ value: value
22
+ }) : /*#__PURE__*/_jsx(ProgressView, {
17
23
  modifiers: modifiers,
18
24
  value: value ?? null
19
25
  });
@@ -1 +1 @@
1
- {"version":3,"names":["ProgressView","progressViewStyle","tint","useAppTheme","useMemo","useHostGuard","jsx","_jsx","Progress","circular","value","theme","modifiers","color"],"sourceRoot":"../../../../src","sources":["atoms/progress/progress.ios.tsx"],"mappings":";;AAAA,SAAQA,YAAY,QAAO,mBAAmB;AAC9C,SAAQC,iBAAiB,EAAEC,IAAI,QAAO,6BAA6B;AACnE,SAAQC,WAAW,QAAO,mBAAmB;AAC7C,SAAQC,OAAO,QAAO,OAAO;AAE7B,SAAQC,YAAY,QAAO,uBAAoB;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAG/C,OAAO,MAAMC,QAA2B,GAAGA,CAAC;EAACC,QAAQ,GAAG,KAAK;EAAEC;AAAoB,CAAC,KAAK;EACvFL,YAAY,CAAC,UAAU,CAAC;EACxB,MAAMM,KAAK,GAAGR,WAAW,CAAC,CAAC;EAE3B,MAAMS,SAAS,GAAGR,OAAO,CACvB,MAAM,CAACH,iBAAiB,CAACQ,QAAQ,GAAG,UAAU,GAAG,QAAQ,CAAC,EAAEP,IAAI,CAACS,KAAK,CAACE,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC,EACrG,CAACJ,QAAQ,EAAEE,KAAK,CAClB,CAAC;EAED,oBAAOJ,IAAA,CAACP,YAAY;IAACY,SAAS,EAAEA,SAAU;IAACF,KAAK,EAAEA,KAAK,IAAI;EAAK,CAAE,CAAC;AACrE,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["Gauge","ProgressView","gaugeStyle","progressViewStyle","tint","useAppTheme","useMemo","useHostGuard","jsx","_jsx","Progress","circular","value","theme","ring","undefined","modifiers","color"],"sourceRoot":"../../../../src","sources":["atoms/progress/progress.ios.tsx"],"mappings":";;AAAA,SAAQA,KAAK,EAAEC,YAAY,QAAO,mBAAmB;AACrD,SAAQC,UAAU,EAAEC,iBAAiB,EAAEC,IAAI,QAAO,6BAA6B;AAC/E,SAAQC,WAAW,QAAO,mBAAmB;AAC7C,SAAQC,OAAO,QAAO,OAAO;AAE7B,SAAQC,YAAY,QAAO,uBAAoB;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAG/C,OAAO,MAAMC,QAA2B,GAAGA,CAAC;EAACC,QAAQ,GAAG,KAAK;EAAEC;AAAoB,CAAC,KAAK;EACvFL,YAAY,CAAC,UAAU,CAAC;EACxB,MAAMM,KAAK,GAAGR,WAAW,CAAC,CAAC;EAE3B,MAAMS,IAAI,GAAGH,QAAQ,IAAIC,KAAK,KAAKG,SAAS;EAC5C,MAAMC,SAAS,GAAGV,OAAO,CACvB,MAAM,CACJQ,IAAI,GAAGZ,UAAU,CAAC,kBAAkB,CAAC,GAAGC,iBAAiB,CAACQ,QAAQ,GAAG,UAAU,GAAG,QAAQ,CAAC,EAC3FP,IAAI,CAACS,KAAK,CAACI,KAAK,CAAC,qBAAqB,CAAC,CAAC,CACzC,EACD,CAACN,QAAQ,EAAEG,IAAI,EAAED,KAAK,CACxB,CAAC;;EAED;EACA,OAAOC,IAAI,gBACTL,IAAA,CAACT,KAAK;IAACgB,SAAS,EAAEA,SAAU;IAACJ,KAAK,EAAEA;EAAM,CAAE,CAAC,gBAE7CH,IAAA,CAACR,YAAY;IAACe,SAAS,EAAEA,SAAU;IAACJ,KAAK,EAAEA,KAAK,IAAI;EAAK,CAAE,CAC5D;AACH,CAAC","ignoreList":[]}
@@ -11,7 +11,10 @@ export const Surface = ({
11
11
  ...sx
12
12
  }) => {
13
13
  useHostGuard('Surface');
14
+
15
+ // `surface.primary` unless told otherwise, as Material's `Surface` is on Android — without it a plain one drew nothing.
14
16
  const modifiers = useSxModifiers({
17
+ bg: 'surface.primary',
15
18
  borderRadius: 'large',
16
19
  p: 's16',
17
20
  ...sx
@@ -1 +1 @@
1
- {"version":3,"names":["GlassEffectContainer","VStack","useSxModifiers","useHostGuard","jsx","_jsx","Surface","children","glass","testID","sx","modifiers","borderRadius","p","content","alignment"],"sourceRoot":"../../../../src","sources":["atoms/surface/surface.ios.tsx"],"mappings":";;AAAA,SAAQA,oBAAoB,EAAEC,MAAM,QAAO,mBAAmB;AAC9D,SAAQC,cAAc,QAAO,gBAAgB;AAC7C,SAAQC,YAAY,QAAO,uBAAoB;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAG/C,OAAO,MAAMC,OAAyB,GAAGA,CAAC;EAACC,QAAQ;EAAEC,KAAK,GAAG,KAAK;EAAEC,MAAM;EAAE,GAAGC;AAAgB,CAAC,KAAK;EACnGP,YAAY,CAAC,SAAS,CAAC;EAEvB,MAAMQ,SAAS,GAAGT,cAAc,CAAC;IAACU,YAAY,EAAE,OAAO;IAAEC,CAAC,EAAE,KAAK;IAAE,GAAGH;EAAE,CAAC,CAAC;EAC1E,MAAMI,OAAO,gBACXT,IAAA,CAACJ,MAAM;IAACc,SAAS,EAAC,SAAS;IAACJ,SAAS,EAAEA,SAAU;IAACF,MAAM,EAAEA,MAAO;IAAAF,QAAA,EAC9DA;EAAQ,CACH,CACT;EAED,IAAI,CAACC,KAAK,EAAE;IACV,OAAOM,OAAO;EAChB;EAEA,oBAAOT,IAAA,CAACL,oBAAoB;IAAAO,QAAA,EAAEO;EAAO,CAAuB,CAAC;AAC/D,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["GlassEffectContainer","VStack","useSxModifiers","useHostGuard","jsx","_jsx","Surface","children","glass","testID","sx","modifiers","bg","borderRadius","p","content","alignment"],"sourceRoot":"../../../../src","sources":["atoms/surface/surface.ios.tsx"],"mappings":";;AAAA,SAAQA,oBAAoB,EAAEC,MAAM,QAAO,mBAAmB;AAC9D,SAAQC,cAAc,QAAO,gBAAgB;AAC7C,SAAQC,YAAY,QAAO,uBAAoB;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAG/C,OAAO,MAAMC,OAAyB,GAAGA,CAAC;EAACC,QAAQ;EAAEC,KAAK,GAAG,KAAK;EAAEC,MAAM;EAAE,GAAGC;AAAgB,CAAC,KAAK;EACnGP,YAAY,CAAC,SAAS,CAAC;;EAEvB;EACA,MAAMQ,SAAS,GAAGT,cAAc,CAAC;IAACU,EAAE,EAAE,iBAAiB;IAAEC,YAAY,EAAE,OAAO;IAAEC,CAAC,EAAE,KAAK;IAAE,GAAGJ;EAAE,CAAC,CAAC;EACjG,MAAMK,OAAO,gBACXV,IAAA,CAACJ,MAAM;IAACe,SAAS,EAAC,SAAS;IAACL,SAAS,EAAEA,SAAU;IAACF,MAAM,EAAEA,MAAO;IAAAF,QAAA,EAC9DA;EAAQ,CACH,CACT;EAED,IAAI,CAACC,KAAK,EAAE;IACV,OAAOO,OAAO;EAChB;EAEA,oBAAOV,IAAA,CAACL,oBAAoB;IAAAO,QAAA,EAAEQ;EAAO,CAAuB,CAAC;AAC/D,CAAC","ignoreList":[]}
@@ -3,6 +3,7 @@
3
3
  import { Column, Text as ComposeText, OutlinedTextField, useNativeState } from '@expo/ui/jetpack-compose';
4
4
  import { useSxModifiers } from '@hzblj/kara-sx';
5
5
  import { useAppTheme } from '@hzblj/kara-theme';
6
+ import { Glyph } from "../../glyph/index.js";
6
7
  import { useHostGuard } from "../../host-context.js";
7
8
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
9
  export const TextField = ({
@@ -20,17 +21,19 @@ export const TextField = ({
20
21
  const modifiers = useSxModifiers({
21
22
  wide: true
22
23
  });
24
+ const invalid = Boolean(error);
25
+ const message = typeof error === 'string' && error ? error : undefined;
23
26
  return /*#__PURE__*/_jsxs(Column, {
24
27
  verticalArrangement: {
25
28
  spacedBy: 4
26
29
  },
27
30
  children: [label ? /*#__PURE__*/_jsx(ComposeText, {
28
- color: theme.colorString(error ? 'content.destructive' : 'content.secondary'),
31
+ color: theme.colorString(invalid ? 'content.destructive' : 'content.secondary'),
29
32
  style: theme.typography.labelMedium,
30
33
  children: label
31
- }) : null, /*#__PURE__*/_jsx(OutlinedTextField, {
34
+ }) : null, /*#__PURE__*/_jsxs(OutlinedTextField, {
32
35
  enabled: !disabled,
33
- isError: error,
36
+ isError: invalid,
34
37
  modifiers: modifiers,
35
38
  onValueChange: onChangeText,
36
39
  singleLine: !multiline,
@@ -40,7 +43,19 @@ export const TextField = ({
40
43
  fontWeight: theme.typography.body.fontWeight
41
44
  },
42
45
  value: value,
43
- visualTransformation: secure ? 'password' : 'none'
46
+ visualTransformation: secure ? 'password' : 'none',
47
+ children: [invalid ? /*#__PURE__*/_jsx(OutlinedTextField.TrailingIcon, {
48
+ children: /*#__PURE__*/_jsx(Glyph, {
49
+ color: "content.destructive",
50
+ name: "error"
51
+ })
52
+ }) : null, message ? /*#__PURE__*/_jsx(OutlinedTextField.SupportingText, {
53
+ children: /*#__PURE__*/_jsx(ComposeText, {
54
+ color: theme.colorString('content.destructive'),
55
+ style: theme.typography.footnote,
56
+ children: message
57
+ })
58
+ }) : null]
44
59
  })]
45
60
  });
46
61
  };
@@ -1 +1 @@
1
- {"version":3,"names":["Column","Text","ComposeText","OutlinedTextField","useNativeState","useSxModifiers","useAppTheme","useHostGuard","jsx","_jsx","jsxs","_jsxs","TextField","defaultValue","disabled","error","label","multiline","onChangeText","secure","theme","value","modifiers","wide","verticalArrangement","spacedBy","children","color","colorString","style","typography","labelMedium","enabled","isError","onValueChange","singleLine","textStyle","fontFamily","body","fontWeight","visualTransformation"],"sourceRoot":"../../../../src","sources":["atoms/text-field/text-field.android.tsx"],"mappings":";;AAAA,SAAQA,MAAM,EAAEC,IAAI,IAAIC,WAAW,EAAEC,iBAAiB,EAAEC,cAAc,QAAO,0BAA0B;AACvG,SAAQC,cAAc,QAAO,gBAAgB;AAC7C,SAAQC,WAAW,QAAO,mBAAmB;AAC7C,SAAQC,YAAY,QAAO,uBAAoB;AAAA,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAG/C,OAAO,MAAMC,SAA6B,GAAGA,CAAC;EAC5CC,YAAY,GAAG,EAAE;EACjBC,QAAQ,GAAG,KAAK;EAChBC,KAAK,GAAG,KAAK;EACbC,KAAK;EACLC,SAAS,GAAG,KAAK;EACjBC,YAAY;EACZC,MAAM,GAAG;AACK,CAAC,KAAK;EACpBZ,YAAY,CAAC,WAAW,CAAC;EACzB,MAAMa,KAAK,GAAGd,WAAW,CAAC,CAAC;EAC3B,MAAMe,KAAK,GAAGjB,cAAc,CAACS,YAAY,CAAC;EAC1C,MAAMS,SAAS,GAAGjB,cAAc,CAAC;IAACkB,IAAI,EAAE;EAAI,CAAC,CAAC;EAE9C,oBACEZ,KAAA,CAACX,MAAM;IAACwB,mBAAmB,EAAE;MAACC,QAAQ,EAAE;IAAC,CAAE;IAAAC,QAAA,GACxCV,KAAK,gBACJP,IAAA,CAACP,WAAW;MACVyB,KAAK,EAAEP,KAAK,CAACQ,WAAW,CAACb,KAAK,GAAG,qBAAqB,GAAG,mBAAmB,CAAE;MAC9Ec,KAAK,EAAET,KAAK,CAACU,UAAU,CAACC,WAAY;MAAAL,QAAA,EAEnCV;IAAK,CACK,CAAC,GACZ,IAAI,eACRP,IAAA,CAACN,iBAAiB;MAChB6B,OAAO,EAAE,CAAClB,QAAS;MACnBmB,OAAO,EAAElB,KAAM;MACfO,SAAS,EAAEA,SAAU;MACrBY,aAAa,EAAEhB,YAAa;MAC5BiB,UAAU,EAAE,CAAClB,SAAU;MACvBmB,SAAS,EAAE;QACTT,KAAK,EAAEP,KAAK,CAACQ,WAAW,CAAC,iBAAiB,CAAC;QAC3CS,UAAU,EAAEjB,KAAK,CAACU,UAAU,CAACQ,IAAI,CAACD,UAAU;QAC5CE,UAAU,EAAEnB,KAAK,CAACU,UAAU,CAACQ,IAAI,CAACC;MACpC,CAAE;MACFlB,KAAK,EAAEA,KAAM;MACbmB,oBAAoB,EAAErB,MAAM,GAAG,UAAU,GAAG;IAAO,CACpD,CAAC;EAAA,CACI,CAAC;AAEb,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["Column","Text","ComposeText","OutlinedTextField","useNativeState","useSxModifiers","useAppTheme","Glyph","useHostGuard","jsx","_jsx","jsxs","_jsxs","TextField","defaultValue","disabled","error","label","multiline","onChangeText","secure","theme","value","modifiers","wide","invalid","Boolean","message","undefined","verticalArrangement","spacedBy","children","color","colorString","style","typography","labelMedium","enabled","isError","onValueChange","singleLine","textStyle","fontFamily","body","fontWeight","visualTransformation","TrailingIcon","name","SupportingText","footnote"],"sourceRoot":"../../../../src","sources":["atoms/text-field/text-field.android.tsx"],"mappings":";;AAAA,SAAQA,MAAM,EAAEC,IAAI,IAAIC,WAAW,EAAEC,iBAAiB,EAAEC,cAAc,QAAO,0BAA0B;AACvG,SAAQC,cAAc,QAAO,gBAAgB;AAC7C,SAAQC,WAAW,QAAO,mBAAmB;AAC7C,SAAQC,KAAK,QAAO,sBAAa;AACjC,SAAQC,YAAY,QAAO,uBAAoB;AAAA,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAG/C,OAAO,MAAMC,SAA6B,GAAGA,CAAC;EAC5CC,YAAY,GAAG,EAAE;EACjBC,QAAQ,GAAG,KAAK;EAChBC,KAAK,GAAG,KAAK;EACbC,KAAK;EACLC,SAAS,GAAG,KAAK;EACjBC,YAAY;EACZC,MAAM,GAAG;AACK,CAAC,KAAK;EACpBZ,YAAY,CAAC,WAAW,CAAC;EACzB,MAAMa,KAAK,GAAGf,WAAW,CAAC,CAAC;EAC3B,MAAMgB,KAAK,GAAGlB,cAAc,CAACU,YAAY,CAAC;EAC1C,MAAMS,SAAS,GAAGlB,cAAc,CAAC;IAACmB,IAAI,EAAE;EAAI,CAAC,CAAC;EAC9C,MAAMC,OAAO,GAAGC,OAAO,CAACV,KAAK,CAAC;EAC9B,MAAMW,OAAO,GAAG,OAAOX,KAAK,KAAK,QAAQ,IAAIA,KAAK,GAAGA,KAAK,GAAGY,SAAS;EAEtE,oBACEhB,KAAA,CAACZ,MAAM;IAAC6B,mBAAmB,EAAE;MAACC,QAAQ,EAAE;IAAC,CAAE;IAAAC,QAAA,GACxCd,KAAK,gBACJP,IAAA,CAACR,WAAW;MACV8B,KAAK,EAAEX,KAAK,CAACY,WAAW,CAACR,OAAO,GAAG,qBAAqB,GAAG,mBAAmB,CAAE;MAChFS,KAAK,EAAEb,KAAK,CAACc,UAAU,CAACC,WAAY;MAAAL,QAAA,EAEnCd;IAAK,CACK,CAAC,GACZ,IAAI,eACRL,KAAA,CAACT,iBAAiB;MAChBkC,OAAO,EAAE,CAACtB,QAAS;MACnBuB,OAAO,EAAEb,OAAQ;MACjBF,SAAS,EAAEA,SAAU;MACrBgB,aAAa,EAAEpB,YAAa;MAC5BqB,UAAU,EAAE,CAACtB,SAAU;MACvBuB,SAAS,EAAE;QACTT,KAAK,EAAEX,KAAK,CAACY,WAAW,CAAC,iBAAiB,CAAC;QAC3CS,UAAU,EAAErB,KAAK,CAACc,UAAU,CAACQ,IAAI,CAACD,UAAU;QAC5CE,UAAU,EAAEvB,KAAK,CAACc,UAAU,CAACQ,IAAI,CAACC;MACpC,CAAE;MACFtB,KAAK,EAAEA,KAAM;MACbuB,oBAAoB,EAAEzB,MAAM,GAAG,UAAU,GAAG,MAAO;MAAAW,QAAA,GAElDN,OAAO,gBACNf,IAAA,CAACP,iBAAiB,CAAC2C,YAAY;QAAAf,QAAA,eAC7BrB,IAAA,CAACH,KAAK;UAACyB,KAAK,EAAC,qBAAqB;UAACe,IAAI,EAAC;QAAO,CAAE;MAAC,CACpB,CAAC,GAC/B,IAAI,EACPpB,OAAO,gBACNjB,IAAA,CAACP,iBAAiB,CAAC6C,cAAc;QAAAjB,QAAA,eAC/BrB,IAAA,CAACR,WAAW;UAAC8B,KAAK,EAAEX,KAAK,CAACY,WAAW,CAAC,qBAAqB,CAAE;UAACC,KAAK,EAAEb,KAAK,CAACc,UAAU,CAACc,QAAS;UAAAlB,QAAA,EAC5FJ;QAAO,CACG;MAAC,CACkB,CAAC,GACjC,IAAI;IAAA,CACS,CAAC;EAAA,CACd,CAAC;AAEb,CAAC","ignoreList":[]}
@@ -48,7 +48,8 @@ export const TextField = ({
48
48
  }) => {
49
49
  useHostGuard('TextField');
50
50
  const text = useNativeState(defaultValue);
51
- const tone = TONE[toneOf(disabled, error)];
51
+ const tone = TONE[toneOf(disabled, Boolean(error))];
52
+ const message = tone === TONE.error && typeof error === 'string' && error ? error : undefined;
52
53
  const sxModifiers = useSxModifiers({
53
54
  bg: tone.bg,
54
55
  borderColor: tone.border,
@@ -83,7 +84,11 @@ export const TextField = ({
83
84
  onTextChange: onChangeText,
84
85
  testID: testID,
85
86
  text: text
86
- })]
87
+ }), message ? /*#__PURE__*/_jsx(Text, {
88
+ color: "content.destructive",
89
+ variant: "footnote",
90
+ children: message
91
+ }) : null]
87
92
  });
88
93
  };
89
94
  //# sourceMappingURL=text-field.ios.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["SecureField","TextField","SwiftUITextField","useNativeState","VStack","disabled","disabledModifier","textFieldStyle","useSxModifiers","spacing","useMemo","useHostGuard","Text","jsx","_jsx","jsxs","_jsxs","TONE","default","bg","border","label","error","toneOf","defaultValue","multiline","onChangeText","secure","testID","text","tone","sxModifiers","borderColor","borderRadius","borderWidth","px","py","wide","modifiers","list","push","alignment","s4","children","color","variant","onTextChange","axis"],"sourceRoot":"../../../../src","sources":["atoms/text-field/text-field.ios.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["SecureField","TextField","SwiftUITextField","useNativeState","VStack","disabled","disabledModifier","textFieldStyle","useSxModifiers","spacing","useMemo","useHostGuard","Text","jsx","_jsx","jsxs","_jsxs","TONE","default","bg","border","label","error","toneOf","defaultValue","multiline","onChangeText","secure","testID","text","tone","Boolean","message","undefined","sxModifiers","borderColor","borderRadius","borderWidth","px","py","wide","modifiers","list","push","alignment","s4","children","color","variant","onTextChange","axis"],"sourceRoot":"../../../../src","sources":["atoms/text-field/text-field.ios.tsx"],"mappings":"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","ignoreList":[]}
@@ -1,7 +1,7 @@
1
1
  import type { ReactNode } from 'react';
2
2
  /**
3
- * A progress bar or ring, tinted `fill.accent.primary` — SwiftUI `ProgressView` / Compose's
4
- * `LinearProgressIndicator` and `CircularProgressIndicator`.
3
+ * A progress bar or ring, tinted `fill.accent.primary` — SwiftUI `ProgressView` (a capacity `Gauge` for a ring with a
4
+ * value, which `ProgressView` cannot draw on iOS) / Compose's `LinearProgressIndicator` and `CircularProgressIndicator`.
5
5
  */
6
6
  export type ProgressProps = {
7
7
  /** A circular indicator instead of a bar. Off by default. */
@@ -1,8 +1,8 @@
1
1
  import type { ResponsiveSx } from '@hzblj/kara-sx';
2
2
  import type { ReactNode } from 'react';
3
3
  /**
4
- * A container padded `s16` and rounded `large` unless told otherwise — a SwiftUI `VStack` on iOS, Material's
5
- * `Surface` around a `Column` on Android.
4
+ * A container on `surface.primary`, padded `s16` and rounded `large` unless told otherwise — a SwiftUI `VStack` on
5
+ * iOS, Material's `Surface` around a `Column` on Android.
6
6
  */
7
7
  export type SurfaceProps = ResponsiveSx & {
8
8
  /** Stacked vertically, from the leading edge. */
@@ -8,8 +8,12 @@ export type TextFieldProps = {
8
8
  defaultValue?: string;
9
9
  /** Stops editing and dims the field. On iOS it outranks `error`. */
10
10
  disabled?: boolean;
11
- /** Marks the field invalid: a destructive outline and label. */
12
- error?: boolean;
11
+ /**
12
+ * Marks the field invalid: a destructive outline and label. A message is shown under the field as well — on Android
13
+ * as Material's supporting text, beside its error icon — so the error never rests on colour alone; Material's error
14
+ * colour is a pale red in dark mode. `true` marks it without a message.
15
+ */
16
+ error?: boolean | string;
13
17
  /** Shown above the field, in `labelMedium`. */
14
18
  label?: string;
15
19
  /** Wraps the text and grows the field to fit it. iOS ignores it when `secure`. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hzblj/kara-components",
3
- "version": "0.8.0",
3
+ "version": "0.9.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",
@@ -59,9 +59,9 @@
59
59
  ]
60
60
  },
61
61
  "dependencies": {
62
- "@hzblj/kara-native": "^0.8.0",
63
- "@hzblj/kara-sx": "^0.8.0",
64
- "@hzblj/kara-theme": "^0.8.0",
62
+ "@hzblj/kara-native": "^0.9.0",
63
+ "@hzblj/kara-sx": "^0.9.0",
64
+ "@hzblj/kara-theme": "^0.9.0",
65
65
  "sf-symbols-typescript": "^2.2.0"
66
66
  },
67
67
  "peerDependencies": {
@@ -1,5 +1,5 @@
1
- import {ProgressView} from '@expo/ui/swift-ui'
2
- import {progressViewStyle, tint} from '@expo/ui/swift-ui/modifiers'
1
+ import {Gauge, ProgressView} from '@expo/ui/swift-ui'
2
+ import {gaugeStyle, progressViewStyle, tint} from '@expo/ui/swift-ui/modifiers'
3
3
  import {useAppTheme} from '@hzblj/kara-theme'
4
4
  import {useMemo} from 'react'
5
5
 
@@ -10,10 +10,19 @@ export const Progress: ProgressComponent = ({circular = false, value}: ProgressP
10
10
  useHostGuard('Progress')
11
11
  const theme = useAppTheme()
12
12
 
13
+ const ring = circular && value !== undefined
13
14
  const modifiers = useMemo(
14
- () => [progressViewStyle(circular ? 'circular' : 'linear'), tint(theme.color('fill.accent.primary'))],
15
- [circular, theme]
15
+ () => [
16
+ ring ? gaugeStyle('circularCapacity') : progressViewStyle(circular ? 'circular' : 'linear'),
17
+ tint(theme.color('fill.accent.primary')),
18
+ ],
19
+ [circular, ring, theme]
16
20
  )
17
21
 
18
- return <ProgressView modifiers={modifiers} value={value ?? null} />
22
+ // SwiftUI's circular `ProgressView` ignores its value on iOS and spins; a ring that fills is a capacity `Gauge`.
23
+ return ring ? (
24
+ <Gauge modifiers={modifiers} value={value} />
25
+ ) : (
26
+ <ProgressView modifiers={modifiers} value={value ?? null} />
27
+ )
19
28
  }
@@ -1,8 +1,8 @@
1
1
  import type {ReactNode} from 'react'
2
2
 
3
3
  /**
4
- * A progress bar or ring, tinted `fill.accent.primary` — SwiftUI `ProgressView` / Compose's
5
- * `LinearProgressIndicator` and `CircularProgressIndicator`.
4
+ * A progress bar or ring, tinted `fill.accent.primary` — SwiftUI `ProgressView` (a capacity `Gauge` for a ring with a
5
+ * value, which `ProgressView` cannot draw on iOS) / Compose's `LinearProgressIndicator` and `CircularProgressIndicator`.
6
6
  */
7
7
  export type ProgressProps = {
8
8
  /** A circular indicator instead of a bar. Off by default. */
@@ -6,7 +6,8 @@ import type {SurfaceComponent, SurfaceProps} from './surface.types'
6
6
  export const Surface: SurfaceComponent = ({children, glass = false, testID, ...sx}: SurfaceProps) => {
7
7
  useHostGuard('Surface')
8
8
 
9
- const modifiers = useSxModifiers({borderRadius: 'large', p: 's16', ...sx})
9
+ // `surface.primary` unless told otherwise, as Material's `Surface` is on Android — without it a plain one drew nothing.
10
+ const modifiers = useSxModifiers({bg: 'surface.primary', borderRadius: 'large', p: 's16', ...sx})
10
11
  const content = (
11
12
  <VStack alignment="leading" modifiers={modifiers} testID={testID}>
12
13
  {children}
@@ -2,8 +2,8 @@ import type {ResponsiveSx} from '@hzblj/kara-sx'
2
2
  import type {ReactNode} from 'react'
3
3
 
4
4
  /**
5
- * A container padded `s16` and rounded `large` unless told otherwise — a SwiftUI `VStack` on iOS, Material's
6
- * `Surface` around a `Column` on Android.
5
+ * A container on `surface.primary`, padded `s16` and rounded `large` unless told otherwise — a SwiftUI `VStack` on
6
+ * iOS, Material's `Surface` around a `Column` on Android.
7
7
  */
8
8
  export type SurfaceProps = ResponsiveSx & {
9
9
  /** Stacked vertically, from the leading edge. */
@@ -1,6 +1,7 @@
1
1
  import {Column, Text as ComposeText, OutlinedTextField, useNativeState} from '@expo/ui/jetpack-compose'
2
2
  import {useSxModifiers} from '@hzblj/kara-sx'
3
3
  import {useAppTheme} from '@hzblj/kara-theme'
4
+ import {Glyph} from '../../glyph'
4
5
  import {useHostGuard} from '../../host-context'
5
6
  import type {TextFieldComponent, TextFieldProps} from './text-field.types'
6
7
 
@@ -17,12 +18,14 @@ export const TextField: TextFieldComponent = ({
17
18
  const theme = useAppTheme()
18
19
  const value = useNativeState(defaultValue)
19
20
  const modifiers = useSxModifiers({wide: true})
21
+ const invalid = Boolean(error)
22
+ const message = typeof error === 'string' && error ? error : undefined
20
23
 
21
24
  return (
22
25
  <Column verticalArrangement={{spacedBy: 4}}>
23
26
  {label ? (
24
27
  <ComposeText
25
- color={theme.colorString(error ? 'content.destructive' : 'content.secondary')}
28
+ color={theme.colorString(invalid ? 'content.destructive' : 'content.secondary')}
26
29
  style={theme.typography.labelMedium}
27
30
  >
28
31
  {label}
@@ -30,7 +33,7 @@ export const TextField: TextFieldComponent = ({
30
33
  ) : null}
31
34
  <OutlinedTextField
32
35
  enabled={!disabled}
33
- isError={error}
36
+ isError={invalid}
34
37
  modifiers={modifiers}
35
38
  onValueChange={onChangeText}
36
39
  singleLine={!multiline}
@@ -41,7 +44,20 @@ export const TextField: TextFieldComponent = ({
41
44
  }}
42
45
  value={value}
43
46
  visualTransformation={secure ? 'password' : 'none'}
44
- />
47
+ >
48
+ {invalid ? (
49
+ <OutlinedTextField.TrailingIcon>
50
+ <Glyph color="content.destructive" name="error" />
51
+ </OutlinedTextField.TrailingIcon>
52
+ ) : null}
53
+ {message ? (
54
+ <OutlinedTextField.SupportingText>
55
+ <ComposeText color={theme.colorString('content.destructive')} style={theme.typography.footnote}>
56
+ {message}
57
+ </ComposeText>
58
+ </OutlinedTextField.SupportingText>
59
+ ) : null}
60
+ </OutlinedTextField>
45
61
  </Column>
46
62
  )
47
63
  }
@@ -45,7 +45,8 @@ export const TextField: TextFieldComponent = ({
45
45
  }: TextFieldProps) => {
46
46
  useHostGuard('TextField')
47
47
  const text = useNativeState(defaultValue)
48
- const tone = TONE[toneOf(disabled, error)]
48
+ const tone = TONE[toneOf(disabled, Boolean(error))]
49
+ const message = tone === TONE.error && typeof error === 'string' && error ? error : undefined
49
50
 
50
51
  const sxModifiers = useSxModifiers({
51
52
  bg: tone.bg,
@@ -85,6 +86,11 @@ export const TextField: TextFieldComponent = ({
85
86
  text={text}
86
87
  />
87
88
  )}
89
+ {message ? (
90
+ <Text color="content.destructive" variant="footnote">
91
+ {message}
92
+ </Text>
93
+ ) : null}
88
94
  </VStack>
89
95
  )
90
96
  }
@@ -9,8 +9,12 @@ export type TextFieldProps = {
9
9
  defaultValue?: string
10
10
  /** Stops editing and dims the field. On iOS it outranks `error`. */
11
11
  disabled?: boolean
12
- /** Marks the field invalid: a destructive outline and label. */
13
- error?: boolean
12
+ /**
13
+ * Marks the field invalid: a destructive outline and label. A message is shown under the field as well — on Android
14
+ * as Material's supporting text, beside its error icon — so the error never rests on colour alone; Material's error
15
+ * colour is a pale red in dark mode. `true` marks it without a message.
16
+ */
17
+ error?: boolean | string
14
18
  /** Shown above the field, in `labelMedium`. */
15
19
  label?: string
16
20
  /** Wraps the text and grows the field to fit it. iOS ignores it when `secure`. */