@muja-ui/native 0.3.0 → 0.4.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/README.md +44 -10
- package/dist/index.cjs +467 -137
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +110 -18
- package/dist/index.d.ts +110 -18
- package/dist/index.js +465 -140
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.cts
CHANGED
|
@@ -2,7 +2,7 @@ import * as react from 'react';
|
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import * as react_native from 'react-native';
|
|
4
4
|
import { FlexStyle, ViewStyle, ViewProps, StyleProp, View, TextStyle, TextProps as TextProps$1, Text as Text$1, PressableProps, TextInputProps, TextInput, DimensionValue } from 'react-native';
|
|
5
|
-
import { Theme, IconDefinition, Variant, Size, ColorMode, ResolvedColorMode } from '@muja-ui/core';
|
|
5
|
+
import { Theme, IconDefinition, Variant, Size, ColorMode, ResolvedColorMode, ThemeOverride } from '@muja-ui/core';
|
|
6
6
|
export { ColorMode, IconDefinition, ResolvedColorMode, Size, Status, Theme, ThemeOverride, Variant, createTheme, darkTheme, lightTheme, registerIcons } from '@muja-ui/core';
|
|
7
7
|
import { SpaceToken, SemanticColorToken, BorderWidthToken, RadiusToken, ShadowToken, ZIndexToken, ShadowValue, FontSizeToken, FontWeightToken, FontFamilyToken, LineHeightToken, LetterSpacingToken } from '@muja-ui/tokens';
|
|
8
8
|
|
|
@@ -144,7 +144,9 @@ type TextProps = TextOwnProps & StyleProps & Omit<TextProps$1, 'style'> & {
|
|
|
144
144
|
/**
|
|
145
145
|
* Typography primitive. Color always comes from a semantic token, never a raw
|
|
146
146
|
* value. React Native needs an absolute `lineHeight`, so the unitless token
|
|
147
|
-
* multiplier is resolved against the font size here
|
|
147
|
+
* multiplier is resolved against the font size here, and the theme's CSS font
|
|
148
|
+
* stack is reduced to the one family the platform can load (see
|
|
149
|
+
* `nativeFontFamily`) — the system font unless the theme names a brand face.
|
|
148
150
|
*
|
|
149
151
|
* ```tsx
|
|
150
152
|
* <Text size="sm" color="textSecondary" truncate>…</Text>
|
|
@@ -161,7 +163,8 @@ interface HeadingProps extends Omit<TextProps, 'accessibilityRole'> {
|
|
|
161
163
|
}
|
|
162
164
|
/**
|
|
163
165
|
* A heading with the correct accessibility role. Sizes follow the level unless
|
|
164
|
-
* `size` overrides them.
|
|
166
|
+
* `size` overrides them. On iOS the two top levels are bold, matching Large
|
|
167
|
+
* Title / Title 1; the rest are semibold like Headline.
|
|
165
168
|
*
|
|
166
169
|
* ```tsx
|
|
167
170
|
* <Heading level={2}>Upcoming events</Heading>
|
|
@@ -213,7 +216,9 @@ interface ButtonProps extends Omit<PressableProps, 'style' | 'children'> {
|
|
|
213
216
|
}
|
|
214
217
|
/**
|
|
215
218
|
* Pressable button. Same variant/size vocabulary as `@muja-ui/web`'s Button;
|
|
216
|
-
* every color resolves from a semantic theme token.
|
|
219
|
+
* every color resolves from a semantic theme token. Heights are minimums so
|
|
220
|
+
* the label can grow with Dynamic Type; a `sm` button widens its touch area
|
|
221
|
+
* to the 44pt floor.
|
|
217
222
|
*
|
|
218
223
|
* ```tsx
|
|
219
224
|
* <Button variant="primary" size="lg" loading onPress={save}>Save</Button>
|
|
@@ -257,6 +262,11 @@ interface InputProps extends Omit<TextInputProps, 'style' | 'editable'> {
|
|
|
257
262
|
* Single-line text field. Focus and invalid states are drawn on the wrapper so
|
|
258
263
|
* adornments sit inside the border.
|
|
259
264
|
*
|
|
265
|
+
* On iOS the field is a filled, borderless rounded rect like a UIKit search
|
|
266
|
+
* field or grouped-list cell; a stroke appears only for focus and errors. The
|
|
267
|
+
* keyboard follows the color mode and shows the native clear button while
|
|
268
|
+
* editing (unless a `rightElement` occupies that spot).
|
|
269
|
+
*
|
|
260
270
|
* ```tsx
|
|
261
271
|
* <Input size="md" placeholder="Email" invalid={!!error} />
|
|
262
272
|
* ```
|
|
@@ -270,7 +280,7 @@ interface TextareaProps extends Omit<TextInputProps, 'style' | 'editable' | 'mul
|
|
|
270
280
|
rows?: number;
|
|
271
281
|
style?: StyleProp<TextStyle>;
|
|
272
282
|
}
|
|
273
|
-
/** Multi-line text field. Same states as `Input`. */
|
|
283
|
+
/** Multi-line text field. Same states — and the same iOS filled look — as `Input`. */
|
|
274
284
|
declare const Textarea: react.ForwardRefExoticComponent<TextareaProps & react.RefAttributes<TextInput>>;
|
|
275
285
|
|
|
276
286
|
interface LabelProps extends TextProps {
|
|
@@ -321,7 +331,9 @@ interface CheckboxProps {
|
|
|
321
331
|
style?: StyleProp<ViewStyle>;
|
|
322
332
|
}
|
|
323
333
|
/**
|
|
324
|
-
* Checkbox with an optional inline label.
|
|
334
|
+
* Checkbox with an optional inline label. iOS has no square checkbox — the
|
|
335
|
+
* idiom (Reminders, Mail's edit mode) is a circle that fills with a tick — so
|
|
336
|
+
* the box is round there and square elsewhere.
|
|
325
337
|
*
|
|
326
338
|
* ```tsx
|
|
327
339
|
* <Checkbox checked={agreed} onChange={setAgreed}>I agree</Checkbox>
|
|
@@ -339,9 +351,12 @@ interface SwitchProps {
|
|
|
339
351
|
style?: StyleProp<ViewStyle>;
|
|
340
352
|
}
|
|
341
353
|
/**
|
|
342
|
-
* Toggle switch.
|
|
343
|
-
*
|
|
344
|
-
*
|
|
354
|
+
* Toggle switch.
|
|
355
|
+
*
|
|
356
|
+
* On iOS this is the real `UISwitch` (through React Native's `Switch`), tinted
|
|
357
|
+
* with the theme's primary colour — native motion, haptics and VoiceOver
|
|
358
|
+
* semantics for free, as the HIG asks. Elsewhere it is drawn from primitives so
|
|
359
|
+
* it follows the theme's metrics on both platforms.
|
|
345
360
|
*
|
|
346
361
|
* ```tsx
|
|
347
362
|
* <Switch checked={enabled} onChange={setEnabled}>Notifications</Switch>
|
|
@@ -570,7 +585,8 @@ interface CardProps {
|
|
|
570
585
|
}
|
|
571
586
|
/**
|
|
572
587
|
* Surface container. Compose with `CardHeader`, `CardTitle`,
|
|
573
|
-
* `CardDescription`, `CardContent` and `CardFooter`.
|
|
588
|
+
* `CardDescription`, `CardContent` and `CardFooter`. On iOS the `outline`
|
|
589
|
+
* stroke is a hairline, the way grouped cells are separated.
|
|
574
590
|
*
|
|
575
591
|
* ```tsx
|
|
576
592
|
* <Card variant="elevated" onPress={open}>
|
|
@@ -672,7 +688,8 @@ interface ListRowProps {
|
|
|
672
688
|
}
|
|
673
689
|
/**
|
|
674
690
|
* Settings/list row: leading slot, two lines of text, trailing slot. Pressable
|
|
675
|
-
* rows get a chevron and a button role.
|
|
691
|
+
* rows get a chevron and a button role. On iOS the row follows a table cell:
|
|
692
|
+
* 44pt minimum, body-size title, secondary-label subtitle, bold chevron.
|
|
676
693
|
*
|
|
677
694
|
* ```tsx
|
|
678
695
|
* <ListRow title="Notifications" subtitle="Push and email" onPress={open} />
|
|
@@ -720,6 +737,9 @@ interface TabsProps<T extends string = string> {
|
|
|
720
737
|
* because native screens usually swap whole lists rather than mounting all
|
|
721
738
|
* panels at once.
|
|
722
739
|
*
|
|
740
|
+
* On iOS `segmented` is drawn as a `UISegmentedControl`: a 2pt inset track,
|
|
741
|
+
* the selected segment lifted on a white pill with a soft shadow, 13pt labels.
|
|
742
|
+
*
|
|
723
743
|
* ```tsx
|
|
724
744
|
* <Tabs items={tabs} value={tab} onChange={setTab} variant="segmented" />
|
|
725
745
|
* ```
|
|
@@ -877,6 +897,7 @@ interface ModalBodyProps {
|
|
|
877
897
|
style?: StyleProp<ViewStyle>;
|
|
878
898
|
}
|
|
879
899
|
declare function ModalBody({ children, scrollable, style }: ModalBodyProps): react.JSX.Element;
|
|
900
|
+
/** Action row. On iOS a hairline separates it from the body, as in an alert. */
|
|
880
901
|
declare function ModalFooter({ children, style, }: {
|
|
881
902
|
children?: ReactNode;
|
|
882
903
|
style?: StyleProp<ViewStyle>;
|
|
@@ -898,8 +919,9 @@ interface BottomSheetProps {
|
|
|
898
919
|
}
|
|
899
920
|
/**
|
|
900
921
|
* Sheet that slides up from the bottom edge, with a grab handle and
|
|
901
|
-
* drag-to-dismiss.
|
|
902
|
-
*
|
|
922
|
+
* drag-to-dismiss. It arrives on a spring with a fading backdrop, the way a
|
|
923
|
+
* UIKit sheet is presented, and the bottom inset is padded so content clears
|
|
924
|
+
* the home indicator. On iOS the grabber matches the system's 36×5.
|
|
903
925
|
*
|
|
904
926
|
* ```tsx
|
|
905
927
|
* <BottomSheet open={open} onClose={close} title="Pick a room">…</BottomSheet>
|
|
@@ -951,6 +973,11 @@ interface ActionSheetProps {
|
|
|
951
973
|
* package's `DropdownMenu`. Anchored dropdowns don't belong on a phone, so the
|
|
952
974
|
* same intent surfaces as a sheet.
|
|
953
975
|
*
|
|
976
|
+
* On iOS it takes the `UIAlertController` action-sheet form: a floating inset
|
|
977
|
+
* group of centred, tint-coloured rows separated by hairlines, destructive
|
|
978
|
+
* rows in red, and Cancel as its own bold card underneath. Elsewhere it is a
|
|
979
|
+
* list inside `BottomSheet`.
|
|
980
|
+
*
|
|
954
981
|
* ```tsx
|
|
955
982
|
* <ActionSheet open={open} onClose={close} actions={[
|
|
956
983
|
* { label: 'Share ticket', onPress: share },
|
|
@@ -958,7 +985,7 @@ interface ActionSheetProps {
|
|
|
958
985
|
* ]} />
|
|
959
986
|
* ```
|
|
960
987
|
*/
|
|
961
|
-
declare function ActionSheet(
|
|
988
|
+
declare function ActionSheet(props: ActionSheetProps): react.JSX.Element;
|
|
962
989
|
|
|
963
990
|
interface ThemeContextValue {
|
|
964
991
|
/** The active theme for the resolved color mode. */
|
|
@@ -984,11 +1011,18 @@ interface ThemeProviderProps {
|
|
|
984
1011
|
*/
|
|
985
1012
|
colorMode?: ColorMode;
|
|
986
1013
|
onColorModeChange?: (mode: ColorMode) => void;
|
|
1014
|
+
/**
|
|
1015
|
+
* Lay the platform's own metrics over the theme — on iOS the HIG type scale
|
|
1016
|
+
* (Body 17, Footnote 13…) and UIKit radii. Colors are never touched. Defaults
|
|
1017
|
+
* to true; turn off to render the shared tokens verbatim on every platform.
|
|
1018
|
+
*/
|
|
1019
|
+
platformAdaptive?: boolean;
|
|
987
1020
|
children: ReactNode;
|
|
988
1021
|
}
|
|
989
1022
|
/**
|
|
990
1023
|
* Provides the resolved theme to every native component. `'system'` follows the
|
|
991
|
-
* OS appearance through React Native's `useColorScheme()`.
|
|
1024
|
+
* OS appearance through React Native's `useColorScheme()`. On iOS the theme is
|
|
1025
|
+
* rendered through Apple HIG metrics (see `adaptThemeToPlatform`).
|
|
992
1026
|
*
|
|
993
1027
|
* ```tsx
|
|
994
1028
|
* <ThemeProvider theme={sduLightTheme} darkTheme={sduDarkTheme}>
|
|
@@ -996,7 +1030,7 @@ interface ThemeProviderProps {
|
|
|
996
1030
|
* </ThemeProvider>
|
|
997
1031
|
* ```
|
|
998
1032
|
*/
|
|
999
|
-
declare function ThemeProvider({ theme, darkTheme, defaultColorMode, colorMode: colorModeProp, onColorModeChange, children, }: ThemeProviderProps): react.JSX.Element;
|
|
1033
|
+
declare function ThemeProvider({ theme, darkTheme, defaultColorMode, colorMode: colorModeProp, onColorModeChange, platformAdaptive, children, }: ThemeProviderProps): react.JSX.Element;
|
|
1000
1034
|
/** The active theme object (already resolved for the current color mode). */
|
|
1001
1035
|
declare function useTheme(): Theme;
|
|
1002
1036
|
/** Color mode state and controls. */
|
|
@@ -1018,9 +1052,24 @@ interface VariantColors {
|
|
|
1018
1052
|
* Maps a `Variant` onto semantic theme colors. Web does this in CSS via
|
|
1019
1053
|
* `data-variant` selectors; native resolves it here so both platforms answer
|
|
1020
1054
|
* `variant="accent"` with the same roles.
|
|
1055
|
+
*
|
|
1056
|
+
* On iOS the two chrome-less variants follow UIKit's button configurations:
|
|
1057
|
+
* `outline` renders as *tinted* (a soft primary fill, no stroke — iOS has no
|
|
1058
|
+
* stroked buttons) and `ghost` as *plain* (tint-coloured label).
|
|
1021
1059
|
*/
|
|
1022
1060
|
declare function variantColors(variant: Variant, theme: Theme): VariantColors;
|
|
1023
|
-
/**
|
|
1061
|
+
/**
|
|
1062
|
+
* Background and opacity for a button-like pressable in its current state.
|
|
1063
|
+
* iOS dims the whole control (UIKit's highlight); Android swaps to the pressed
|
|
1064
|
+
* colour. Rows and cells are different — they highlight with a background on
|
|
1065
|
+
* both platforms, so they don't use this.
|
|
1066
|
+
*/
|
|
1067
|
+
declare function pressFeedback(pressed: boolean, colors: VariantColors): ViewStyle;
|
|
1068
|
+
/**
|
|
1069
|
+
* Control geometry per size — shared by Button, Input, Select and Textarea.
|
|
1070
|
+
* `height` is a minimum: controls grow with Dynamic Type / font scaling
|
|
1071
|
+
* instead of clipping their label.
|
|
1072
|
+
*/
|
|
1024
1073
|
interface SizeMetrics {
|
|
1025
1074
|
height: number;
|
|
1026
1075
|
paddingHorizontal: number;
|
|
@@ -1030,6 +1079,49 @@ interface SizeMetrics {
|
|
|
1030
1079
|
}
|
|
1031
1080
|
declare function sizeMetrics(size: Size, theme: Theme): SizeMetrics;
|
|
1032
1081
|
|
|
1082
|
+
/**
|
|
1083
|
+
* Read at call time (not module load) so a test can flip the stubbed
|
|
1084
|
+
* `Platform.OS` and exercise both branches of a component.
|
|
1085
|
+
*/
|
|
1086
|
+
declare function isIOS(): boolean;
|
|
1087
|
+
/**
|
|
1088
|
+
* Apple HIG metrics layered over the shared tokens on iOS.
|
|
1089
|
+
*
|
|
1090
|
+
* - Type scale follows the Dynamic Type default sizes: `xs` Footnote 13,
|
|
1091
|
+
* `sm` Subheadline 15, `md` Body 17, `lg` Title 3 20, `xl` Title 2 22,
|
|
1092
|
+
* `2xl` Title 1 28, `3xl` Large Title 34.
|
|
1093
|
+
* - Radii follow UIKit: 10 for controls and grouped cells, 12 for large
|
|
1094
|
+
* buttons and cards, 14 for alerts, 20 for sheets.
|
|
1095
|
+
*
|
|
1096
|
+
* Colors are untouched — brand and dark mode stay the theme's business.
|
|
1097
|
+
*/
|
|
1098
|
+
declare const iosThemeOverride: ThemeOverride;
|
|
1099
|
+
/**
|
|
1100
|
+
* Returns the theme the current platform should render: on iOS the HIG
|
|
1101
|
+
* metrics above are merged in, elsewhere the theme is returned as-is.
|
|
1102
|
+
* `ThemeProvider` applies this automatically (`platformAdaptive`).
|
|
1103
|
+
*/
|
|
1104
|
+
declare function adaptThemeToPlatform(theme: Theme): Theme;
|
|
1105
|
+
|
|
1106
|
+
/**
|
|
1107
|
+
* Turns a CSS font stack from the theme into the single family React Native
|
|
1108
|
+
* wants. The tokens are written as web stacks
|
|
1109
|
+
* (`"'Gilroy', -apple-system, BlinkMacSystemFont, …"`); passing that string
|
|
1110
|
+
* to `fontFamily` on iOS logs "Unrecognized font family" and silently falls
|
|
1111
|
+
* back, so the first usable entry is picked here instead:
|
|
1112
|
+
*
|
|
1113
|
+
* - a system keyword (`-apple-system`, `system-ui`, `sans-serif`, `System`…)
|
|
1114
|
+
* resolves to `undefined` — SF Pro on iOS, Roboto on Android;
|
|
1115
|
+
* - `ui-monospace` / `ui-serif` resolve to the platform's built-in face;
|
|
1116
|
+
* - web-only names (`Segoe UI`, `SF Mono`…) are skipped;
|
|
1117
|
+
* - anything else (`Gilroy`) is returned verbatim for the app to have loaded.
|
|
1118
|
+
*
|
|
1119
|
+
* ```ts
|
|
1120
|
+
* nativeFontFamily(theme.typography.fontFamily.sans) // → undefined on a stock theme
|
|
1121
|
+
* ```
|
|
1122
|
+
*/
|
|
1123
|
+
declare function nativeFontFamily(stack: string | undefined): string | undefined;
|
|
1124
|
+
|
|
1033
1125
|
/** Local-time whole-day helpers. The calendar never leaves local time. */
|
|
1034
1126
|
declare function startOfDay(date: Date): Date;
|
|
1035
1127
|
declare function startOfMonth(date: Date): Date;
|
|
@@ -1044,4 +1136,4 @@ declare function dayKey(date: Date): string;
|
|
|
1044
1136
|
*/
|
|
1045
1137
|
declare function monthGrid(month: Date, weekStartsOn: 0 | 1): Date[];
|
|
1046
1138
|
|
|
1047
|
-
export { Accordion, type AccordionItemData, type AccordionProps, ActionSheet, type ActionSheetAction, type ActionSheetProps, Avatar, type AvatarProps, Badge, type BadgeProps, type BadgeTone, BottomSheet, type BottomSheetProps, Box, type BoxProps, Button, type ButtonProps, Calendar, type CalendarProps, Card, CardContent, CardDescription, CardFooter, CardHeader, type CardProps, CardTitle, Carousel, type CarouselProps, Checkbox, type CheckboxProps, Chip, type ChipProps, Collapse, type CollapseProps, Container, type ContainerProps, Divider, type DividerProps, Drawer, type DrawerProps, EmptyState, type EmptyStateProps, Flex, type FlexOwnProps, type FlexProps, FormField, type FormFieldProps, HStack, Heading, type HeadingLevel, type HeadingProps, Icon, IconButton, type IconButtonProps, type IconProps, Input, type InputProps, Label, type LabelProps, ListRow, type ListRowProps, Modal, ModalBody, type ModalBodyProps, ModalFooter, ModalHeader, type ModalHeaderProps, type ModalProps, ModalTitle, Progress, type ProgressProps, Radio, RadioGroup, type RadioGroupProps, type RadioProps, Screen, type ScreenProps, Section, type SectionProps, Select, type SelectOption, type SelectProps, type SizeMetrics, Skeleton, type SkeletonProps, Spacer, type SpacerProps, Spinner, type SpinnerProps, Stack, type StackProps, type StyleProps, Switch, type SwitchProps, type TabItem, Tabs, type TabsProps, Text, type TextOwnProps, type TextProps, Textarea, type TextareaProps, type ThemeContextValue, ThemeProvider, type ThemeProviderProps, type ToastContextValue, type ToastOptions, type ToastPlacement, ToastProvider, type ToastProviderProps, type ToastTone, Tooltip, type TooltipProps, type VariantColors, addDays, addMonths, dayKey, isSameDay, monthGrid, shadowStyle, sizeMetrics, splitStyleProps, startOfDay, startOfMonth, useColorMode, useColorModeValue, useTheme, useToast, variantColors };
|
|
1139
|
+
export { Accordion, type AccordionItemData, type AccordionProps, ActionSheet, type ActionSheetAction, type ActionSheetProps, Avatar, type AvatarProps, Badge, type BadgeProps, type BadgeTone, BottomSheet, type BottomSheetProps, Box, type BoxProps, Button, type ButtonProps, Calendar, type CalendarProps, Card, CardContent, CardDescription, CardFooter, CardHeader, type CardProps, CardTitle, Carousel, type CarouselProps, Checkbox, type CheckboxProps, Chip, type ChipProps, Collapse, type CollapseProps, Container, type ContainerProps, Divider, type DividerProps, Drawer, type DrawerProps, EmptyState, type EmptyStateProps, Flex, type FlexOwnProps, type FlexProps, FormField, type FormFieldProps, HStack, Heading, type HeadingLevel, type HeadingProps, Icon, IconButton, type IconButtonProps, type IconProps, Input, type InputProps, Label, type LabelProps, ListRow, type ListRowProps, Modal, ModalBody, type ModalBodyProps, ModalFooter, ModalHeader, type ModalHeaderProps, type ModalProps, ModalTitle, Progress, type ProgressProps, Radio, RadioGroup, type RadioGroupProps, type RadioProps, Screen, type ScreenProps, Section, type SectionProps, Select, type SelectOption, type SelectProps, type SizeMetrics, Skeleton, type SkeletonProps, Spacer, type SpacerProps, Spinner, type SpinnerProps, Stack, type StackProps, type StyleProps, Switch, type SwitchProps, type TabItem, Tabs, type TabsProps, Text, type TextOwnProps, type TextProps, Textarea, type TextareaProps, type ThemeContextValue, ThemeProvider, type ThemeProviderProps, type ToastContextValue, type ToastOptions, type ToastPlacement, ToastProvider, type ToastProviderProps, type ToastTone, Tooltip, type TooltipProps, type VariantColors, adaptThemeToPlatform, addDays, addMonths, dayKey, iosThemeOverride, isIOS, isSameDay, monthGrid, nativeFontFamily, pressFeedback, shadowStyle, sizeMetrics, splitStyleProps, startOfDay, startOfMonth, useColorMode, useColorModeValue, useTheme, useToast, variantColors };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as react from 'react';
|
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import * as react_native from 'react-native';
|
|
4
4
|
import { FlexStyle, ViewStyle, ViewProps, StyleProp, View, TextStyle, TextProps as TextProps$1, Text as Text$1, PressableProps, TextInputProps, TextInput, DimensionValue } from 'react-native';
|
|
5
|
-
import { Theme, IconDefinition, Variant, Size, ColorMode, ResolvedColorMode } from '@muja-ui/core';
|
|
5
|
+
import { Theme, IconDefinition, Variant, Size, ColorMode, ResolvedColorMode, ThemeOverride } from '@muja-ui/core';
|
|
6
6
|
export { ColorMode, IconDefinition, ResolvedColorMode, Size, Status, Theme, ThemeOverride, Variant, createTheme, darkTheme, lightTheme, registerIcons } from '@muja-ui/core';
|
|
7
7
|
import { SpaceToken, SemanticColorToken, BorderWidthToken, RadiusToken, ShadowToken, ZIndexToken, ShadowValue, FontSizeToken, FontWeightToken, FontFamilyToken, LineHeightToken, LetterSpacingToken } from '@muja-ui/tokens';
|
|
8
8
|
|
|
@@ -144,7 +144,9 @@ type TextProps = TextOwnProps & StyleProps & Omit<TextProps$1, 'style'> & {
|
|
|
144
144
|
/**
|
|
145
145
|
* Typography primitive. Color always comes from a semantic token, never a raw
|
|
146
146
|
* value. React Native needs an absolute `lineHeight`, so the unitless token
|
|
147
|
-
* multiplier is resolved against the font size here
|
|
147
|
+
* multiplier is resolved against the font size here, and the theme's CSS font
|
|
148
|
+
* stack is reduced to the one family the platform can load (see
|
|
149
|
+
* `nativeFontFamily`) — the system font unless the theme names a brand face.
|
|
148
150
|
*
|
|
149
151
|
* ```tsx
|
|
150
152
|
* <Text size="sm" color="textSecondary" truncate>…</Text>
|
|
@@ -161,7 +163,8 @@ interface HeadingProps extends Omit<TextProps, 'accessibilityRole'> {
|
|
|
161
163
|
}
|
|
162
164
|
/**
|
|
163
165
|
* A heading with the correct accessibility role. Sizes follow the level unless
|
|
164
|
-
* `size` overrides them.
|
|
166
|
+
* `size` overrides them. On iOS the two top levels are bold, matching Large
|
|
167
|
+
* Title / Title 1; the rest are semibold like Headline.
|
|
165
168
|
*
|
|
166
169
|
* ```tsx
|
|
167
170
|
* <Heading level={2}>Upcoming events</Heading>
|
|
@@ -213,7 +216,9 @@ interface ButtonProps extends Omit<PressableProps, 'style' | 'children'> {
|
|
|
213
216
|
}
|
|
214
217
|
/**
|
|
215
218
|
* Pressable button. Same variant/size vocabulary as `@muja-ui/web`'s Button;
|
|
216
|
-
* every color resolves from a semantic theme token.
|
|
219
|
+
* every color resolves from a semantic theme token. Heights are minimums so
|
|
220
|
+
* the label can grow with Dynamic Type; a `sm` button widens its touch area
|
|
221
|
+
* to the 44pt floor.
|
|
217
222
|
*
|
|
218
223
|
* ```tsx
|
|
219
224
|
* <Button variant="primary" size="lg" loading onPress={save}>Save</Button>
|
|
@@ -257,6 +262,11 @@ interface InputProps extends Omit<TextInputProps, 'style' | 'editable'> {
|
|
|
257
262
|
* Single-line text field. Focus and invalid states are drawn on the wrapper so
|
|
258
263
|
* adornments sit inside the border.
|
|
259
264
|
*
|
|
265
|
+
* On iOS the field is a filled, borderless rounded rect like a UIKit search
|
|
266
|
+
* field or grouped-list cell; a stroke appears only for focus and errors. The
|
|
267
|
+
* keyboard follows the color mode and shows the native clear button while
|
|
268
|
+
* editing (unless a `rightElement` occupies that spot).
|
|
269
|
+
*
|
|
260
270
|
* ```tsx
|
|
261
271
|
* <Input size="md" placeholder="Email" invalid={!!error} />
|
|
262
272
|
* ```
|
|
@@ -270,7 +280,7 @@ interface TextareaProps extends Omit<TextInputProps, 'style' | 'editable' | 'mul
|
|
|
270
280
|
rows?: number;
|
|
271
281
|
style?: StyleProp<TextStyle>;
|
|
272
282
|
}
|
|
273
|
-
/** Multi-line text field. Same states as `Input`. */
|
|
283
|
+
/** Multi-line text field. Same states — and the same iOS filled look — as `Input`. */
|
|
274
284
|
declare const Textarea: react.ForwardRefExoticComponent<TextareaProps & react.RefAttributes<TextInput>>;
|
|
275
285
|
|
|
276
286
|
interface LabelProps extends TextProps {
|
|
@@ -321,7 +331,9 @@ interface CheckboxProps {
|
|
|
321
331
|
style?: StyleProp<ViewStyle>;
|
|
322
332
|
}
|
|
323
333
|
/**
|
|
324
|
-
* Checkbox with an optional inline label.
|
|
334
|
+
* Checkbox with an optional inline label. iOS has no square checkbox — the
|
|
335
|
+
* idiom (Reminders, Mail's edit mode) is a circle that fills with a tick — so
|
|
336
|
+
* the box is round there and square elsewhere.
|
|
325
337
|
*
|
|
326
338
|
* ```tsx
|
|
327
339
|
* <Checkbox checked={agreed} onChange={setAgreed}>I agree</Checkbox>
|
|
@@ -339,9 +351,12 @@ interface SwitchProps {
|
|
|
339
351
|
style?: StyleProp<ViewStyle>;
|
|
340
352
|
}
|
|
341
353
|
/**
|
|
342
|
-
* Toggle switch.
|
|
343
|
-
*
|
|
344
|
-
*
|
|
354
|
+
* Toggle switch.
|
|
355
|
+
*
|
|
356
|
+
* On iOS this is the real `UISwitch` (through React Native's `Switch`), tinted
|
|
357
|
+
* with the theme's primary colour — native motion, haptics and VoiceOver
|
|
358
|
+
* semantics for free, as the HIG asks. Elsewhere it is drawn from primitives so
|
|
359
|
+
* it follows the theme's metrics on both platforms.
|
|
345
360
|
*
|
|
346
361
|
* ```tsx
|
|
347
362
|
* <Switch checked={enabled} onChange={setEnabled}>Notifications</Switch>
|
|
@@ -570,7 +585,8 @@ interface CardProps {
|
|
|
570
585
|
}
|
|
571
586
|
/**
|
|
572
587
|
* Surface container. Compose with `CardHeader`, `CardTitle`,
|
|
573
|
-
* `CardDescription`, `CardContent` and `CardFooter`.
|
|
588
|
+
* `CardDescription`, `CardContent` and `CardFooter`. On iOS the `outline`
|
|
589
|
+
* stroke is a hairline, the way grouped cells are separated.
|
|
574
590
|
*
|
|
575
591
|
* ```tsx
|
|
576
592
|
* <Card variant="elevated" onPress={open}>
|
|
@@ -672,7 +688,8 @@ interface ListRowProps {
|
|
|
672
688
|
}
|
|
673
689
|
/**
|
|
674
690
|
* Settings/list row: leading slot, two lines of text, trailing slot. Pressable
|
|
675
|
-
* rows get a chevron and a button role.
|
|
691
|
+
* rows get a chevron and a button role. On iOS the row follows a table cell:
|
|
692
|
+
* 44pt minimum, body-size title, secondary-label subtitle, bold chevron.
|
|
676
693
|
*
|
|
677
694
|
* ```tsx
|
|
678
695
|
* <ListRow title="Notifications" subtitle="Push and email" onPress={open} />
|
|
@@ -720,6 +737,9 @@ interface TabsProps<T extends string = string> {
|
|
|
720
737
|
* because native screens usually swap whole lists rather than mounting all
|
|
721
738
|
* panels at once.
|
|
722
739
|
*
|
|
740
|
+
* On iOS `segmented` is drawn as a `UISegmentedControl`: a 2pt inset track,
|
|
741
|
+
* the selected segment lifted on a white pill with a soft shadow, 13pt labels.
|
|
742
|
+
*
|
|
723
743
|
* ```tsx
|
|
724
744
|
* <Tabs items={tabs} value={tab} onChange={setTab} variant="segmented" />
|
|
725
745
|
* ```
|
|
@@ -877,6 +897,7 @@ interface ModalBodyProps {
|
|
|
877
897
|
style?: StyleProp<ViewStyle>;
|
|
878
898
|
}
|
|
879
899
|
declare function ModalBody({ children, scrollable, style }: ModalBodyProps): react.JSX.Element;
|
|
900
|
+
/** Action row. On iOS a hairline separates it from the body, as in an alert. */
|
|
880
901
|
declare function ModalFooter({ children, style, }: {
|
|
881
902
|
children?: ReactNode;
|
|
882
903
|
style?: StyleProp<ViewStyle>;
|
|
@@ -898,8 +919,9 @@ interface BottomSheetProps {
|
|
|
898
919
|
}
|
|
899
920
|
/**
|
|
900
921
|
* Sheet that slides up from the bottom edge, with a grab handle and
|
|
901
|
-
* drag-to-dismiss.
|
|
902
|
-
*
|
|
922
|
+
* drag-to-dismiss. It arrives on a spring with a fading backdrop, the way a
|
|
923
|
+
* UIKit sheet is presented, and the bottom inset is padded so content clears
|
|
924
|
+
* the home indicator. On iOS the grabber matches the system's 36×5.
|
|
903
925
|
*
|
|
904
926
|
* ```tsx
|
|
905
927
|
* <BottomSheet open={open} onClose={close} title="Pick a room">…</BottomSheet>
|
|
@@ -951,6 +973,11 @@ interface ActionSheetProps {
|
|
|
951
973
|
* package's `DropdownMenu`. Anchored dropdowns don't belong on a phone, so the
|
|
952
974
|
* same intent surfaces as a sheet.
|
|
953
975
|
*
|
|
976
|
+
* On iOS it takes the `UIAlertController` action-sheet form: a floating inset
|
|
977
|
+
* group of centred, tint-coloured rows separated by hairlines, destructive
|
|
978
|
+
* rows in red, and Cancel as its own bold card underneath. Elsewhere it is a
|
|
979
|
+
* list inside `BottomSheet`.
|
|
980
|
+
*
|
|
954
981
|
* ```tsx
|
|
955
982
|
* <ActionSheet open={open} onClose={close} actions={[
|
|
956
983
|
* { label: 'Share ticket', onPress: share },
|
|
@@ -958,7 +985,7 @@ interface ActionSheetProps {
|
|
|
958
985
|
* ]} />
|
|
959
986
|
* ```
|
|
960
987
|
*/
|
|
961
|
-
declare function ActionSheet(
|
|
988
|
+
declare function ActionSheet(props: ActionSheetProps): react.JSX.Element;
|
|
962
989
|
|
|
963
990
|
interface ThemeContextValue {
|
|
964
991
|
/** The active theme for the resolved color mode. */
|
|
@@ -984,11 +1011,18 @@ interface ThemeProviderProps {
|
|
|
984
1011
|
*/
|
|
985
1012
|
colorMode?: ColorMode;
|
|
986
1013
|
onColorModeChange?: (mode: ColorMode) => void;
|
|
1014
|
+
/**
|
|
1015
|
+
* Lay the platform's own metrics over the theme — on iOS the HIG type scale
|
|
1016
|
+
* (Body 17, Footnote 13…) and UIKit radii. Colors are never touched. Defaults
|
|
1017
|
+
* to true; turn off to render the shared tokens verbatim on every platform.
|
|
1018
|
+
*/
|
|
1019
|
+
platformAdaptive?: boolean;
|
|
987
1020
|
children: ReactNode;
|
|
988
1021
|
}
|
|
989
1022
|
/**
|
|
990
1023
|
* Provides the resolved theme to every native component. `'system'` follows the
|
|
991
|
-
* OS appearance through React Native's `useColorScheme()`.
|
|
1024
|
+
* OS appearance through React Native's `useColorScheme()`. On iOS the theme is
|
|
1025
|
+
* rendered through Apple HIG metrics (see `adaptThemeToPlatform`).
|
|
992
1026
|
*
|
|
993
1027
|
* ```tsx
|
|
994
1028
|
* <ThemeProvider theme={sduLightTheme} darkTheme={sduDarkTheme}>
|
|
@@ -996,7 +1030,7 @@ interface ThemeProviderProps {
|
|
|
996
1030
|
* </ThemeProvider>
|
|
997
1031
|
* ```
|
|
998
1032
|
*/
|
|
999
|
-
declare function ThemeProvider({ theme, darkTheme, defaultColorMode, colorMode: colorModeProp, onColorModeChange, children, }: ThemeProviderProps): react.JSX.Element;
|
|
1033
|
+
declare function ThemeProvider({ theme, darkTheme, defaultColorMode, colorMode: colorModeProp, onColorModeChange, platformAdaptive, children, }: ThemeProviderProps): react.JSX.Element;
|
|
1000
1034
|
/** The active theme object (already resolved for the current color mode). */
|
|
1001
1035
|
declare function useTheme(): Theme;
|
|
1002
1036
|
/** Color mode state and controls. */
|
|
@@ -1018,9 +1052,24 @@ interface VariantColors {
|
|
|
1018
1052
|
* Maps a `Variant` onto semantic theme colors. Web does this in CSS via
|
|
1019
1053
|
* `data-variant` selectors; native resolves it here so both platforms answer
|
|
1020
1054
|
* `variant="accent"` with the same roles.
|
|
1055
|
+
*
|
|
1056
|
+
* On iOS the two chrome-less variants follow UIKit's button configurations:
|
|
1057
|
+
* `outline` renders as *tinted* (a soft primary fill, no stroke — iOS has no
|
|
1058
|
+
* stroked buttons) and `ghost` as *plain* (tint-coloured label).
|
|
1021
1059
|
*/
|
|
1022
1060
|
declare function variantColors(variant: Variant, theme: Theme): VariantColors;
|
|
1023
|
-
/**
|
|
1061
|
+
/**
|
|
1062
|
+
* Background and opacity for a button-like pressable in its current state.
|
|
1063
|
+
* iOS dims the whole control (UIKit's highlight); Android swaps to the pressed
|
|
1064
|
+
* colour. Rows and cells are different — they highlight with a background on
|
|
1065
|
+
* both platforms, so they don't use this.
|
|
1066
|
+
*/
|
|
1067
|
+
declare function pressFeedback(pressed: boolean, colors: VariantColors): ViewStyle;
|
|
1068
|
+
/**
|
|
1069
|
+
* Control geometry per size — shared by Button, Input, Select and Textarea.
|
|
1070
|
+
* `height` is a minimum: controls grow with Dynamic Type / font scaling
|
|
1071
|
+
* instead of clipping their label.
|
|
1072
|
+
*/
|
|
1024
1073
|
interface SizeMetrics {
|
|
1025
1074
|
height: number;
|
|
1026
1075
|
paddingHorizontal: number;
|
|
@@ -1030,6 +1079,49 @@ interface SizeMetrics {
|
|
|
1030
1079
|
}
|
|
1031
1080
|
declare function sizeMetrics(size: Size, theme: Theme): SizeMetrics;
|
|
1032
1081
|
|
|
1082
|
+
/**
|
|
1083
|
+
* Read at call time (not module load) so a test can flip the stubbed
|
|
1084
|
+
* `Platform.OS` and exercise both branches of a component.
|
|
1085
|
+
*/
|
|
1086
|
+
declare function isIOS(): boolean;
|
|
1087
|
+
/**
|
|
1088
|
+
* Apple HIG metrics layered over the shared tokens on iOS.
|
|
1089
|
+
*
|
|
1090
|
+
* - Type scale follows the Dynamic Type default sizes: `xs` Footnote 13,
|
|
1091
|
+
* `sm` Subheadline 15, `md` Body 17, `lg` Title 3 20, `xl` Title 2 22,
|
|
1092
|
+
* `2xl` Title 1 28, `3xl` Large Title 34.
|
|
1093
|
+
* - Radii follow UIKit: 10 for controls and grouped cells, 12 for large
|
|
1094
|
+
* buttons and cards, 14 for alerts, 20 for sheets.
|
|
1095
|
+
*
|
|
1096
|
+
* Colors are untouched — brand and dark mode stay the theme's business.
|
|
1097
|
+
*/
|
|
1098
|
+
declare const iosThemeOverride: ThemeOverride;
|
|
1099
|
+
/**
|
|
1100
|
+
* Returns the theme the current platform should render: on iOS the HIG
|
|
1101
|
+
* metrics above are merged in, elsewhere the theme is returned as-is.
|
|
1102
|
+
* `ThemeProvider` applies this automatically (`platformAdaptive`).
|
|
1103
|
+
*/
|
|
1104
|
+
declare function adaptThemeToPlatform(theme: Theme): Theme;
|
|
1105
|
+
|
|
1106
|
+
/**
|
|
1107
|
+
* Turns a CSS font stack from the theme into the single family React Native
|
|
1108
|
+
* wants. The tokens are written as web stacks
|
|
1109
|
+
* (`"'Gilroy', -apple-system, BlinkMacSystemFont, …"`); passing that string
|
|
1110
|
+
* to `fontFamily` on iOS logs "Unrecognized font family" and silently falls
|
|
1111
|
+
* back, so the first usable entry is picked here instead:
|
|
1112
|
+
*
|
|
1113
|
+
* - a system keyword (`-apple-system`, `system-ui`, `sans-serif`, `System`…)
|
|
1114
|
+
* resolves to `undefined` — SF Pro on iOS, Roboto on Android;
|
|
1115
|
+
* - `ui-monospace` / `ui-serif` resolve to the platform's built-in face;
|
|
1116
|
+
* - web-only names (`Segoe UI`, `SF Mono`…) are skipped;
|
|
1117
|
+
* - anything else (`Gilroy`) is returned verbatim for the app to have loaded.
|
|
1118
|
+
*
|
|
1119
|
+
* ```ts
|
|
1120
|
+
* nativeFontFamily(theme.typography.fontFamily.sans) // → undefined on a stock theme
|
|
1121
|
+
* ```
|
|
1122
|
+
*/
|
|
1123
|
+
declare function nativeFontFamily(stack: string | undefined): string | undefined;
|
|
1124
|
+
|
|
1033
1125
|
/** Local-time whole-day helpers. The calendar never leaves local time. */
|
|
1034
1126
|
declare function startOfDay(date: Date): Date;
|
|
1035
1127
|
declare function startOfMonth(date: Date): Date;
|
|
@@ -1044,4 +1136,4 @@ declare function dayKey(date: Date): string;
|
|
|
1044
1136
|
*/
|
|
1045
1137
|
declare function monthGrid(month: Date, weekStartsOn: 0 | 1): Date[];
|
|
1046
1138
|
|
|
1047
|
-
export { Accordion, type AccordionItemData, type AccordionProps, ActionSheet, type ActionSheetAction, type ActionSheetProps, Avatar, type AvatarProps, Badge, type BadgeProps, type BadgeTone, BottomSheet, type BottomSheetProps, Box, type BoxProps, Button, type ButtonProps, Calendar, type CalendarProps, Card, CardContent, CardDescription, CardFooter, CardHeader, type CardProps, CardTitle, Carousel, type CarouselProps, Checkbox, type CheckboxProps, Chip, type ChipProps, Collapse, type CollapseProps, Container, type ContainerProps, Divider, type DividerProps, Drawer, type DrawerProps, EmptyState, type EmptyStateProps, Flex, type FlexOwnProps, type FlexProps, FormField, type FormFieldProps, HStack, Heading, type HeadingLevel, type HeadingProps, Icon, IconButton, type IconButtonProps, type IconProps, Input, type InputProps, Label, type LabelProps, ListRow, type ListRowProps, Modal, ModalBody, type ModalBodyProps, ModalFooter, ModalHeader, type ModalHeaderProps, type ModalProps, ModalTitle, Progress, type ProgressProps, Radio, RadioGroup, type RadioGroupProps, type RadioProps, Screen, type ScreenProps, Section, type SectionProps, Select, type SelectOption, type SelectProps, type SizeMetrics, Skeleton, type SkeletonProps, Spacer, type SpacerProps, Spinner, type SpinnerProps, Stack, type StackProps, type StyleProps, Switch, type SwitchProps, type TabItem, Tabs, type TabsProps, Text, type TextOwnProps, type TextProps, Textarea, type TextareaProps, type ThemeContextValue, ThemeProvider, type ThemeProviderProps, type ToastContextValue, type ToastOptions, type ToastPlacement, ToastProvider, type ToastProviderProps, type ToastTone, Tooltip, type TooltipProps, type VariantColors, addDays, addMonths, dayKey, isSameDay, monthGrid, shadowStyle, sizeMetrics, splitStyleProps, startOfDay, startOfMonth, useColorMode, useColorModeValue, useTheme, useToast, variantColors };
|
|
1139
|
+
export { Accordion, type AccordionItemData, type AccordionProps, ActionSheet, type ActionSheetAction, type ActionSheetProps, Avatar, type AvatarProps, Badge, type BadgeProps, type BadgeTone, BottomSheet, type BottomSheetProps, Box, type BoxProps, Button, type ButtonProps, Calendar, type CalendarProps, Card, CardContent, CardDescription, CardFooter, CardHeader, type CardProps, CardTitle, Carousel, type CarouselProps, Checkbox, type CheckboxProps, Chip, type ChipProps, Collapse, type CollapseProps, Container, type ContainerProps, Divider, type DividerProps, Drawer, type DrawerProps, EmptyState, type EmptyStateProps, Flex, type FlexOwnProps, type FlexProps, FormField, type FormFieldProps, HStack, Heading, type HeadingLevel, type HeadingProps, Icon, IconButton, type IconButtonProps, type IconProps, Input, type InputProps, Label, type LabelProps, ListRow, type ListRowProps, Modal, ModalBody, type ModalBodyProps, ModalFooter, ModalHeader, type ModalHeaderProps, type ModalProps, ModalTitle, Progress, type ProgressProps, Radio, RadioGroup, type RadioGroupProps, type RadioProps, Screen, type ScreenProps, Section, type SectionProps, Select, type SelectOption, type SelectProps, type SizeMetrics, Skeleton, type SkeletonProps, Spacer, type SpacerProps, Spinner, type SpinnerProps, Stack, type StackProps, type StyleProps, Switch, type SwitchProps, type TabItem, Tabs, type TabsProps, Text, type TextOwnProps, type TextProps, Textarea, type TextareaProps, type ThemeContextValue, ThemeProvider, type ThemeProviderProps, type ToastContextValue, type ToastOptions, type ToastPlacement, ToastProvider, type ToastProviderProps, type ToastTone, Tooltip, type TooltipProps, type VariantColors, adaptThemeToPlatform, addDays, addMonths, dayKey, iosThemeOverride, isIOS, isSameDay, monthGrid, nativeFontFamily, pressFeedback, shadowStyle, sizeMetrics, splitStyleProps, startOfDay, startOfMonth, useColorMode, useColorModeValue, useTheme, useToast, variantColors };
|