@hzblj/kara-sx 0.0.0-stage → 0.2.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 (79) hide show
  1. package/README.md +7 -2
  2. package/lib/module/flatten-sx.js +59 -0
  3. package/lib/module/flatten-sx.js.map +1 -0
  4. package/lib/module/index.js +19 -0
  5. package/lib/module/index.js.map +1 -0
  6. package/lib/module/package.json +1 -0
  7. package/lib/module/resolve-cache.js +79 -0
  8. package/lib/module/resolve-cache.js.map +1 -0
  9. package/lib/module/responsive-sx.js +66 -0
  10. package/lib/module/responsive-sx.js.map +1 -0
  11. package/lib/module/responsive.types.js +4 -0
  12. package/lib/module/responsive.types.js.map +1 -0
  13. package/lib/module/sx-key.js +25 -0
  14. package/lib/module/sx-key.js.map +1 -0
  15. package/lib/module/sx-keys.js +46 -0
  16. package/lib/module/sx-keys.js.map +1 -0
  17. package/lib/module/sx-padding.js +26 -0
  18. package/lib/module/sx-padding.js.map +1 -0
  19. package/lib/module/sx-to-modifiers.android.js +168 -0
  20. package/lib/module/sx-to-modifiers.android.js.map +1 -0
  21. package/lib/module/sx-to-modifiers.ios.js +266 -0
  22. package/lib/module/sx-to-modifiers.ios.js.map +1 -0
  23. package/lib/module/sx-to-style.js +137 -0
  24. package/lib/module/sx-to-style.js.map +1 -0
  25. package/lib/module/sx.types.js +4 -0
  26. package/lib/module/sx.types.js.map +1 -0
  27. package/lib/module/use-sx-modifiers.android.js +30 -0
  28. package/lib/module/use-sx-modifiers.android.js.map +1 -0
  29. package/lib/module/use-sx-modifiers.ios.js +30 -0
  30. package/lib/module/use-sx-modifiers.ios.js.map +1 -0
  31. package/lib/module/use-sx.js +30 -0
  32. package/lib/module/use-sx.js.map +1 -0
  33. package/lib/module/value-key.js +16 -0
  34. package/lib/module/value-key.js.map +1 -0
  35. package/lib/module/view-sx-to-style.js +159 -0
  36. package/lib/module/view-sx-to-style.js.map +1 -0
  37. package/lib/module/view-sx.types.js +4 -0
  38. package/lib/module/view-sx.types.js.map +1 -0
  39. package/lib/module/with-sx.js +50 -0
  40. package/lib/module/with-sx.js.map +1 -0
  41. package/lib/typescript/flatten-sx.d.ts +15 -0
  42. package/lib/typescript/index.d.ts +16 -0
  43. package/lib/typescript/resolve-cache.d.ts +14 -0
  44. package/lib/typescript/responsive-sx.d.ts +80 -0
  45. package/lib/typescript/responsive.types.d.ts +23 -0
  46. package/lib/typescript/sx-key.d.ts +7 -0
  47. package/lib/typescript/sx-keys.d.ts +6 -0
  48. package/lib/typescript/sx-padding.d.ts +5 -0
  49. package/lib/typescript/sx-to-modifiers.d.ts +1 -0
  50. package/lib/typescript/sx-to-modifiers.ios.d.ts +4 -0
  51. package/lib/typescript/sx-to-style.d.ts +4 -0
  52. package/lib/typescript/sx.types.d.ts +182 -0
  53. package/lib/typescript/use-sx-modifiers.d.ts +1 -0
  54. package/lib/typescript/use-sx-modifiers.ios.d.ts +14 -0
  55. package/lib/typescript/use-sx.d.ts +15 -0
  56. package/lib/typescript/value-key.d.ts +7 -0
  57. package/lib/typescript/view-sx-to-style.d.ts +17 -0
  58. package/lib/typescript/view-sx.types.d.ts +80 -0
  59. package/lib/typescript/with-sx.d.ts +28 -0
  60. package/package.json +78 -4
  61. package/src/flatten-sx.ts +70 -0
  62. package/src/index.ts +16 -0
  63. package/src/resolve-cache.ts +105 -0
  64. package/src/responsive-sx.ts +75 -0
  65. package/src/responsive.types.ts +23 -0
  66. package/src/sx-key.ts +32 -0
  67. package/src/sx-keys.ts +47 -0
  68. package/src/sx-padding.ts +27 -0
  69. package/src/sx-to-modifiers.android.ts +224 -0
  70. package/src/sx-to-modifiers.ios.ts +322 -0
  71. package/src/sx-to-style.ts +142 -0
  72. package/src/sx.types.ts +215 -0
  73. package/src/use-sx-modifiers.android.ts +29 -0
  74. package/src/use-sx-modifiers.ios.ts +29 -0
  75. package/src/use-sx.ts +34 -0
  76. package/src/value-key.ts +18 -0
  77. package/src/view-sx-to-style.ts +180 -0
  78. package/src/view-sx.types.ts +87 -0
  79. package/src/with-sx.tsx +51 -0
@@ -0,0 +1,159 @@
1
+ "use strict";
2
+
3
+ import { radii, spacing } from '@hzblj/kara-theme';
4
+ import { createSxCache } from "./resolve-cache.js";
5
+ import { SX_CORE_KEYS } from "./sx-keys.js";
6
+ import { sxToStyle } from "./sx-to-style.js";
7
+ /**
8
+ * `Record`s rather than bare arrays, for the same reason as `SX_CORE_KEY_RECORD`: `satisfies` on an
9
+ * array only checks membership, while these refuse to compile when a key is added to `ViewSx` but
10
+ * missing here — which `split` would then leak into the wrapped component's own props.
11
+ */
12
+ const CORNER_KEY_RECORD = {
13
+ borderBottomLeftRadius: true,
14
+ borderBottomRadius: true,
15
+ borderBottomRightRadius: true,
16
+ borderLeftRadius: true,
17
+ borderRightRadius: true,
18
+ borderTopLeftRadius: true,
19
+ borderTopRadius: true,
20
+ borderTopRightRadius: true
21
+ };
22
+ const CORNER_KEYS = Object.keys(CORNER_KEY_RECORD);
23
+ const VIEW_ONLY_KEY_RECORD = {
24
+ ...CORNER_KEY_RECORD,
25
+ align: true,
26
+ alignContent: true,
27
+ alignSelf: true,
28
+ aspectRatio: true,
29
+ basis: true,
30
+ borderBottomWidth: true,
31
+ borderLeftWidth: true,
32
+ borderRightWidth: true,
33
+ borderStyle: true,
34
+ borderTopWidth: true,
35
+ bottom: true,
36
+ columnGap: true,
37
+ display: true,
38
+ flex: true,
39
+ flexDirection: true,
40
+ gap: true,
41
+ grow: true,
42
+ justify: true,
43
+ left: true,
44
+ m: true,
45
+ maxH: true,
46
+ maxW: true,
47
+ mb: true,
48
+ ml: true,
49
+ mr: true,
50
+ mt: true,
51
+ mx: true,
52
+ my: true,
53
+ overflow: true,
54
+ position: true,
55
+ right: true,
56
+ rowGap: true,
57
+ shrink: true,
58
+ top: true,
59
+ wrap: true
60
+ };
61
+ const VIEW_ONLY_KEYS = Object.keys(VIEW_ONLY_KEY_RECORD);
62
+
63
+ /**
64
+ * Every key the RN style engine owns — what `sx()` and `useSx` split off a component's props. Built
65
+ * from `SX_CORE_KEYS` rather than `SX_KEYS` on purpose: including the `ios`/`android` buckets would
66
+ * have `Box` strip them off its props and drop them, since a React Native style has nothing to
67
+ * resolve them into.
68
+ */
69
+ export const VIEW_SX_KEYS = [...SX_CORE_KEYS, ...VIEW_ONLY_KEYS];
70
+ const space = token => token === undefined ? undefined : spacing[token];
71
+ const radius = token => token === undefined ? undefined : radii[token];
72
+
73
+ /**
74
+ * Left to `sxToStyle`'s single `borderRadius` unless a corner or edge prop is present —
75
+ * emitting per-corner keys unconditionally would shadow it with `undefined`.
76
+ */
77
+ const cornerRadiiStyle = sx => {
78
+ if (!CORNER_KEYS.some(key => sx[key] !== undefined)) {
79
+ return {};
80
+ }
81
+ const all = radius(sx.borderRadius);
82
+ const bottom = radius(sx.borderBottomRadius);
83
+ const left = radius(sx.borderLeftRadius);
84
+ const right = radius(sx.borderRightRadius);
85
+ const top = radius(sx.borderTopRadius);
86
+ return {
87
+ borderBottomLeftRadius: radius(sx.borderBottomLeftRadius) ?? bottom ?? left ?? all,
88
+ borderBottomRightRadius: radius(sx.borderBottomRightRadius) ?? bottom ?? right ?? all,
89
+ borderTopLeftRadius: radius(sx.borderTopLeftRadius) ?? top ?? left ?? all,
90
+ borderTopRightRadius: radius(sx.borderTopRightRadius) ?? top ?? right ?? all
91
+ };
92
+ };
93
+ const marginStyle = sx => {
94
+ const all = space(sx.m);
95
+ const x = space(sx.mx);
96
+ const y = space(sx.my);
97
+ return {
98
+ marginBottom: space(sx.mb) ?? y ?? all,
99
+ marginLeft: space(sx.ml) ?? x ?? all,
100
+ marginRight: space(sx.mr) ?? x ?? all,
101
+ marginTop: space(sx.mt) ?? y ?? all
102
+ };
103
+ };
104
+ const borderStyle = sx => ({
105
+ borderBottomWidth: sx.borderBottomWidth,
106
+ borderLeftWidth: sx.borderLeftWidth,
107
+ borderRightWidth: sx.borderRightWidth,
108
+ borderStyle: sx.borderStyle,
109
+ borderTopWidth: sx.borderTopWidth
110
+ });
111
+
112
+ /** `minH`/`minW` are `sxToStyle`'s, and naming them here would shadow it with `undefined`. */
113
+ const sizingStyle = sx => ({
114
+ aspectRatio: sx.aspectRatio,
115
+ maxHeight: sx.maxH,
116
+ maxWidth: sx.maxW
117
+ });
118
+ const flexStyle = sx => ({
119
+ alignContent: sx.alignContent,
120
+ alignItems: sx.align,
121
+ alignSelf: sx.alignSelf,
122
+ columnGap: space(sx.columnGap),
123
+ flex: sx.flex,
124
+ flexBasis: sx.basis,
125
+ flexDirection: sx.flexDirection,
126
+ flexGrow: sx.grow,
127
+ flexShrink: sx.shrink,
128
+ flexWrap: sx.wrap,
129
+ gap: space(sx.gap),
130
+ justifyContent: sx.justify,
131
+ rowGap: space(sx.rowGap)
132
+ });
133
+
134
+ /** `zIndex` is `sxToStyle`'s too, for the same reason as `minH`/`minW` above. */
135
+ const layoutStyle = sx => ({
136
+ bottom: sx.bottom,
137
+ display: sx.display,
138
+ left: sx.left,
139
+ overflow: sx.overflow,
140
+ position: sx.position,
141
+ right: sx.right,
142
+ top: sx.top
143
+ });
144
+ export const viewSxToStyle = (sx, theme) => ({
145
+ ...sxToStyle(sx, theme),
146
+ ...cornerRadiiStyle(sx),
147
+ ...marginStyle(sx),
148
+ ...borderStyle(sx),
149
+ ...sizingStyle(sx),
150
+ ...flexStyle(sx),
151
+ ...layoutStyle(sx)
152
+ });
153
+
154
+ /**
155
+ * `split` hands back a `ResponsiveViewSx`, because that is what a component's props hold — `resolve`
156
+ * only accepts the flat `ViewSx` that `flattenSx` turns those into, so the two cannot be crossed.
157
+ */
158
+ export const viewSxCache = createSxCache(VIEW_SX_KEYS, viewSxToStyle);
159
+ //# sourceMappingURL=view-sx-to-style.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["radii","spacing","createSxCache","SX_CORE_KEYS","sxToStyle","CORNER_KEY_RECORD","borderBottomLeftRadius","borderBottomRadius","borderBottomRightRadius","borderLeftRadius","borderRightRadius","borderTopLeftRadius","borderTopRadius","borderTopRightRadius","CORNER_KEYS","Object","keys","VIEW_ONLY_KEY_RECORD","align","alignContent","alignSelf","aspectRatio","basis","borderBottomWidth","borderLeftWidth","borderRightWidth","borderStyle","borderTopWidth","bottom","columnGap","display","flex","flexDirection","gap","grow","justify","left","m","maxH","maxW","mb","ml","mr","mt","mx","my","overflow","position","right","rowGap","shrink","top","wrap","VIEW_ONLY_KEYS","VIEW_SX_KEYS","space","token","undefined","radius","cornerRadiiStyle","sx","some","key","all","borderRadius","marginStyle","x","y","marginBottom","marginLeft","marginRight","marginTop","sizingStyle","maxHeight","maxWidth","flexStyle","alignItems","flexBasis","flexGrow","flexShrink","flexWrap","justifyContent","layoutStyle","viewSxToStyle","theme","viewSxCache"],"sourceRoot":"../../src","sources":["view-sx-to-style.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export {};
4
+ //# sourceMappingURL=view-sx.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../src","sources":["view-sx.types.ts"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+
3
+ import { memo } from 'react';
4
+ import { useSplitSx } from "./use-sx.js";
5
+
6
+ /**
7
+ * `sx()` resolves a view style; React Native's text and image styles accept those keys too, so this
8
+ * covers every flavour of `style` a wrapped component might declare.
9
+ */
10
+
11
+ /** The wrapped component's own props — ref included — with the whole `sx` surface added. */
12
+ import { jsx as _jsx } from "react/jsx-runtime";
13
+ const nameOf = Component => {
14
+ if (typeof Component === 'string') {
15
+ return Component;
16
+ }
17
+ const {
18
+ displayName,
19
+ name
20
+ } = Component;
21
+ return displayName || name || 'Component';
22
+ };
23
+
24
+ /**
25
+ * Turns any style-taking component into an `sx` one: the `sx` props are split off, resolved against
26
+ * the theme and handed over as `style`. An explicit `style` still wins — it is merged on top.
27
+ *
28
+ * Props come from `ComponentPropsWithRef`, so a `ref` survives the wrapping. The component has to
29
+ * accept a `style`; that cannot be a constraint here, because narrowing `TComponent` past
30
+ * `ElementType` is what breaks the ref inference.
31
+ *
32
+ * Memoised because the point of the cache is a stable style object — without `memo` a parent
33
+ * re-render would walk the child anyway and throw that stability away.
34
+ */
35
+ export const sx = Component => {
36
+ const Sxed = ({
37
+ style,
38
+ ...props
39
+ }) => {
40
+ const [resolved, rest] = useSplitSx(props);
41
+ const Styled = Component;
42
+ return /*#__PURE__*/_jsx(Styled, {
43
+ ...rest,
44
+ style: style ? [resolved, style] : resolved
45
+ });
46
+ };
47
+ Sxed.displayName = `sx(${nameOf(Component)})`;
48
+ return /*#__PURE__*/memo(Sxed);
49
+ };
50
+ //# sourceMappingURL=with-sx.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["memo","useSplitSx","jsx","_jsx","nameOf","Component","displayName","name","sx","Sxed","style","props","resolved","rest","Styled"],"sourceRoot":"../../src","sources":["with-sx.tsx"],"mappings":";;AAAA,SAA0EA,IAAI,QAAO,OAAO;AAI5F,SAAQC,UAAU,QAAO,aAAU;;AAEnC;AACA;AACA;AACA;;AAGA;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAMA,MAAMC,MAAM,GAAIC,SAAsB,IAAa;EACjD,IAAI,OAAOA,SAAS,KAAK,QAAQ,EAAE;IACjC,OAAOA,SAAS;EAClB;EAEA,MAAM;IAACC,WAAW;IAAEC;EAAI,CAAC,GAAGF,SAAiC;EAE7D,OAAOC,WAAW,IAAIC,IAAI,IAAI,WAAW;AAC3C,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,EAAE,GAAoCH,SAAqB,IAAK;EAC3E,MAAMI,IAAI,GAAGA,CAAC;IAACC,KAAK;IAAE,GAAGC;EAAiD,CAAC,KAAK;IAC9E,MAAM,CAACC,QAAQ,EAAEC,IAAI,CAAC,GAAGZ,UAAU,CAACU,KAAgC,CAAC;IACrE,MAAMG,MAAM,GAAGT,SAAmD;IAElE,oBAAOF,IAAA,CAACW,MAAM;MAAA,GAAKD,IAAI;MAAEH,KAAK,EAAEA,KAAK,GAAG,CAACE,QAAQ,EAAEF,KAAK,CAAC,GAAGE;IAAS,CAAE,CAAC;EAC1E,CAAC;EAEDH,IAAI,CAACH,WAAW,GAAG,MAAMF,MAAM,CAACC,SAAS,CAAC,GAAG;EAE7C,oBAAOL,IAAI,CAACS,IAAI,CAAC;AACnB,CAAC","ignoreList":[]}
@@ -0,0 +1,15 @@
1
+ import { type ActiveBreakpoint } from '@hzblj/kara-theme';
2
+ import type { ResponsiveOf } from './responsive.types';
3
+ /**
4
+ * Collapses a responsive `sx` into the flat one the active breakpoint asks for.
5
+ *
6
+ * Deliberately upstream of the caches rather than inside them: `resolve-cache` and `sxKey` only ever
7
+ * see flat values, so neither their one-level key flattening nor their key space has to grow a
8
+ * breakpoint dimension — and two devices that land on the same flat `sx` still share its entry. A
9
+ * breakpoint folded into the cache key instead would have doubled the entries for every `sx` in the
10
+ * app, responsive or not.
11
+ *
12
+ * Hands back the very object it was given when nothing in it is responsive, which is the overwhelming
13
+ * case: `sx()` wraps every view, and those call sites paying nothing is what keeps it affordable.
14
+ */
15
+ export declare const flattenSx: <TSx extends object, TKey extends keyof TSx & string>(sx: ResponsiveOf<TSx, TKey>, keys: readonly TKey[], active: ActiveBreakpoint) => TSx;
@@ -0,0 +1,16 @@
1
+ export * from './flatten-sx';
2
+ export * from './resolve-cache';
3
+ export * from './responsive.types';
4
+ export * from './responsive-sx';
5
+ export * from './sx.types';
6
+ export * from './sx-key';
7
+ export * from './sx-keys';
8
+ export * from './sx-padding';
9
+ export * from './sx-to-modifiers';
10
+ export * from './sx-to-style';
11
+ export * from './use-sx';
12
+ export * from './use-sx-modifiers';
13
+ export * from './value-key';
14
+ export * from './view-sx.types';
15
+ export * from './view-sx-to-style';
16
+ export * from './with-sx';
@@ -0,0 +1,14 @@
1
+ import type { Theme } from '@hzblj/kara-theme';
2
+ type StyleResolver<TProps, TStyle> = (props: TProps, theme: Theme) => TStyle;
3
+ /**
4
+ * `resolve` takes `TProps`, `split` hands back `TInput`. The same surface, except that props reach
5
+ * `split` straight off a component with responsive values still in them, and reach `resolve` only once
6
+ * `flattenSx` has collapsed those — so a caller who splits has to flatten before it can resolve.
7
+ * Defaults to `TProps`, for a cache whose surface has nothing responsive in it.
8
+ */
9
+ export type SxCache<TProps, TStyle, TInput = TProps> = {
10
+ resolve: (props: TProps, theme: Theme) => TStyle;
11
+ split: <T extends Record<string, unknown>>(props: T) => [TInput, Record<string, unknown>];
12
+ };
13
+ export declare const createSxCache: <TProps extends Record<string, unknown>, TStyle, TInput = TProps>(keys: readonly (keyof TProps & string)[], resolver: StyleResolver<TProps, TStyle>) => SxCache<TProps, TStyle, TInput>;
14
+ export {};
@@ -0,0 +1,80 @@
1
+ import type { ResponsiveOf } from './responsive.types';
2
+ import type { Sx } from './sx.types';
3
+ import type { ViewSx } from './view-sx.types';
4
+ /**
5
+ * Layout keys only, and deliberately so: a wider screen wants a different gap, padding or column
6
+ * count — not a different colour. `bg`, `shadow`, the radii, `opacity`, the transforms and both
7
+ * platform buckets therefore stay scalar. Every key admitted here is one more that `flattenSx` walks
8
+ * on every render, for a kind of change a design system should not be making anyway.
9
+ *
10
+ * `Partial` because this is a subset by design; what the `satisfies` buys is the other direction — a
11
+ * key renamed in `SxCore` stops compiling here instead of silently going non-responsive.
12
+ */
13
+ declare const SX_RESPONSIVE_KEY_RECORD: {
14
+ readonly h: true;
15
+ readonly minH: true;
16
+ readonly minW: true;
17
+ readonly p: true;
18
+ readonly pb: true;
19
+ readonly pl: true;
20
+ readonly pr: true;
21
+ readonly pt: true;
22
+ readonly px: true;
23
+ readonly py: true;
24
+ readonly tall: true;
25
+ readonly w: true;
26
+ readonly wide: true;
27
+ };
28
+ export type ResponsiveSxKey = keyof typeof SX_RESPONSIVE_KEY_RECORD;
29
+ /** What `useSxModifiers` flattens before the SwiftUI and Compose paths see it. */
30
+ export declare const SX_RESPONSIVE_KEYS: readonly ResponsiveSxKey[];
31
+ /** The core keys plus what only the React Native style path has: margins, gaps, flex, sizing maxima. */
32
+ declare const VIEW_RESPONSIVE_KEY_RECORD: {
33
+ readonly h: true;
34
+ readonly minH: true;
35
+ readonly minW: true;
36
+ readonly p: true;
37
+ readonly pb: true;
38
+ readonly pl: true;
39
+ readonly pr: true;
40
+ readonly pt: true;
41
+ readonly px: true;
42
+ readonly py: true;
43
+ readonly tall: true;
44
+ readonly w: true;
45
+ readonly wide: true;
46
+ readonly align: true;
47
+ readonly alignContent: true;
48
+ readonly alignSelf: true;
49
+ readonly basis: true;
50
+ readonly columnGap: true;
51
+ readonly display: true;
52
+ readonly flex: true;
53
+ readonly flexDirection: true;
54
+ readonly gap: true;
55
+ readonly grow: true;
56
+ readonly justify: true;
57
+ readonly m: true;
58
+ readonly maxH: true;
59
+ readonly maxW: true;
60
+ readonly mb: true;
61
+ readonly ml: true;
62
+ readonly mr: true;
63
+ readonly mt: true;
64
+ readonly mx: true;
65
+ readonly my: true;
66
+ readonly rowGap: true;
67
+ readonly shrink: true;
68
+ readonly wrap: true;
69
+ };
70
+ export type ResponsiveViewSxKey = keyof typeof VIEW_RESPONSIVE_KEY_RECORD;
71
+ /** What `useSx` flattens before the style cache sees it. */
72
+ export declare const VIEW_RESPONSIVE_KEYS: readonly ResponsiveViewSxKey[];
73
+ /**
74
+ * The native modifier surface as a component takes it — `Sx` is the same surface once a breakpoint
75
+ * has been picked, which is what every resolver and cache downstream of `flattenSx` works with.
76
+ */
77
+ export type ResponsiveSx = ResponsiveOf<Sx, ResponsiveSxKey>;
78
+ /** `ViewSx` as a component takes it, standing to it as `ResponsiveSx` does to `Sx`. */
79
+ export type ResponsiveViewSx = ResponsiveOf<ViewSx, ResponsiveViewSxKey>;
80
+ export {};
@@ -0,0 +1,23 @@
1
+ import type { Breakpoint } from '@hzblj/kara-theme';
2
+ /**
3
+ * A value that may differ per breakpoint: the plain value, or one keyed by breakpoint.
4
+ *
5
+ * `base` is mandatory. Partly because the cascade needs a floor to fall back to, and partly because
6
+ * an `sx` that applies nothing on the narrowest phone is a bug rather than a style.
7
+ *
8
+ * The cascade runs mobile-first — a breakpoint holds until a wider one overrides it. So
9
+ * `{base: 's8', md: 's16'}` pads by 8 below `md` and by 16 from `md` up, `lg` and `xl` included.
10
+ */
11
+ export type Responsive<TValue> = TValue | ({
12
+ base: TValue;
13
+ } & Partial<Record<Breakpoint, TValue>>);
14
+ /**
15
+ * Widens the named keys of a flat `sx` surface to `Responsive`, leaving the rest alone.
16
+ *
17
+ * A transform over the flat type rather than a hand-written twin, so a key added to `Sx` or `ViewSx`
18
+ * needs no second edit here — and `NonNullable`, so the optionality stays on the prop and cannot
19
+ * sneak into `base`, which would defeat the point of requiring it.
20
+ */
21
+ export type ResponsiveOf<TSx, TKey extends keyof TSx> = Omit<TSx, TKey> & {
22
+ [K in TKey]?: Responsive<NonNullable<TSx[K]>>;
23
+ };
@@ -0,0 +1,7 @@
1
+ import type { Sx } from './sx.types';
2
+ /**
3
+ * A stable `useMemo` dependency for an `Sx`. Atoms take theirs from a rest spread, so the object is
4
+ * a fresh identity on every render even when nothing in it changed — the values flattened into one
5
+ * string say exactly as much as the object does.
6
+ */
7
+ export declare const sxKey: (sx: Sx) => string;
@@ -0,0 +1,6 @@
1
+ import type { Sx, SxCore } from './sx.types';
2
+ /** The keys every target shares. The React Native style path takes these and none of the buckets. */
3
+ export declare const SX_CORE_KEYS: readonly (keyof SxCore)[];
4
+ /** Kept apart from `SX_CORE_KEYS` so the React Native path can take the core without them. */
5
+ export declare const SX_BUCKET_KEYS: readonly Exclude<keyof Sx, keyof SxCore>[];
6
+ export declare const SX_KEYS: readonly (keyof Sx)[];
@@ -0,0 +1,5 @@
1
+ import type { Sx, SxPadding } from './sx.types';
2
+ /** Padding is all this reads, so both `Sx` and the widened `StyleSx` satisfy it. */
3
+ type SxPaddingInput = Pick<Sx, 'p' | 'pb' | 'pl' | 'pr' | 'pt' | 'px' | 'py'>;
4
+ export declare const sxPadding: (sx: SxPaddingInput) => SxPadding | undefined;
5
+ export {};
@@ -0,0 +1 @@
1
+ export * from './sx-to-modifiers.ios';
@@ -0,0 +1,4 @@
1
+ import { type ModifierConfig } from '@expo/ui/swift-ui/modifiers';
2
+ import { type Theme } from '@hzblj/kara-theme';
3
+ import type { FrameAlignment, Sx } from './sx.types';
4
+ export declare const sxToModifiers: (sx: Sx, theme: Theme, alignment?: FrameAlignment) => ModifierConfig[];
@@ -0,0 +1,4 @@
1
+ import { type Theme } from '@hzblj/kara-theme';
2
+ import { type ViewStyle } from 'react-native';
3
+ import type { StyleSx } from './sx.types';
4
+ export declare const sxToStyle: (sx: StyleSx, theme: Theme) => ViewStyle;
@@ -0,0 +1,182 @@
1
+ import type { ModifierConfig as AndroidModifier } from '@expo/ui/jetpack-compose/modifiers';
2
+ import type { ModifierConfig as IosModifier } from '@expo/ui/swift-ui/modifiers';
3
+ import type { ColorToken, OpacitySize, RadiiSize, ShadowName, SpaceSize, ZIndexSize } from '@hzblj/kara-theme';
4
+ /** A length React Native accepts: absolute points, or a percentage of the parent. */
5
+ export type SxDimension = `${number}%` | number;
6
+ /**
7
+ * The keys all three targets — SwiftUI modifiers, Compose modifiers and React Native styles — can
8
+ * express with the same meaning. A key only belongs here if all three honour it; anything one of them
9
+ * has to fake or ignore goes to `IosSx`, `AndroidSx` or `ViewSx` instead.
10
+ */
11
+ export type SxCore = {
12
+ bg?: ColorToken;
13
+ blur?: number;
14
+ borderColor?: ColorToken;
15
+ borderRadius?: RadiiSize;
16
+ borderWidth?: number;
17
+ h?: number;
18
+ minH?: number;
19
+ minW?: number;
20
+ offsetX?: number;
21
+ offsetY?: number;
22
+ opacity?: OpacitySize;
23
+ p?: SpaceSize;
24
+ pb?: SpaceSize;
25
+ pl?: SpaceSize;
26
+ pr?: SpaceSize;
27
+ pt?: SpaceSize;
28
+ px?: SpaceSize;
29
+ py?: SpaceSize;
30
+ /** Clockwise, in degrees. */
31
+ rotate?: number;
32
+ /** Uniform, or per axis — an omitted axis stays at 1. */
33
+ scale?: number | {
34
+ x?: number;
35
+ y?: number;
36
+ };
37
+ shadow?: ShadowName;
38
+ tall?: boolean;
39
+ w?: number;
40
+ wide?: boolean;
41
+ zIndex?: ZIndexSize;
42
+ };
43
+ /** Liquid Glass, as SwiftUI's `glassEffect` names its variants. */
44
+ export type GlassVariant = 'clear' | 'identity' | 'regular';
45
+ /**
46
+ * Every declared value in a platform bucket is a primitive — or one flat object of primitives, for
47
+ * modifiers that take several settings at once — because `sxKey` identifies an `sx` by flattening
48
+ * its values into a string, one level deep. Anything deeper would collapse to `[object Object]` and
49
+ * two different configs would share a cache entry. `modifiers` is the sole exception, keyed by
50
+ * identity.
51
+ */
52
+ export type SxBucketValue = boolean | number | string | undefined;
53
+ /** One modifier's settings: a single flat level, so `sxKey`'s one-level walk captures all of it. */
54
+ export type SxBucketConfig = {
55
+ [setting: string]: SxBucketValue;
56
+ };
57
+ /** Holds a bucket to `SxBucketValue`/`SxBucketConfig`, so a key breaking that rule refuses to compile. */
58
+ type Bucket<T extends {
59
+ [K in keyof T]: K extends 'modifiers' ? T[K] : SxBucketConfig | SxBucketValue;
60
+ }> = T;
61
+ /** What gets redacted: skeleton placeholder, privacy blur, or the "pending update" restyle. */
62
+ export type RedactionReason = 'invalidated' | 'placeholder' | 'privacy';
63
+ /**
64
+ * SwiftUI modifiers with no honest Compose counterpart. Setting these on Android is inert rather than
65
+ * a type error — a design system degrades gracefully instead of forcing every call site to branch.
66
+ */
67
+ export type IosSx = Bucket<{
68
+ /** Width over height, fitted within the proposed size. The escape hatch covers `fill`. */
69
+ aspectRatio?: number;
70
+ brightness?: number;
71
+ clipped?: boolean;
72
+ colorInvert?: boolean;
73
+ /**
74
+ * Sizes the box relative to the nearest container: split it into `count` columns `spacing` apart
75
+ * and span `span` of them — SwiftUI's stand-in for a fractional width, which its `frame` lacks.
76
+ */
77
+ containerRelativeFrame?: {
78
+ alignment?: FrameAlignment;
79
+ axes: 'both' | 'horizontal' | 'vertical';
80
+ count?: number;
81
+ span?: number;
82
+ spacing?: number;
83
+ };
84
+ /** How a content change animates when one is driven natively. `countsDown` is `numericText`'s. */
85
+ contentTransition?: {
86
+ countsDown?: boolean;
87
+ type: 'identity' | 'interpolate' | 'numericText' | 'opacity';
88
+ };
89
+ /** Cascades to every control in the subtree, the SwiftUI environment way. */
90
+ controlSize?: 'extraLarge' | 'large' | 'mini' | 'regular' | 'small';
91
+ contrast?: number;
92
+ fixedSize?: 'both' | 'horizontal' | 'vertical';
93
+ /**
94
+ * Liquid Glass: a bare variant, or the full config. `tint` takes a theme token, and without a
95
+ * `shape` the glass traces the box's own `borderRadius`, the way strokes and shadows do.
96
+ */
97
+ glass?: GlassVariant | {
98
+ cornerRadius?: number;
99
+ interactive?: boolean;
100
+ shape?: 'capsule' | 'circle' | 'containerRelativeShape' | 'ellipse' | 'rectangle' | 'roundedRectangle';
101
+ tint?: ColorToken;
102
+ variant: GlassVariant;
103
+ };
104
+ grayscale?: number;
105
+ /** Invisible, but still taking up its layout space — unlike not rendering the box at all. */
106
+ hidden?: boolean;
107
+ /** In degrees. */
108
+ hueRotation?: number;
109
+ /** The height SwiftUI prefers when nothing constrains it — what `fixedSize` resolves to. */
110
+ idealH?: number;
111
+ /** The width SwiftUI prefers when nothing constrains it — what `fixedSize` resolves to. */
112
+ idealW?: number;
113
+ /** `true` extends into every safe area; the config narrows which regions and edges. */
114
+ ignoreSafeArea?: boolean | {
115
+ edges?: 'all' | 'bottom' | 'horizontal' | 'leading' | 'top' | 'trailing' | 'vertical';
116
+ regions?: 'all' | 'container' | 'keyboard';
117
+ };
118
+ /** Who gets space first when the parent runs short — *not* a proportional flex weight. */
119
+ layoutPriority?: number;
120
+ luminanceToAlpha?: boolean;
121
+ /** Escape hatch, appended last. Pass a stable array — a fresh one every render defeats the memo. */
122
+ modifiers?: IosModifier[];
123
+ /** Redacts only when an ancestor applies the `privacy` reason — inert on its own. */
124
+ privacySensitive?: boolean;
125
+ /**
126
+ * Redacts this subtree — `placeholder` is SwiftUI's built-in skeleton. One reason here;
127
+ * combining several is escape-hatch territory.
128
+ */
129
+ redacted?: RedactionReason;
130
+ saturation?: number;
131
+ /** Cascades to the controls and icons in the subtree. */
132
+ tint?: ColorToken;
133
+ /** Exempts this subtree from an ancestor's `redacted`. */
134
+ unredacted?: boolean;
135
+ }>;
136
+ /** Compose modifiers with no honest SwiftUI counterpart. Inert on iOS, by the same argument. */
137
+ export type AndroidSx = Bucket<{
138
+ /** This box's own placement inside a `ZStack` parent — Compose's per-child `Modifier.align`. */
139
+ align?: 'bottom' | 'bottomCenter' | 'bottomEnd' | 'bottomStart' | 'center' | 'centerEnd' | 'centerHorizontally' | 'centerStart' | 'centerVertically' | 'end' | 'start' | 'top' | 'topCenter' | 'topEnd' | 'topStart';
140
+ animateContentSize?: boolean;
141
+ /** Fraction of the parent's height (0–1). The whole of it is `tall`, which works on iOS too. */
142
+ fillMaxHeight?: number;
143
+ /** Fraction of the parent's width (0–1). The whole of it is `wide`, which works on iOS too. */
144
+ fillMaxWidth?: number;
145
+ imePadding?: boolean;
146
+ matchParentSize?: boolean;
147
+ /** Escape hatch, appended last. Pass a stable array — a fresh one every render defeats the memo. */
148
+ modifiers?: AndroidModifier[];
149
+ /** Proportional share of the leftover space in a Row or Column, the way `flexGrow` behaves. */
150
+ weight?: number;
151
+ wrapContentHeight?: 'bottom' | 'centerVertically' | 'top' | boolean;
152
+ wrapContentWidth?: 'centerHorizontally' | 'end' | 'start' | boolean;
153
+ }>;
154
+ /**
155
+ * The native modifier surface: what SwiftUI and Compose can both express, plus a bucket each for what
156
+ * only one of them can. Both buckets exist on both platforms so a component's shared `*.types.ts`
157
+ * contract — and the `contract.check.ts` that holds the two implementations to it — stays one type.
158
+ */
159
+ export type Sx = SxCore & {
160
+ android?: AndroidSx;
161
+ ios?: IosSx;
162
+ };
163
+ /**
164
+ * `SxCore` for the React Native style path, which — unlike the SwiftUI/Compose modifiers, where a
165
+ * frame needs concrete points — can size a view as a percentage of its parent. Deliberately built
166
+ * from `SxCore` and not `Sx`: React Native styles are identical on both platforms, so the `ios` and
167
+ * `android` buckets would have nothing to resolve into and would silently swallow whatever was passed.
168
+ */
169
+ export type StyleSx = Omit<SxCore, 'h' | 'minH' | 'minW' | 'w'> & {
170
+ h?: SxDimension;
171
+ minH?: SxDimension;
172
+ minW?: SxDimension;
173
+ w?: SxDimension;
174
+ };
175
+ export type FrameAlignment = 'bottom' | 'bottomLeading' | 'bottomTrailing' | 'center' | 'leading' | 'top' | 'topLeading' | 'topTrailing' | 'trailing';
176
+ export type SxPadding = {
177
+ bottom?: number;
178
+ leading?: number;
179
+ top?: number;
180
+ trailing?: number;
181
+ };
182
+ export {};
@@ -0,0 +1 @@
1
+ export * from './use-sx-modifiers.ios';
@@ -0,0 +1,14 @@
1
+ import type { ModifierConfig } from '@expo/ui/swift-ui/modifiers';
2
+ import { type ResponsiveSx } from './responsive-sx';
3
+ import type { FrameAlignment } from './sx.types';
4
+ /**
5
+ * `sxToModifiers` behind a `useMemo`, so a re-render hands the native view the modifier array it is
6
+ * already holding instead of an equal-but-new one to diff.
7
+ *
8
+ * The responsive flattening happens before `sxKey`, so the key describes the values actually applied
9
+ * at this breakpoint — a rotation to a wider window changes it, and nothing else does.
10
+ *
11
+ * `ios.modifiers` is depended on by identity, because `sxKey` cannot flatten opaque modifier configs
12
+ * into a string. A call site that builds that array inline therefore re-resolves every render.
13
+ */
14
+ export declare const useSxModifiers: (sx: ResponsiveSx, alignment?: FrameAlignment) => ModifierConfig[];
@@ -0,0 +1,15 @@
1
+ import type { ViewStyle } from 'react-native';
2
+ import { type ResponsiveViewSx } from './responsive-sx';
3
+ /**
4
+ * Resolves an `sx` object into a React Native style. Needs no `useMemo`: the cache keys on the
5
+ * flattened sx values, so the same sx at the same breakpoint hands back the very same object every
6
+ * render — and across components.
7
+ */
8
+ export declare const useSx: (sx: ResponsiveViewSx) => ViewStyle;
9
+ /**
10
+ * `useSx` for a component whose own props arrive mixed in with the `sx` ones: the `sx` keys are split
11
+ * off and resolved, and the rest is handed back untouched. What `sx()` does internally, exposed for the
12
+ * components that cannot be built on it because they own their `style` prop — an animated one, or a
13
+ * `ScrollView` styling two boxes at once.
14
+ */
15
+ export declare const useSplitSx: <TProps extends Record<string, unknown>>(props: TProps) => [ViewStyle, Record<string, unknown>];
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Flattens a value into a cache-key fragment. Objects are walked one level — with keys sorted, so
3
+ * two configs holding the same values key alike — rather than left to `String`, which turns every
4
+ * object into the same `[object Object]` and would have two different ones share a cache entry.
5
+ * One level is all the `Bucket` constraint admits, so deeper nesting cannot reach this.
6
+ */
7
+ export declare const valueKey: (value: unknown) => string;