@korsolutions/ui 0.0.12 → 0.0.14
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/dist/components/index.d.mts +38 -3
- package/dist/components/index.mjs +171 -7
- package/dist/{index-Dafk8ZGv.d.mts → index-_E4x_kNB.d.mts} +95 -6
- package/dist/index.d.mts +3 -3
- package/dist/primitives/index.d.mts +2 -2
- package/dist/primitives/index.mjs +2 -2
- package/dist/{primitives-C2enZ5Ku.mjs → primitives-DQMWXbuX.mjs} +121 -4
- package/package.json +12 -4
- package/src/components/avatar/avatar.tsx +23 -0
- package/src/components/avatar/variants/default.tsx +30 -0
- package/src/components/avatar/variants/index.ts +5 -0
- package/src/components/button/variants/default.tsx +7 -1
- package/src/components/button/variants/index.ts +2 -0
- package/src/components/button/variants/secondary.tsx +58 -0
- package/src/components/empty/empty.tsx +26 -0
- package/src/components/empty/variants/default.tsx +35 -0
- package/src/components/empty/variants/index.ts +5 -0
- package/src/components/index.ts +2 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useScreenSize.ts +41 -0
- package/src/primitives/avatar/avatar-fallback.tsx +16 -0
- package/src/primitives/avatar/avatar-image.tsx +17 -0
- package/src/primitives/avatar/avatar-root.tsx +21 -0
- package/src/primitives/avatar/context.ts +16 -0
- package/src/primitives/avatar/index.ts +14 -0
- package/src/primitives/avatar/types.ts +9 -0
- package/src/primitives/button/button-root.tsx +9 -4
- package/src/primitives/button/types.ts +1 -1
- package/src/primitives/empty/context.ts +16 -0
- package/src/primitives/empty/empty-description.tsx +16 -0
- package/src/primitives/empty/empty-media.tsx +16 -0
- package/src/primitives/empty/empty-root.tsx +21 -0
- package/src/primitives/empty/empty-title.tsx +16 -0
- package/src/primitives/empty/index.ts +17 -0
- package/src/primitives/empty/types.ts +11 -0
- package/src/primitives/index.ts +2 -0
- package/src/utils/hsla-utils.ts +26 -0
- package/tsconfig.json +1 -0
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { B as FieldStyles, C as SelectStyles, F as InputPrimitiveBaseProps, L as InputStyles, M as ButtonStyles, c as EmptyStyles, m as CardStyles, r as AvatarStyles, x as SelectRootBaseProps } from "../index-_E4x_kNB.mjs";
|
|
2
2
|
import React from "react";
|
|
3
|
-
import { TextProps, TextStyle } from "react-native";
|
|
3
|
+
import { ImageSource, TextProps, TextStyle } from "react-native";
|
|
4
4
|
|
|
5
5
|
//#region src/components/button/variants/index.d.ts
|
|
6
6
|
declare const ButtonVariants: {
|
|
7
7
|
default: () => ButtonStyles;
|
|
8
|
+
secondary: () => ButtonStyles;
|
|
8
9
|
};
|
|
9
10
|
//#endregion
|
|
10
11
|
//#region src/components/button/button.d.ts
|
|
@@ -131,4 +132,38 @@ interface LinkProps extends TextProps {
|
|
|
131
132
|
}
|
|
132
133
|
declare function Link(props: LinkProps): React.JSX.Element;
|
|
133
134
|
//#endregion
|
|
134
|
-
|
|
135
|
+
//#region src/components/empty/variants/default.d.ts
|
|
136
|
+
declare function useEmptyVariantDefault(): EmptyStyles;
|
|
137
|
+
//#endregion
|
|
138
|
+
//#region src/components/empty/variants/index.d.ts
|
|
139
|
+
declare const EmptyVariants: {
|
|
140
|
+
default: typeof useEmptyVariantDefault;
|
|
141
|
+
};
|
|
142
|
+
//#endregion
|
|
143
|
+
//#region src/components/empty/empty.d.ts
|
|
144
|
+
interface EmptyProps {
|
|
145
|
+
children?: React.ReactNode;
|
|
146
|
+
media?: React.ReactNode;
|
|
147
|
+
title: string;
|
|
148
|
+
description?: string;
|
|
149
|
+
variant?: keyof typeof EmptyVariants;
|
|
150
|
+
}
|
|
151
|
+
declare function Empty(props: EmptyProps): React.JSX.Element;
|
|
152
|
+
//#endregion
|
|
153
|
+
//#region src/components/avatar/variants/default.d.ts
|
|
154
|
+
declare function useAvatarVariantDefault(): AvatarStyles;
|
|
155
|
+
//#endregion
|
|
156
|
+
//#region src/components/avatar/variants/index.d.ts
|
|
157
|
+
declare const AvatarVariants: {
|
|
158
|
+
default: typeof useAvatarVariantDefault;
|
|
159
|
+
};
|
|
160
|
+
//#endregion
|
|
161
|
+
//#region src/components/avatar/avatar.d.ts
|
|
162
|
+
interface AvatarProps {
|
|
163
|
+
source?: ImageSource;
|
|
164
|
+
fallback: string;
|
|
165
|
+
variant?: keyof typeof AvatarVariants;
|
|
166
|
+
}
|
|
167
|
+
declare function Avatar(props: AvatarProps): React.JSX.Element;
|
|
168
|
+
//#endregion
|
|
169
|
+
export { Avatar, AvatarProps, Button, Card, Empty, EmptyProps, Field, FieldProps, Input, Link, LinkProps, Select, SelectOption, SelectProps, Typography, TypographyProps };
|
|
@@ -1,10 +1,29 @@
|
|
|
1
1
|
import { n as useTheme } from "../themes-DXcjBdO2.mjs";
|
|
2
2
|
import "../portal-DoPaAohb.mjs";
|
|
3
|
-
import { a as
|
|
4
|
-
import React from "react";
|
|
3
|
+
import { a as ButtonPrimitive, i as SelectPrimitive, n as EmptyPrimitive, o as InputPrimitive, r as CardPrimitive, s as FieldPrimitive, t as AvatarPrimitive } from "../primitives-DQMWXbuX.mjs";
|
|
4
|
+
import React, { useState } from "react";
|
|
5
5
|
import { Linking, Text } from "react-native";
|
|
6
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
|
|
8
|
+
//#region src/utils/hsla-utils.ts
|
|
9
|
+
const hslaSetLightness = (hsla, lightness) => {
|
|
10
|
+
const parts = hsla.replace(/^hsla?\(|\s+|\)$/g, "").split(",");
|
|
11
|
+
if (parts.length < 3) throw new Error("Invalid HSLA color format");
|
|
12
|
+
return `hsla(${parseInt(parts[0], 10)}, ${parseInt(parts[1], 10)}%, ${lightness}%, ${parts[3] ? parseFloat(parts[3]) : 1})`;
|
|
13
|
+
};
|
|
14
|
+
const hslaGetLightness = (hsla) => {
|
|
15
|
+
const parts = hsla.replace(/^hsla?\(|\s+|\)$/g, "").split(",");
|
|
16
|
+
if (parts.length < 3) throw new Error("Invalid HSLA color format");
|
|
17
|
+
return parseInt(parts[2], 10);
|
|
18
|
+
};
|
|
19
|
+
const hslaSetRelativeLightness = (hsla, delta) => {
|
|
20
|
+
let newLightness = hslaGetLightness(hsla) + delta;
|
|
21
|
+
if (newLightness > 100) newLightness = 100;
|
|
22
|
+
if (newLightness < 0) newLightness = 0;
|
|
23
|
+
return hslaSetLightness(hsla, newLightness);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
//#endregion
|
|
8
27
|
//#region src/utils/use-themed-styles.ts
|
|
9
28
|
const useThemedStyles = (callback) => {
|
|
10
29
|
const theme = useTheme();
|
|
@@ -24,16 +43,19 @@ const useButtonVariantDefault = () => {
|
|
|
24
43
|
root: {
|
|
25
44
|
default: {
|
|
26
45
|
flexDirection: "row",
|
|
27
|
-
backgroundColor: colors.primary,
|
|
28
46
|
paddingVertical: 12,
|
|
29
47
|
paddingHorizontal: 16,
|
|
30
48
|
borderRadius: radius,
|
|
31
49
|
gap: 8,
|
|
32
50
|
alignItems: "center",
|
|
33
|
-
justifyContent: "center"
|
|
51
|
+
justifyContent: "center",
|
|
52
|
+
backgroundColor: colors.primary,
|
|
53
|
+
borderWidth: 1,
|
|
54
|
+
borderColor: colors.border
|
|
34
55
|
},
|
|
35
56
|
disabled: { opacity: .5 },
|
|
36
|
-
loading: { opacity: .8 }
|
|
57
|
+
loading: { opacity: .8 },
|
|
58
|
+
hovered: { backgroundColor: hslaSetRelativeLightness(colors.primary, -10) }
|
|
37
59
|
},
|
|
38
60
|
label: {
|
|
39
61
|
default: {
|
|
@@ -53,9 +75,51 @@ const useButtonVariantDefault = () => {
|
|
|
53
75
|
}));
|
|
54
76
|
};
|
|
55
77
|
|
|
78
|
+
//#endregion
|
|
79
|
+
//#region src/components/button/variants/secondary.tsx
|
|
80
|
+
const useButtonVariantSecondary = () => {
|
|
81
|
+
return useThemedStyles(({ colors, radius, fontFamily, fontSize }) => ({
|
|
82
|
+
root: {
|
|
83
|
+
default: {
|
|
84
|
+
flexDirection: "row",
|
|
85
|
+
paddingVertical: 12,
|
|
86
|
+
paddingHorizontal: 16,
|
|
87
|
+
borderRadius: radius,
|
|
88
|
+
gap: 8,
|
|
89
|
+
alignItems: "center",
|
|
90
|
+
justifyContent: "center",
|
|
91
|
+
borderWidth: 1,
|
|
92
|
+
borderColor: colors.border,
|
|
93
|
+
backgroundColor: colors.secondary
|
|
94
|
+
},
|
|
95
|
+
disabled: { opacity: .5 },
|
|
96
|
+
loading: { opacity: .8 },
|
|
97
|
+
hovered: { backgroundColor: hslaSetRelativeLightness(colors.secondary, -1) }
|
|
98
|
+
},
|
|
99
|
+
label: {
|
|
100
|
+
default: {
|
|
101
|
+
color: colors.foreground,
|
|
102
|
+
fontSize,
|
|
103
|
+
fontWeight: "bold",
|
|
104
|
+
fontFamily
|
|
105
|
+
},
|
|
106
|
+
disabled: { color: colors.mutedForeground },
|
|
107
|
+
loading: { color: colors.mutedForeground }
|
|
108
|
+
},
|
|
109
|
+
spinner: {
|
|
110
|
+
default: { color: colors.primaryForeground },
|
|
111
|
+
disabled: { color: colors.mutedForeground },
|
|
112
|
+
loading: { color: colors.mutedForeground }
|
|
113
|
+
}
|
|
114
|
+
}));
|
|
115
|
+
};
|
|
116
|
+
|
|
56
117
|
//#endregion
|
|
57
118
|
//#region src/components/button/variants/index.ts
|
|
58
|
-
const ButtonVariants = {
|
|
119
|
+
const ButtonVariants = {
|
|
120
|
+
default: useButtonVariantDefault,
|
|
121
|
+
secondary: useButtonVariantSecondary
|
|
122
|
+
};
|
|
59
123
|
|
|
60
124
|
//#endregion
|
|
61
125
|
//#region src/components/button/button.tsx
|
|
@@ -417,4 +481,104 @@ function Link(props) {
|
|
|
417
481
|
}
|
|
418
482
|
|
|
419
483
|
//#endregion
|
|
420
|
-
|
|
484
|
+
//#region src/components/empty/variants/default.tsx
|
|
485
|
+
function useEmptyVariantDefault() {
|
|
486
|
+
return useThemedStyles(({ colors, fontFamily, fontSize }) => ({
|
|
487
|
+
root: {
|
|
488
|
+
alignItems: "center",
|
|
489
|
+
padding: 32,
|
|
490
|
+
gap: 32
|
|
491
|
+
},
|
|
492
|
+
media: {
|
|
493
|
+
backgroundColor: colors.muted,
|
|
494
|
+
width: 64,
|
|
495
|
+
height: 64,
|
|
496
|
+
borderRadius: "50%",
|
|
497
|
+
alignItems: "center",
|
|
498
|
+
justifyContent: "center"
|
|
499
|
+
},
|
|
500
|
+
title: {
|
|
501
|
+
fontFamily,
|
|
502
|
+
fontSize,
|
|
503
|
+
color: colors.foreground,
|
|
504
|
+
textAlign: "center",
|
|
505
|
+
fontWeight: "600"
|
|
506
|
+
},
|
|
507
|
+
description: {
|
|
508
|
+
fontFamily,
|
|
509
|
+
fontSize: fontSize * .875,
|
|
510
|
+
color: colors.mutedForeground,
|
|
511
|
+
textAlign: "center"
|
|
512
|
+
}
|
|
513
|
+
}));
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
//#endregion
|
|
517
|
+
//#region src/components/empty/variants/index.ts
|
|
518
|
+
const EmptyVariants = { default: useEmptyVariantDefault };
|
|
519
|
+
|
|
520
|
+
//#endregion
|
|
521
|
+
//#region src/components/empty/empty.tsx
|
|
522
|
+
function Empty(props) {
|
|
523
|
+
const useVariantStyles = EmptyVariants[props.variant || "default"];
|
|
524
|
+
const styles = useVariantStyles();
|
|
525
|
+
return /* @__PURE__ */ jsxs(EmptyPrimitive.Root, {
|
|
526
|
+
styles,
|
|
527
|
+
children: [
|
|
528
|
+
!!props.media && /* @__PURE__ */ jsx(EmptyPrimitive.Media, { children: props.media }),
|
|
529
|
+
/* @__PURE__ */ jsx(EmptyPrimitive.Title, { children: props.title }),
|
|
530
|
+
props.description && /* @__PURE__ */ jsx(EmptyPrimitive.Description, { children: props.description }),
|
|
531
|
+
props.children
|
|
532
|
+
]
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
//#endregion
|
|
537
|
+
//#region src/components/avatar/variants/default.tsx
|
|
538
|
+
function useAvatarVariantDefault() {
|
|
539
|
+
return useThemedStyles(({ colors, fontFamily, fontSize }) => ({
|
|
540
|
+
root: {
|
|
541
|
+
backgroundColor: colors.surface,
|
|
542
|
+
borderRadius: "50%",
|
|
543
|
+
overflow: "hidden",
|
|
544
|
+
width: 64,
|
|
545
|
+
height: 64,
|
|
546
|
+
alignItems: "center",
|
|
547
|
+
justifyContent: "center"
|
|
548
|
+
},
|
|
549
|
+
image: {
|
|
550
|
+
width: "100%",
|
|
551
|
+
height: "100%",
|
|
552
|
+
resizeMode: "cover"
|
|
553
|
+
},
|
|
554
|
+
fallback: {
|
|
555
|
+
fontFamily,
|
|
556
|
+
fontSize,
|
|
557
|
+
color: colors.foreground,
|
|
558
|
+
textAlign: "center",
|
|
559
|
+
verticalAlign: "middle"
|
|
560
|
+
}
|
|
561
|
+
}));
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
//#endregion
|
|
565
|
+
//#region src/components/avatar/variants/index.ts
|
|
566
|
+
const AvatarVariants = { default: useAvatarVariantDefault };
|
|
567
|
+
|
|
568
|
+
//#endregion
|
|
569
|
+
//#region src/components/avatar/avatar.tsx
|
|
570
|
+
function Avatar(props) {
|
|
571
|
+
const useVariantStyles = AvatarVariants[props.variant || "default"];
|
|
572
|
+
const styles = useVariantStyles();
|
|
573
|
+
const [imageError, setImageError] = useState(false);
|
|
574
|
+
return /* @__PURE__ */ jsxs(AvatarPrimitive.Root, {
|
|
575
|
+
styles,
|
|
576
|
+
children: [props.source && /* @__PURE__ */ jsx(AvatarPrimitive.Image, {
|
|
577
|
+
source: props.source,
|
|
578
|
+
onError: () => setImageError(true)
|
|
579
|
+
}), (!props.source || imageError) && /* @__PURE__ */ jsx(AvatarPrimitive.Fallback, { children: props.fallback })]
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
//#endregion
|
|
584
|
+
export { Avatar, Button, Card, Empty, Field, Input, Link, Select, Typography };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react0 from "react";
|
|
2
2
|
import React$1 from "react";
|
|
3
|
-
import { StyleProp, TextInputProps, TextProps, TextStyle, ViewStyle } from "react-native";
|
|
3
|
+
import { ImageSource, ImageStyle, StyleProp, TextInputProps, TextProps, TextStyle, ViewStyle } from "react-native";
|
|
4
4
|
|
|
5
5
|
//#region src/primitives/field/field-label.d.ts
|
|
6
6
|
interface FieldLabelProps {
|
|
@@ -65,7 +65,7 @@ interface InputPrimitiveProps extends InputPrimitiveBaseProps {
|
|
|
65
65
|
render?: (props: InputPrimitiveProps) => React.ReactNode;
|
|
66
66
|
styles?: InputStyles;
|
|
67
67
|
}
|
|
68
|
-
declare function InputPrimitive(props: InputPrimitiveProps):
|
|
68
|
+
declare function InputPrimitive(props: InputPrimitiveProps): react0.JSX.Element;
|
|
69
69
|
//#endregion
|
|
70
70
|
//#region src/primitives/button/button-label.d.ts
|
|
71
71
|
interface ButtonPrimitiveLabelProps {
|
|
@@ -76,7 +76,7 @@ interface ButtonPrimitiveLabelProps {
|
|
|
76
76
|
declare function ButtonLabel(props: ButtonPrimitiveLabelProps): React$1.JSX.Element;
|
|
77
77
|
//#endregion
|
|
78
78
|
//#region src/primitives/button/types.d.ts
|
|
79
|
-
type ButtonState = "default" | "disabled" | "loading";
|
|
79
|
+
type ButtonState = "default" | "disabled" | "loading" | "hovered";
|
|
80
80
|
interface ButtonStyles {
|
|
81
81
|
root?: Partial<Record<ButtonState, ButtonPrimitiveRootProps["style"]>>;
|
|
82
82
|
label?: Partial<Record<ButtonState, ButtonPrimitiveLabelProps["style"]>>;
|
|
@@ -152,7 +152,7 @@ interface SelectOptionProps {
|
|
|
152
152
|
render?: (props: SelectOptionProps) => React.ReactElement;
|
|
153
153
|
style?: StyleProp<TextStyle>;
|
|
154
154
|
}
|
|
155
|
-
declare function SelectOption(props: SelectOptionProps):
|
|
155
|
+
declare function SelectOption(props: SelectOptionProps): react0.JSX.Element;
|
|
156
156
|
//#endregion
|
|
157
157
|
//#region src/primitives/select/types.d.ts
|
|
158
158
|
type SelectState = "default" | "disabled";
|
|
@@ -262,4 +262,93 @@ declare const CardPrimitive: {
|
|
|
262
262
|
Footer: typeof CardFooter;
|
|
263
263
|
};
|
|
264
264
|
//#endregion
|
|
265
|
-
|
|
265
|
+
//#region src/primitives/empty/empty-description.d.ts
|
|
266
|
+
interface EmptyDescriptionProps {
|
|
267
|
+
children: string;
|
|
268
|
+
render?: (props: EmptyDescriptionProps) => React$1.ReactNode;
|
|
269
|
+
style?: StyleProp<TextStyle>;
|
|
270
|
+
}
|
|
271
|
+
declare function EmptyDescription(props: EmptyDescriptionProps): React$1.JSX.Element;
|
|
272
|
+
//#endregion
|
|
273
|
+
//#region src/primitives/empty/empty-media.d.ts
|
|
274
|
+
interface EmptyMediaProps {
|
|
275
|
+
children: React$1.ReactNode;
|
|
276
|
+
render?: (props: EmptyMediaProps) => React$1.ReactNode;
|
|
277
|
+
style?: StyleProp<ViewStyle>;
|
|
278
|
+
}
|
|
279
|
+
declare function EmptyMedia(props: EmptyMediaProps): React$1.JSX.Element;
|
|
280
|
+
//#endregion
|
|
281
|
+
//#region src/primitives/empty/empty-title.d.ts
|
|
282
|
+
interface EmptyTitleProps {
|
|
283
|
+
children: string;
|
|
284
|
+
render?: (props: EmptyTitleProps) => React$1.ReactNode;
|
|
285
|
+
style?: StyleProp<TextStyle>;
|
|
286
|
+
}
|
|
287
|
+
declare function EmptyTitle(props: EmptyTitleProps): React$1.JSX.Element;
|
|
288
|
+
//#endregion
|
|
289
|
+
//#region src/primitives/empty/types.d.ts
|
|
290
|
+
type EmptyStyles = {
|
|
291
|
+
root?: EmptyRootProps["style"];
|
|
292
|
+
media?: EmptyMediaProps["style"];
|
|
293
|
+
title?: EmptyTitleProps["style"];
|
|
294
|
+
description?: EmptyDescriptionProps["style"];
|
|
295
|
+
};
|
|
296
|
+
//#endregion
|
|
297
|
+
//#region src/primitives/empty/empty-root.d.ts
|
|
298
|
+
interface EmptyRootProps {
|
|
299
|
+
children: React$1.ReactNode;
|
|
300
|
+
render?: (props: EmptyRootProps) => React$1.ReactNode;
|
|
301
|
+
style?: StyleProp<ViewStyle>;
|
|
302
|
+
styles?: EmptyStyles;
|
|
303
|
+
}
|
|
304
|
+
declare function EmptyRoot(props: EmptyRootProps): React$1.JSX.Element;
|
|
305
|
+
//#endregion
|
|
306
|
+
//#region src/primitives/empty/index.d.ts
|
|
307
|
+
declare const EmptyPrimitive: {
|
|
308
|
+
Root: typeof EmptyRoot;
|
|
309
|
+
Media: typeof EmptyMedia;
|
|
310
|
+
Title: typeof EmptyTitle;
|
|
311
|
+
Description: typeof EmptyDescription;
|
|
312
|
+
};
|
|
313
|
+
//#endregion
|
|
314
|
+
//#region src/primitives/avatar/avatar-fallback.d.ts
|
|
315
|
+
interface AvatarFallbackProps {
|
|
316
|
+
children: string;
|
|
317
|
+
render?: (props: AvatarFallbackProps) => React$1.ReactNode;
|
|
318
|
+
style?: StyleProp<TextStyle>;
|
|
319
|
+
}
|
|
320
|
+
declare function AvatarFallback(props: AvatarFallbackProps): React$1.JSX.Element;
|
|
321
|
+
//#endregion
|
|
322
|
+
//#region src/primitives/avatar/avatar-image.d.ts
|
|
323
|
+
interface AvatarImageProps {
|
|
324
|
+
source: ImageSource;
|
|
325
|
+
onError: () => void;
|
|
326
|
+
render?: (props: AvatarImageProps) => React$1.ReactNode;
|
|
327
|
+
style?: StyleProp<ImageStyle>;
|
|
328
|
+
}
|
|
329
|
+
declare function AvatarImage(props: AvatarImageProps): React$1.JSX.Element;
|
|
330
|
+
//#endregion
|
|
331
|
+
//#region src/primitives/avatar/types.d.ts
|
|
332
|
+
type AvatarStyles = {
|
|
333
|
+
root?: AvatarRootProps["style"];
|
|
334
|
+
image?: AvatarImageProps["style"];
|
|
335
|
+
fallback?: AvatarFallbackProps["style"];
|
|
336
|
+
};
|
|
337
|
+
//#endregion
|
|
338
|
+
//#region src/primitives/avatar/avatar-root.d.ts
|
|
339
|
+
interface AvatarRootProps {
|
|
340
|
+
children: React$1.ReactNode;
|
|
341
|
+
render?: (props: AvatarRootProps) => React$1.ReactNode;
|
|
342
|
+
style?: StyleProp<ViewStyle>;
|
|
343
|
+
styles?: AvatarStyles;
|
|
344
|
+
}
|
|
345
|
+
declare function AvatarRoot(props: AvatarRootProps): React$1.JSX.Element;
|
|
346
|
+
//#endregion
|
|
347
|
+
//#region src/primitives/avatar/index.d.ts
|
|
348
|
+
declare const AvatarPrimitive: {
|
|
349
|
+
Root: typeof AvatarRoot;
|
|
350
|
+
Image: typeof AvatarImage;
|
|
351
|
+
Fallback: typeof AvatarFallback;
|
|
352
|
+
};
|
|
353
|
+
//#endregion
|
|
354
|
+
export { ButtonPrimitiveRootProps as A, FieldStyles as B, SelectStyles as C, SelectValueProps as D, SelectOverlayProps as E, InputPrimitiveBaseProps as F, FieldDescriptionProps as H, InputPrimitiveProps as I, InputStyles as L, ButtonStyles as M, ButtonPrimitiveLabelProps as N, SelectTriggerProps as O, InputPrimitive as P, FieldPrimitive as R, SelectRootProps as S, SelectContentProps as T, FieldLabelProps as U, FieldErrorProps as V, CardTitleProps as _, AvatarFallbackProps as a, SelectPortalProps as b, EmptyStyles as c, EmptyDescriptionProps as d, CardPrimitive as f, CardBodyProps as g, CardFooterProps as h, AvatarImageProps as i, ButtonState as j, ButtonPrimitive as k, EmptyTitleProps as l, CardStyles as m, AvatarRootProps as n, EmptyPrimitive as o, CardRootProps as p, AvatarStyles as r, EmptyRootProps as s, AvatarPrimitive as t, EmptyMediaProps as u, CardHeaderProps as v, SelectOptionProps as w, SelectRootBaseProps as x, SelectPrimitive as y, FieldPrimitiveRootProps as z };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react2 from "react";
|
|
2
2
|
|
|
3
3
|
//#region src/themes/types.d.ts
|
|
4
4
|
type ThemeName = "default";
|
|
@@ -37,7 +37,7 @@ interface ThemeContext {
|
|
|
37
37
|
setTheme: (themeName: ThemeName) => void;
|
|
38
38
|
themeName: ThemeName;
|
|
39
39
|
}
|
|
40
|
-
declare const ThemeContext:
|
|
40
|
+
declare const ThemeContext: react2.Context<ThemeContext | null>;
|
|
41
41
|
declare const useTheme: () => ThemeContext;
|
|
42
42
|
//#endregion
|
|
43
43
|
//#region src/index.d.ts
|
|
@@ -45,6 +45,6 @@ declare const UniversalUIProvider: ({
|
|
|
45
45
|
children
|
|
46
46
|
}: {
|
|
47
47
|
children: React.ReactNode;
|
|
48
|
-
}) =>
|
|
48
|
+
}) => react2.JSX.Element;
|
|
49
49
|
//#endregion
|
|
50
50
|
export { UniversalUIProvider, useTheme };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as
|
|
2
|
-
export { ButtonPrimitive, ButtonPrimitiveLabelProps, ButtonPrimitiveRootProps, ButtonState, ButtonStyles, CardBodyProps, CardFooterProps, CardHeaderProps, CardPrimitive, CardRootProps, CardStyles, CardTitleProps, FieldDescriptionProps, FieldErrorProps, FieldLabelProps, FieldPrimitive, FieldPrimitiveRootProps, FieldStyles, InputPrimitive, InputPrimitiveBaseProps, InputPrimitiveProps, InputStyles, SelectContentProps, SelectOptionProps, SelectOverlayProps, SelectPortalProps, SelectPrimitive, SelectRootBaseProps, SelectRootProps, SelectStyles, SelectTriggerProps, SelectValueProps };
|
|
1
|
+
import { A as ButtonPrimitiveRootProps, B as FieldStyles, C as SelectStyles, D as SelectValueProps, E as SelectOverlayProps, F as InputPrimitiveBaseProps, H as FieldDescriptionProps, I as InputPrimitiveProps, L as InputStyles, M as ButtonStyles, N as ButtonPrimitiveLabelProps, O as SelectTriggerProps, P as InputPrimitive, R as FieldPrimitive, S as SelectRootProps, T as SelectContentProps, U as FieldLabelProps, V as FieldErrorProps, _ as CardTitleProps, a as AvatarFallbackProps, b as SelectPortalProps, c as EmptyStyles, d as EmptyDescriptionProps, f as CardPrimitive, g as CardBodyProps, h as CardFooterProps, i as AvatarImageProps, j as ButtonState, k as ButtonPrimitive, l as EmptyTitleProps, m as CardStyles, n as AvatarRootProps, o as EmptyPrimitive, p as CardRootProps, r as AvatarStyles, s as EmptyRootProps, t as AvatarPrimitive, u as EmptyMediaProps, v as CardHeaderProps, w as SelectOptionProps, x as SelectRootBaseProps, y as SelectPrimitive, z as FieldPrimitiveRootProps } from "../index-_E4x_kNB.mjs";
|
|
2
|
+
export { AvatarFallbackProps, AvatarImageProps, AvatarPrimitive, AvatarRootProps, AvatarStyles, ButtonPrimitive, ButtonPrimitiveLabelProps, ButtonPrimitiveRootProps, ButtonState, ButtonStyles, CardBodyProps, CardFooterProps, CardHeaderProps, CardPrimitive, CardRootProps, CardStyles, CardTitleProps, EmptyDescriptionProps, EmptyMediaProps, EmptyPrimitive, EmptyRootProps, EmptyStyles, EmptyTitleProps, FieldDescriptionProps, FieldErrorProps, FieldLabelProps, FieldPrimitive, FieldPrimitiveRootProps, FieldStyles, InputPrimitive, InputPrimitiveBaseProps, InputPrimitiveProps, InputStyles, SelectContentProps, SelectOptionProps, SelectOverlayProps, SelectPortalProps, SelectPrimitive, SelectRootBaseProps, SelectRootProps, SelectStyles, SelectTriggerProps, SelectValueProps };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import "../portal-DoPaAohb.mjs";
|
|
2
|
-
import { a as
|
|
2
|
+
import { a as ButtonPrimitive, i as SelectPrimitive, n as EmptyPrimitive, o as InputPrimitive, r as CardPrimitive, s as FieldPrimitive, t as AvatarPrimitive } from "../primitives-DQMWXbuX.mjs";
|
|
3
3
|
|
|
4
|
-
export { ButtonPrimitive, CardPrimitive, FieldPrimitive, InputPrimitive, SelectPrimitive };
|
|
4
|
+
export { AvatarPrimitive, ButtonPrimitive, CardPrimitive, EmptyPrimitive, FieldPrimitive, InputPrimitive, SelectPrimitive };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as Portal } from "./portal-DoPaAohb.mjs";
|
|
2
2
|
import React, { createContext, useContext, useEffect, useState } from "react";
|
|
3
|
-
import { ActivityIndicator, Pressable, StyleSheet, Text, TextInput, View } from "react-native";
|
|
3
|
+
import { ActivityIndicator, Image, Pressable, StyleSheet, Text, TextInput, View } from "react-native";
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
5
|
|
|
6
6
|
//#region src/primitives/field/context.ts
|
|
@@ -113,13 +113,15 @@ const useButtonPrimitive = () => {
|
|
|
113
113
|
|
|
114
114
|
//#endregion
|
|
115
115
|
//#region src/primitives/button/button-root.tsx
|
|
116
|
-
const calculateState$2 = (props) => {
|
|
116
|
+
const calculateState$2 = (props, isHovered) => {
|
|
117
117
|
if (props.isDisabled) return "disabled";
|
|
118
118
|
if (props.isLoading) return "loading";
|
|
119
|
+
if (isHovered) return "hovered";
|
|
119
120
|
return "default";
|
|
120
121
|
};
|
|
121
122
|
function ButtonRoot(props) {
|
|
122
|
-
const
|
|
123
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
124
|
+
const state = calculateState$2(props, isHovered);
|
|
123
125
|
const calculatedStyle = [
|
|
124
126
|
props.styles?.root?.default,
|
|
125
127
|
props.styles?.root?.[state],
|
|
@@ -134,6 +136,8 @@ function ButtonRoot(props) {
|
|
|
134
136
|
},
|
|
135
137
|
children: /* @__PURE__ */ jsx(Container, {
|
|
136
138
|
...props,
|
|
139
|
+
onHoverIn: () => setIsHovered(true),
|
|
140
|
+
onHoverOut: () => setIsHovered(false),
|
|
137
141
|
style: calculatedStyle
|
|
138
142
|
})
|
|
139
143
|
});
|
|
@@ -438,4 +442,117 @@ const CardPrimitive = {
|
|
|
438
442
|
};
|
|
439
443
|
|
|
440
444
|
//#endregion
|
|
441
|
-
|
|
445
|
+
//#region src/primitives/empty/context.ts
|
|
446
|
+
const EmptyContext = createContext({});
|
|
447
|
+
const useEmpty = () => {
|
|
448
|
+
const context = useContext(EmptyContext);
|
|
449
|
+
if (!context) throw new Error("useEmptyContext must be used within a EmptyProvider");
|
|
450
|
+
return context;
|
|
451
|
+
};
|
|
452
|
+
|
|
453
|
+
//#endregion
|
|
454
|
+
//#region src/primitives/empty/empty-root.tsx
|
|
455
|
+
function EmptyRoot(props) {
|
|
456
|
+
const composedStyles = [props.styles?.root, props.style];
|
|
457
|
+
const Component = props.render ?? View;
|
|
458
|
+
return /* @__PURE__ */ jsx(EmptyContext.Provider, {
|
|
459
|
+
value: { styles: props.styles },
|
|
460
|
+
children: /* @__PURE__ */ jsx(Component, {
|
|
461
|
+
...props,
|
|
462
|
+
style: composedStyles
|
|
463
|
+
})
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
//#endregion
|
|
468
|
+
//#region src/primitives/empty/empty-media.tsx
|
|
469
|
+
function EmptyMedia(props) {
|
|
470
|
+
const composedStyles = [useEmpty().styles?.media, props.style];
|
|
471
|
+
return /* @__PURE__ */ jsx(props.render ?? View, {
|
|
472
|
+
...props,
|
|
473
|
+
style: composedStyles
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
//#endregion
|
|
478
|
+
//#region src/primitives/empty/empty-title.tsx
|
|
479
|
+
function EmptyTitle(props) {
|
|
480
|
+
const composedStyles = [useEmpty().styles?.title, props.style];
|
|
481
|
+
return /* @__PURE__ */ jsx(props.render ?? Text, {
|
|
482
|
+
...props,
|
|
483
|
+
style: composedStyles
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
//#endregion
|
|
488
|
+
//#region src/primitives/empty/empty-description.tsx
|
|
489
|
+
function EmptyDescription(props) {
|
|
490
|
+
const composedStyles = [useEmpty().styles?.description, props.style];
|
|
491
|
+
return /* @__PURE__ */ jsx(props.render ?? Text, {
|
|
492
|
+
...props,
|
|
493
|
+
style: composedStyles
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
//#endregion
|
|
498
|
+
//#region src/primitives/empty/index.ts
|
|
499
|
+
const EmptyPrimitive = {
|
|
500
|
+
Root: EmptyRoot,
|
|
501
|
+
Media: EmptyMedia,
|
|
502
|
+
Title: EmptyTitle,
|
|
503
|
+
Description: EmptyDescription
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
//#endregion
|
|
507
|
+
//#region src/primitives/avatar/context.ts
|
|
508
|
+
const AvatarContext = createContext(void 0);
|
|
509
|
+
const useAvatar = () => {
|
|
510
|
+
const context = useContext(AvatarContext);
|
|
511
|
+
if (!context) throw new Error("useAvatarContext must be used within a AvatarProvider");
|
|
512
|
+
return context;
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
//#endregion
|
|
516
|
+
//#region src/primitives/avatar/avatar-root.tsx
|
|
517
|
+
function AvatarRoot(props) {
|
|
518
|
+
const composedStyles = [props.styles?.root, props.style];
|
|
519
|
+
const Component = props.render ?? View;
|
|
520
|
+
return /* @__PURE__ */ jsx(AvatarContext.Provider, {
|
|
521
|
+
value: { styles: props.styles },
|
|
522
|
+
children: /* @__PURE__ */ jsx(Component, {
|
|
523
|
+
...props,
|
|
524
|
+
style: composedStyles
|
|
525
|
+
})
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
//#endregion
|
|
530
|
+
//#region src/primitives/avatar/avatar-fallback.tsx
|
|
531
|
+
function AvatarFallback(props) {
|
|
532
|
+
const composedStyles = [useAvatar().styles?.fallback, props.style];
|
|
533
|
+
return /* @__PURE__ */ jsx(props.render ?? View, {
|
|
534
|
+
...props,
|
|
535
|
+
style: composedStyles
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
//#endregion
|
|
540
|
+
//#region src/primitives/avatar/avatar-image.tsx
|
|
541
|
+
function AvatarImage(props) {
|
|
542
|
+
const composedStyles = [useAvatar().styles?.image, props.style];
|
|
543
|
+
return /* @__PURE__ */ jsx(props.render ?? Image, {
|
|
544
|
+
...props,
|
|
545
|
+
style: composedStyles
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
//#endregion
|
|
550
|
+
//#region src/primitives/avatar/index.ts
|
|
551
|
+
const AvatarPrimitive = {
|
|
552
|
+
Root: AvatarRoot,
|
|
553
|
+
Image: AvatarImage,
|
|
554
|
+
Fallback: AvatarFallback
|
|
555
|
+
};
|
|
556
|
+
|
|
557
|
+
//#endregion
|
|
558
|
+
export { ButtonPrimitive as a, SelectPrimitive as i, EmptyPrimitive as n, InputPrimitive as o, CardPrimitive as r, FieldPrimitive as s, AvatarPrimitive as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@korsolutions/ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/index.mjs",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -8,15 +8,23 @@
|
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
10
|
"default": "./dist/index.mjs",
|
|
11
|
-
"types": "./dist/index.d.mts"
|
|
11
|
+
"types": "./dist/index.d.mts",
|
|
12
|
+
"dev-source": "./src/index.ts"
|
|
12
13
|
},
|
|
13
14
|
"./primitives": {
|
|
14
15
|
"default": "./dist/primitives/index.mjs",
|
|
15
|
-
"types": "./dist/primitives/index.d.mts"
|
|
16
|
+
"types": "./dist/primitives/index.d.mts",
|
|
17
|
+
"dev-source": "./src/primitives/index.ts"
|
|
16
18
|
},
|
|
17
19
|
"./components": {
|
|
18
20
|
"default": "./dist/components/index.mjs",
|
|
19
|
-
"types": "./dist/components/index.d.mts"
|
|
21
|
+
"types": "./dist/components/index.d.mts",
|
|
22
|
+
"dev-source": "./src/components/index.ts"
|
|
23
|
+
},
|
|
24
|
+
"./hooks": {
|
|
25
|
+
"default": "./dist/hooks/index.mjs",
|
|
26
|
+
"types": "./dist/hooks/index.d.mts",
|
|
27
|
+
"dev-source": "./src/hooks/index.ts"
|
|
20
28
|
}
|
|
21
29
|
},
|
|
22
30
|
"scripts": {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { AvatarPrimitive } from "@/primitives";
|
|
2
|
+
import React, { useState } from "react";
|
|
3
|
+
import { ImageSource } from "react-native";
|
|
4
|
+
import { AvatarVariants } from "./variants";
|
|
5
|
+
|
|
6
|
+
export interface AvatarProps {
|
|
7
|
+
source?: ImageSource;
|
|
8
|
+
fallback: string;
|
|
9
|
+
|
|
10
|
+
variant?: keyof typeof AvatarVariants;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function Avatar(props: AvatarProps) {
|
|
14
|
+
const useVariantStyles = AvatarVariants[props.variant || "default"];
|
|
15
|
+
const styles = useVariantStyles();
|
|
16
|
+
const [imageError, setImageError] = useState(false);
|
|
17
|
+
return (
|
|
18
|
+
<AvatarPrimitive.Root styles={styles}>
|
|
19
|
+
{props.source && <AvatarPrimitive.Image source={props.source} onError={() => setImageError(true)} />}
|
|
20
|
+
{(!props.source || imageError) && <AvatarPrimitive.Fallback>{props.fallback}</AvatarPrimitive.Fallback>}
|
|
21
|
+
</AvatarPrimitive.Root>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { AvatarStyles } from "@/primitives";
|
|
2
|
+
import { useThemedStyles } from "@/utils/use-themed-styles";
|
|
3
|
+
|
|
4
|
+
export function useAvatarVariantDefault(): AvatarStyles {
|
|
5
|
+
return useThemedStyles(
|
|
6
|
+
({ colors, fontFamily, fontSize }): AvatarStyles => ({
|
|
7
|
+
root: {
|
|
8
|
+
backgroundColor: colors.surface,
|
|
9
|
+
borderRadius: "50%",
|
|
10
|
+
overflow: "hidden",
|
|
11
|
+
width: 64,
|
|
12
|
+
height: 64,
|
|
13
|
+
alignItems: "center",
|
|
14
|
+
justifyContent: "center",
|
|
15
|
+
},
|
|
16
|
+
image: {
|
|
17
|
+
width: "100%",
|
|
18
|
+
height: "100%",
|
|
19
|
+
resizeMode: "cover",
|
|
20
|
+
},
|
|
21
|
+
fallback: {
|
|
22
|
+
fontFamily,
|
|
23
|
+
fontSize,
|
|
24
|
+
color: colors.foreground,
|
|
25
|
+
textAlign: "center",
|
|
26
|
+
verticalAlign: "middle",
|
|
27
|
+
},
|
|
28
|
+
})
|
|
29
|
+
);
|
|
30
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ButtonStyles } from "@/primitives";
|
|
2
|
+
import { hslaSetRelativeLightness } from "@/utils/hsla-utils";
|
|
2
3
|
import { useThemedStyles } from "@/utils/use-themed-styles";
|
|
3
4
|
|
|
4
5
|
export const useButtonVariantDefault = (): ButtonStyles => {
|
|
@@ -7,13 +8,15 @@ export const useButtonVariantDefault = (): ButtonStyles => {
|
|
|
7
8
|
root: {
|
|
8
9
|
default: {
|
|
9
10
|
flexDirection: "row",
|
|
10
|
-
backgroundColor: colors.primary,
|
|
11
11
|
paddingVertical: 12,
|
|
12
12
|
paddingHorizontal: 16,
|
|
13
13
|
borderRadius: radius,
|
|
14
14
|
gap: 8,
|
|
15
15
|
alignItems: "center",
|
|
16
16
|
justifyContent: "center",
|
|
17
|
+
backgroundColor: colors.primary,
|
|
18
|
+
borderWidth: 1,
|
|
19
|
+
borderColor: colors.border,
|
|
17
20
|
},
|
|
18
21
|
disabled: {
|
|
19
22
|
opacity: 0.5,
|
|
@@ -21,6 +24,9 @@ export const useButtonVariantDefault = (): ButtonStyles => {
|
|
|
21
24
|
loading: {
|
|
22
25
|
opacity: 0.8,
|
|
23
26
|
},
|
|
27
|
+
hovered: {
|
|
28
|
+
backgroundColor: hslaSetRelativeLightness(colors.primary, -10),
|
|
29
|
+
},
|
|
24
30
|
},
|
|
25
31
|
label: {
|
|
26
32
|
default: {
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { ButtonStyles } from "@/primitives";
|
|
2
|
+
import { hslaSetRelativeLightness } from "@/utils/hsla-utils";
|
|
3
|
+
import { useThemedStyles } from "@/utils/use-themed-styles";
|
|
4
|
+
|
|
5
|
+
export const useButtonVariantSecondary = (): ButtonStyles => {
|
|
6
|
+
return useThemedStyles(
|
|
7
|
+
({ colors, radius, fontFamily, fontSize }): ButtonStyles => ({
|
|
8
|
+
root: {
|
|
9
|
+
default: {
|
|
10
|
+
flexDirection: "row",
|
|
11
|
+
paddingVertical: 12,
|
|
12
|
+
paddingHorizontal: 16,
|
|
13
|
+
borderRadius: radius,
|
|
14
|
+
gap: 8,
|
|
15
|
+
alignItems: "center",
|
|
16
|
+
justifyContent: "center",
|
|
17
|
+
borderWidth: 1,
|
|
18
|
+
borderColor: colors.border,
|
|
19
|
+
backgroundColor: colors.secondary,
|
|
20
|
+
},
|
|
21
|
+
disabled: {
|
|
22
|
+
opacity: 0.5,
|
|
23
|
+
},
|
|
24
|
+
loading: {
|
|
25
|
+
opacity: 0.8,
|
|
26
|
+
},
|
|
27
|
+
hovered: {
|
|
28
|
+
backgroundColor: hslaSetRelativeLightness(colors.secondary, -1),
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
label: {
|
|
32
|
+
default: {
|
|
33
|
+
color: colors.foreground,
|
|
34
|
+
fontSize,
|
|
35
|
+
fontWeight: "bold",
|
|
36
|
+
fontFamily,
|
|
37
|
+
},
|
|
38
|
+
disabled: {
|
|
39
|
+
color: colors.mutedForeground,
|
|
40
|
+
},
|
|
41
|
+
loading: {
|
|
42
|
+
color: colors.mutedForeground,
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
spinner: {
|
|
46
|
+
default: {
|
|
47
|
+
color: colors.primaryForeground,
|
|
48
|
+
},
|
|
49
|
+
disabled: {
|
|
50
|
+
color: colors.mutedForeground,
|
|
51
|
+
},
|
|
52
|
+
loading: {
|
|
53
|
+
color: colors.mutedForeground,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
})
|
|
57
|
+
);
|
|
58
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { EmptyPrimitive } from "@/primitives";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { EmptyVariants } from "./variants";
|
|
4
|
+
|
|
5
|
+
export interface EmptyProps {
|
|
6
|
+
children?: React.ReactNode;
|
|
7
|
+
media?: React.ReactNode;
|
|
8
|
+
title: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
|
|
11
|
+
variant?: keyof typeof EmptyVariants;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function Empty(props: EmptyProps) {
|
|
15
|
+
const useVariantStyles = EmptyVariants[props.variant || "default"];
|
|
16
|
+
const styles = useVariantStyles();
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<EmptyPrimitive.Root styles={styles}>
|
|
20
|
+
{!!props.media && <EmptyPrimitive.Media>{props.media}</EmptyPrimitive.Media>}
|
|
21
|
+
<EmptyPrimitive.Title>{props.title}</EmptyPrimitive.Title>
|
|
22
|
+
{props.description && <EmptyPrimitive.Description>{props.description}</EmptyPrimitive.Description>}
|
|
23
|
+
{props.children}
|
|
24
|
+
</EmptyPrimitive.Root>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { EmptyStyles } from "@/primitives";
|
|
2
|
+
import { useThemedStyles } from "@/utils/use-themed-styles";
|
|
3
|
+
|
|
4
|
+
export function useEmptyVariantDefault(): EmptyStyles {
|
|
5
|
+
return useThemedStyles(
|
|
6
|
+
({ colors, fontFamily, fontSize }): EmptyStyles => ({
|
|
7
|
+
root: {
|
|
8
|
+
alignItems: "center",
|
|
9
|
+
padding: 32,
|
|
10
|
+
gap: 32,
|
|
11
|
+
},
|
|
12
|
+
media: {
|
|
13
|
+
backgroundColor: colors.muted,
|
|
14
|
+
width: 64,
|
|
15
|
+
height: 64,
|
|
16
|
+
borderRadius: "50%",
|
|
17
|
+
alignItems: "center",
|
|
18
|
+
justifyContent: "center",
|
|
19
|
+
},
|
|
20
|
+
title: {
|
|
21
|
+
fontFamily: fontFamily,
|
|
22
|
+
fontSize: fontSize,
|
|
23
|
+
color: colors.foreground,
|
|
24
|
+
textAlign: "center",
|
|
25
|
+
fontWeight: "600",
|
|
26
|
+
},
|
|
27
|
+
description: {
|
|
28
|
+
fontFamily: fontFamily,
|
|
29
|
+
fontSize: fontSize * 0.875,
|
|
30
|
+
color: colors.mutedForeground,
|
|
31
|
+
textAlign: "center",
|
|
32
|
+
},
|
|
33
|
+
})
|
|
34
|
+
);
|
|
35
|
+
}
|
package/src/components/index.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./useScreenSize";
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { useWindowDimensions } from "react-native";
|
|
2
|
+
|
|
3
|
+
export type ScreenSize = "mobile" | "tablet" | "desktop";
|
|
4
|
+
|
|
5
|
+
interface Response {
|
|
6
|
+
readonly size: ScreenSize;
|
|
7
|
+
readonly width: number;
|
|
8
|
+
readonly height: number;
|
|
9
|
+
readonly isMobile: boolean;
|
|
10
|
+
readonly isTablet: boolean;
|
|
11
|
+
readonly isDesktop: boolean;
|
|
12
|
+
|
|
13
|
+
select<T>(specifics: ({ [size in ScreenSize]?: T } & { default: T }) | { [platform in ScreenSize]: T }): T;
|
|
14
|
+
select<T>(specifics: { [size in ScreenSize]?: T }): T | undefined;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function useScreenSize(): Response {
|
|
18
|
+
const windowDimensions = useWindowDimensions();
|
|
19
|
+
|
|
20
|
+
const size: ScreenSize = windowDimensions.width < 768 ? "mobile" : windowDimensions.width < 1024 ? "tablet" : "desktop";
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
size,
|
|
24
|
+
width: windowDimensions.width,
|
|
25
|
+
height: windowDimensions.height,
|
|
26
|
+
isMobile: size === "mobile",
|
|
27
|
+
isTablet: size === "tablet",
|
|
28
|
+
isDesktop: size === "desktop",
|
|
29
|
+
select: (specifics) => {
|
|
30
|
+
const { mobile, tablet, desktop } = specifics;
|
|
31
|
+
|
|
32
|
+
if (size === "mobile" && mobile !== undefined) return mobile;
|
|
33
|
+
if (size === "tablet" && tablet !== undefined) return tablet;
|
|
34
|
+
if (size === "desktop" && desktop !== undefined) return desktop;
|
|
35
|
+
if (!("default" in specifics)) {
|
|
36
|
+
throw new Error(`Utils.$screenSize.select: No value specified for current screen size: ${size}`);
|
|
37
|
+
}
|
|
38
|
+
return specifics.default;
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { StyleProp, TextStyle, View } from "react-native";
|
|
3
|
+
import { useAvatar } from "./context";
|
|
4
|
+
|
|
5
|
+
export interface AvatarFallbackProps {
|
|
6
|
+
children: string;
|
|
7
|
+
render?: (props: AvatarFallbackProps) => React.ReactNode;
|
|
8
|
+
style?: StyleProp<TextStyle>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function AvatarFallback(props: AvatarFallbackProps) {
|
|
12
|
+
const avatar = useAvatar();
|
|
13
|
+
const composedStyles = [avatar.styles?.fallback, props.style];
|
|
14
|
+
const Component = props.render ?? View;
|
|
15
|
+
return <Component {...props} style={composedStyles} />;
|
|
16
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Image, ImageSource, ImageStyle, StyleProp } from "react-native";
|
|
3
|
+
import { useAvatar } from "./context";
|
|
4
|
+
|
|
5
|
+
export interface AvatarImageProps {
|
|
6
|
+
source: ImageSource;
|
|
7
|
+
onError: () => void;
|
|
8
|
+
render?: (props: AvatarImageProps) => React.ReactNode;
|
|
9
|
+
style?: StyleProp<ImageStyle>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function AvatarImage(props: AvatarImageProps) {
|
|
13
|
+
const avatar = useAvatar();
|
|
14
|
+
const composedStyles = [avatar.styles?.image, props.style];
|
|
15
|
+
const Component = props.render ?? Image;
|
|
16
|
+
return <Component {...props} style={composedStyles} />;
|
|
17
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { StyleProp, View, ViewStyle } from "react-native";
|
|
3
|
+
import { AvatarContext } from "./context";
|
|
4
|
+
import { AvatarStyles } from "./types";
|
|
5
|
+
|
|
6
|
+
export interface AvatarRootProps {
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
render?: (props: AvatarRootProps) => React.ReactNode;
|
|
9
|
+
style?: StyleProp<ViewStyle>;
|
|
10
|
+
styles?: AvatarStyles;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function AvatarRoot(props: AvatarRootProps) {
|
|
14
|
+
const composedStyles = [props.styles?.root, props.style];
|
|
15
|
+
const Component = props.render ?? View;
|
|
16
|
+
return (
|
|
17
|
+
<AvatarContext.Provider value={{ styles: props.styles }}>
|
|
18
|
+
<Component {...props} style={composedStyles} />
|
|
19
|
+
</AvatarContext.Provider>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { createContext, useContext } from "react";
|
|
2
|
+
import { AvatarStyles } from "./types";
|
|
3
|
+
|
|
4
|
+
export interface AvatarContext {
|
|
5
|
+
styles?: AvatarStyles;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const AvatarContext = createContext<AvatarContext | undefined>(undefined);
|
|
9
|
+
|
|
10
|
+
export const useAvatar = () => {
|
|
11
|
+
const context = useContext(AvatarContext);
|
|
12
|
+
if (!context) {
|
|
13
|
+
throw new Error("useAvatarContext must be used within a AvatarProvider");
|
|
14
|
+
}
|
|
15
|
+
return context;
|
|
16
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { AvatarRoot } from "./avatar-root";
|
|
2
|
+
import { AvatarFallback } from "./avatar-fallback";
|
|
3
|
+
import { AvatarImage } from "./avatar-image";
|
|
4
|
+
|
|
5
|
+
export const AvatarPrimitive = {
|
|
6
|
+
Root: AvatarRoot,
|
|
7
|
+
Image: AvatarImage,
|
|
8
|
+
Fallback: AvatarFallback,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type { AvatarRootProps } from "./avatar-root";
|
|
12
|
+
export type { AvatarFallbackProps } from "./avatar-fallback";
|
|
13
|
+
export type { AvatarImageProps } from "./avatar-image";
|
|
14
|
+
export type { AvatarStyles } from "./types";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { AvatarFallbackProps } from "./avatar-fallback";
|
|
2
|
+
import { AvatarImageProps } from "./avatar-image";
|
|
3
|
+
import { AvatarRootProps } from "./avatar-root";
|
|
4
|
+
|
|
5
|
+
export type AvatarStyles = {
|
|
6
|
+
root?: AvatarRootProps["style"];
|
|
7
|
+
image?: AvatarImageProps["style"];
|
|
8
|
+
fallback?: AvatarFallbackProps["style"];
|
|
9
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { useState } from "react";
|
|
2
2
|
import { Pressable, StyleProp, ViewStyle } from "react-native";
|
|
3
3
|
import { ButtonStyles, ButtonState } from "./types";
|
|
4
4
|
import { ButtonPrimitiveContext } from "./button-context";
|
|
@@ -17,25 +17,30 @@ export interface ButtonPrimitiveRootProps {
|
|
|
17
17
|
render?: (props: this) => React.ReactElement;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
const calculateState = (props: ButtonPrimitiveRootProps): ButtonState => {
|
|
20
|
+
const calculateState = (props: ButtonPrimitiveRootProps, isHovered: boolean): ButtonState => {
|
|
21
21
|
if (props.isDisabled) {
|
|
22
22
|
return "disabled";
|
|
23
23
|
}
|
|
24
24
|
if (props.isLoading) {
|
|
25
25
|
return "loading";
|
|
26
26
|
}
|
|
27
|
+
if (isHovered) {
|
|
28
|
+
return "hovered";
|
|
29
|
+
}
|
|
27
30
|
return "default";
|
|
28
31
|
};
|
|
29
32
|
|
|
30
33
|
export function ButtonRoot(props: ButtonPrimitiveRootProps) {
|
|
31
|
-
const
|
|
34
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
35
|
+
|
|
36
|
+
const state = calculateState(props, isHovered);
|
|
32
37
|
|
|
33
38
|
const calculatedStyle = [props.styles?.root?.default, props.styles?.root?.[state], props.style];
|
|
34
39
|
|
|
35
40
|
const Container = props.render ?? Pressable;
|
|
36
41
|
return (
|
|
37
42
|
<ButtonPrimitiveContext.Provider value={{ disabled: props.isDisabled, state, styles: props.styles }}>
|
|
38
|
-
<Container {...props} style={calculatedStyle} />
|
|
43
|
+
<Container {...props} onHoverIn={() => setIsHovered(true)} onHoverOut={() => setIsHovered(false)} style={calculatedStyle} />
|
|
39
44
|
</ButtonPrimitiveContext.Provider>
|
|
40
45
|
);
|
|
41
46
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ButtonPrimitiveRootProps } from "./button-root";
|
|
2
2
|
import { ButtonPrimitiveLabelProps } from "./button-label";
|
|
3
3
|
|
|
4
|
-
export type ButtonState = "default" | "disabled" | "loading";
|
|
4
|
+
export type ButtonState = "default" | "disabled" | "loading" | "hovered";
|
|
5
5
|
|
|
6
6
|
export interface ButtonStyles {
|
|
7
7
|
root?: Partial<Record<ButtonState, ButtonPrimitiveRootProps["style"]>>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { createContext, useContext } from "react";
|
|
2
|
+
import { EmptyStyles } from "./types";
|
|
3
|
+
|
|
4
|
+
export interface EmptyContext {
|
|
5
|
+
styles?: EmptyStyles;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const EmptyContext = createContext<EmptyContext>({});
|
|
9
|
+
|
|
10
|
+
export const useEmpty = () => {
|
|
11
|
+
const context = useContext(EmptyContext);
|
|
12
|
+
if (!context) {
|
|
13
|
+
throw new Error("useEmptyContext must be used within a EmptyProvider");
|
|
14
|
+
}
|
|
15
|
+
return context;
|
|
16
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { StyleProp, Text, TextStyle } from "react-native";
|
|
3
|
+
import { useEmpty } from "./context";
|
|
4
|
+
|
|
5
|
+
export interface EmptyDescriptionProps {
|
|
6
|
+
children: string;
|
|
7
|
+
render?: (props: EmptyDescriptionProps) => React.ReactNode;
|
|
8
|
+
style?: StyleProp<TextStyle>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function EmptyDescription(props: EmptyDescriptionProps) {
|
|
12
|
+
const empty = useEmpty();
|
|
13
|
+
const composedStyles = [empty.styles?.description, props.style];
|
|
14
|
+
const Component = props.render ?? Text;
|
|
15
|
+
return <Component {...props} style={composedStyles} />;
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { StyleProp, View, ViewStyle } from "react-native";
|
|
3
|
+
import { useEmpty } from "./context";
|
|
4
|
+
|
|
5
|
+
export interface EmptyMediaProps {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
render?: (props: EmptyMediaProps) => React.ReactNode;
|
|
8
|
+
style?: StyleProp<ViewStyle>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function EmptyMedia(props: EmptyMediaProps) {
|
|
12
|
+
const empty = useEmpty();
|
|
13
|
+
const composedStyles = [empty.styles?.media, props.style];
|
|
14
|
+
const Component = props.render ?? View;
|
|
15
|
+
return <Component {...props} style={composedStyles} />;
|
|
16
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { StyleProp, View, ViewStyle } from "react-native";
|
|
3
|
+
import { EmptyContext } from "./context";
|
|
4
|
+
import { EmptyStyles } from "./types";
|
|
5
|
+
|
|
6
|
+
export interface EmptyRootProps {
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
render?: (props: EmptyRootProps) => React.ReactNode;
|
|
9
|
+
style?: StyleProp<ViewStyle>;
|
|
10
|
+
styles?: EmptyStyles;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function EmptyRoot(props: EmptyRootProps) {
|
|
14
|
+
const composedStyles = [props.styles?.root, props.style];
|
|
15
|
+
const Component = props.render ?? View;
|
|
16
|
+
return (
|
|
17
|
+
<EmptyContext.Provider value={{ styles: props.styles }}>
|
|
18
|
+
<Component {...props} style={composedStyles} />
|
|
19
|
+
</EmptyContext.Provider>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useEmpty } from "./context";
|
|
3
|
+
import { StyleProp, Text, TextStyle } from "react-native";
|
|
4
|
+
|
|
5
|
+
export interface EmptyTitleProps {
|
|
6
|
+
children: string;
|
|
7
|
+
render?: (props: EmptyTitleProps) => React.ReactNode;
|
|
8
|
+
style?: StyleProp<TextStyle>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function EmptyTitle(props: EmptyTitleProps) {
|
|
12
|
+
const empty = useEmpty();
|
|
13
|
+
const composedStyles = [empty.styles?.title, props.style];
|
|
14
|
+
const Component = props.render ?? Text;
|
|
15
|
+
return <Component {...props} style={composedStyles} />;
|
|
16
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { EmptyRoot } from "./empty-root";
|
|
2
|
+
import { EmptyMedia } from "./empty-media";
|
|
3
|
+
import { EmptyTitle } from "./empty-title";
|
|
4
|
+
import { EmptyDescription } from "./empty-description";
|
|
5
|
+
|
|
6
|
+
export const EmptyPrimitive = {
|
|
7
|
+
Root: EmptyRoot,
|
|
8
|
+
Media: EmptyMedia,
|
|
9
|
+
Title: EmptyTitle,
|
|
10
|
+
Description: EmptyDescription,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type { EmptyRootProps } from "./empty-root";
|
|
14
|
+
export type { EmptyMediaProps } from "./empty-media";
|
|
15
|
+
export type { EmptyTitleProps } from "./empty-title";
|
|
16
|
+
export type { EmptyDescriptionProps } from "./empty-description";
|
|
17
|
+
export type { EmptyStyles } from "./types";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { EmptyDescriptionProps } from "./empty-description";
|
|
2
|
+
import { EmptyMediaProps } from "./empty-media";
|
|
3
|
+
import { EmptyRootProps } from "./empty-root";
|
|
4
|
+
import { EmptyTitleProps } from "./empty-title";
|
|
5
|
+
|
|
6
|
+
export type EmptyStyles = {
|
|
7
|
+
root?: EmptyRootProps["style"];
|
|
8
|
+
media?: EmptyMediaProps["style"];
|
|
9
|
+
title?: EmptyTitleProps["style"];
|
|
10
|
+
description?: EmptyDescriptionProps["style"];
|
|
11
|
+
};
|
package/src/primitives/index.ts
CHANGED
package/src/utils/hsla-utils.ts
CHANGED
|
@@ -8,3 +8,29 @@ export const hslaSetAlpha = (hsla: string, alpha: number): string => {
|
|
|
8
8
|
const l = parseInt(parts[2], 10);
|
|
9
9
|
return `hsla(${h}, ${s}%, ${l}%, ${alpha})`;
|
|
10
10
|
};
|
|
11
|
+
|
|
12
|
+
export const hslaSetLightness = (hsla: string, lightness: number): string => {
|
|
13
|
+
const parts = hsla.replace(/^hsla?\(|\s+|\)$/g, "").split(",");
|
|
14
|
+
if (parts.length < 3) {
|
|
15
|
+
throw new Error("Invalid HSLA color format");
|
|
16
|
+
}
|
|
17
|
+
const h = parseInt(parts[0], 10);
|
|
18
|
+
const s = parseInt(parts[1], 10);
|
|
19
|
+
return `hsla(${h}, ${s}%, ${lightness}%, ${parts[3] ? parseFloat(parts[3]) : 1})`;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const hslaGetLightness = (hsla: string): number => {
|
|
23
|
+
const parts = hsla.replace(/^hsla?\(|\s+|\)$/g, "").split(",");
|
|
24
|
+
if (parts.length < 3) {
|
|
25
|
+
throw new Error("Invalid HSLA color format");
|
|
26
|
+
}
|
|
27
|
+
return parseInt(parts[2], 10);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const hslaSetRelativeLightness = (hsla: string, delta: number): string => {
|
|
31
|
+
const currentLightness = hslaGetLightness(hsla);
|
|
32
|
+
let newLightness = currentLightness + delta;
|
|
33
|
+
if (newLightness > 100) newLightness = 100;
|
|
34
|
+
if (newLightness < 0) newLightness = 0;
|
|
35
|
+
return hslaSetLightness(hsla, newLightness);
|
|
36
|
+
};
|