@korsolutions/ui 0.0.3 → 0.0.5
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 +84 -0
- package/dist/components/index.mjs +288 -0
- package/dist/index-Dafk8ZGv.d.mts +265 -0
- package/dist/index.d.mts +45 -0
- package/dist/index.mjs +11 -0
- package/dist/portal-DoPaAohb.mjs +61 -0
- package/dist/primitives/index.d.mts +2 -0
- package/dist/primitives/index.mjs +4 -0
- package/dist/primitives-BYUlEz2_.mjs +442 -0
- package/dist/themes-BrLbh9h6.mjs +86 -0
- package/package.json +20 -8
- package/src/components/button/button.tsx +24 -0
- package/src/components/button/variants/default.tsx +52 -0
- package/src/components/button/variants/index.ts +5 -0
- package/src/components/card/card.tsx +26 -0
- package/src/components/card/variants/default.tsx +38 -0
- package/src/components/card/variants/index.ts +5 -0
- package/src/components/field/field.tsx +27 -0
- package/src/components/field/variants/default.tsx +29 -0
- package/src/components/field/variants/index.ts +5 -0
- package/src/components/index.ts +5 -0
- package/src/components/input/input.tsx +14 -0
- package/src/components/input/variants/default.tsx +34 -0
- package/src/components/input/variants/index.ts +5 -0
- package/src/components/select/select.tsx +35 -0
- package/src/components/select/variants/default.tsx +81 -0
- package/src/components/select/variants/index.ts +5 -0
- package/src/index.tsx +13 -0
- package/src/primitives/button/button-context.tsx +5 -5
- package/src/primitives/button/button-label.tsx +7 -5
- package/src/primitives/button/button-root.tsx +12 -8
- package/src/primitives/button/button-spinner.tsx +14 -0
- package/src/primitives/button/index.ts +5 -3
- package/src/primitives/button/types.ts +6 -5
- package/src/primitives/card/{card-content.tsx → card-body.tsx} +5 -5
- package/src/primitives/card/card-footer.tsx +1 -1
- package/src/primitives/card/card-header.tsx +1 -1
- package/src/primitives/card/card-root.tsx +1 -1
- package/src/primitives/card/card-title.tsx +1 -1
- package/src/primitives/card/index.ts +4 -4
- package/src/primitives/card/types.ts +2 -2
- package/src/primitives/field/context.ts +5 -19
- package/src/primitives/field/field-description.tsx +17 -0
- package/src/primitives/field/field-error.tsx +17 -0
- package/src/primitives/field/field-label.tsx +7 -3
- package/src/primitives/field/field-root.tsx +13 -59
- package/src/primitives/field/index.ts +9 -6
- package/src/primitives/field/types.ts +8 -7
- package/src/primitives/index.ts +5 -0
- package/src/primitives/input/index.ts +1 -1
- package/src/primitives/input/input.tsx +48 -13
- package/src/primitives/input/types.ts +2 -4
- package/src/primitives/select/context.ts +3 -3
- package/src/primitives/select/index.ts +2 -2
- package/src/primitives/select/select-content.tsx +2 -2
- package/src/primitives/select/select-option.tsx +27 -4
- package/src/primitives/select/select-overlay.tsx +1 -1
- package/src/primitives/select/select-root.tsx +13 -11
- package/src/primitives/select/select-trigger.tsx +3 -2
- package/src/primitives/select/select-value.tsx +4 -1
- package/src/primitives/select/types.ts +3 -1
- package/src/themes/default/colors.ts +45 -0
- package/src/themes/default/index.ts +11 -0
- package/src/themes/index.ts +2 -0
- package/src/themes/provider.tsx +56 -0
- package/src/themes/themes.ts +6 -0
- package/src/themes/types.ts +30 -0
- package/src/utils/hsla-utils.ts +10 -0
- package/src/utils/use-themed-styles.ts +13 -0
- package/tsconfig.json +8 -0
- package/tsdown.config.ts +8 -0
- package/src/index.ts +0 -7
- package/src/primitives/field/field-control.tsx +0 -29
- package/src/primitives/provider.tsx +0 -10
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { useEffect, useState, useSyncExternalStore } from "react";
|
|
2
|
+
import "react-native";
|
|
3
|
+
import { Fragment, jsx } from "react/jsx-runtime";
|
|
4
|
+
|
|
5
|
+
//#region src/primitives/portal/portal.tsx
|
|
6
|
+
const DEFAULT_PORTAL_HOST = "KOR_NATIVE_DEFAULT_HOST_NAME";
|
|
7
|
+
const store = {
|
|
8
|
+
map: (/* @__PURE__ */ new Map()).set(DEFAULT_PORTAL_HOST, /* @__PURE__ */ new Map()),
|
|
9
|
+
listeners: /* @__PURE__ */ new Set()
|
|
10
|
+
};
|
|
11
|
+
function emit() {
|
|
12
|
+
for (const cb of store.listeners) cb();
|
|
13
|
+
}
|
|
14
|
+
function getSnapshot() {
|
|
15
|
+
return store.map;
|
|
16
|
+
}
|
|
17
|
+
function subscribe(cb) {
|
|
18
|
+
store.listeners.add(cb);
|
|
19
|
+
return () => {
|
|
20
|
+
store.listeners.delete(cb);
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function updatePortal(hostName, name, children) {
|
|
24
|
+
const next = new Map(store.map);
|
|
25
|
+
const portal = next.get(hostName) ?? /* @__PURE__ */ new Map();
|
|
26
|
+
portal.set(name, children);
|
|
27
|
+
next.set(hostName, portal);
|
|
28
|
+
store.map = next;
|
|
29
|
+
emit();
|
|
30
|
+
}
|
|
31
|
+
function removePortal(hostName, name) {
|
|
32
|
+
const next = new Map(store.map);
|
|
33
|
+
const portal = next.get(hostName) ?? /* @__PURE__ */ new Map();
|
|
34
|
+
portal.delete(name);
|
|
35
|
+
next.set(hostName, portal);
|
|
36
|
+
store.map = next;
|
|
37
|
+
emit();
|
|
38
|
+
}
|
|
39
|
+
function PortalHost({ name = DEFAULT_PORTAL_HOST }) {
|
|
40
|
+
const portalMap = useSyncExternalStore(subscribe, getSnapshot, getSnapshot).get(name) ?? /* @__PURE__ */ new Map();
|
|
41
|
+
if (portalMap.size === 0) return null;
|
|
42
|
+
return /* @__PURE__ */ jsx(Fragment, { children: Array.from(portalMap.values()) });
|
|
43
|
+
}
|
|
44
|
+
function Portal({ name, hostName = DEFAULT_PORTAL_HOST, children }) {
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
updatePortal(hostName, name, children);
|
|
47
|
+
}, [
|
|
48
|
+
hostName,
|
|
49
|
+
name,
|
|
50
|
+
children
|
|
51
|
+
]);
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
return () => {
|
|
54
|
+
removePortal(hostName, name);
|
|
55
|
+
};
|
|
56
|
+
}, [hostName, name]);
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
//#endregion
|
|
61
|
+
export { PortalHost as n, Portal as t };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { A as FieldErrorProps, C as InputPrimitive, D as FieldPrimitive, E as InputStyles, M as FieldLabelProps, O as FieldPrimitiveRootProps, S as ButtonPrimitiveLabelProps, T as InputPrimitiveProps, _ as SelectTriggerProps, a as CardBodyProps, b as ButtonState, c as SelectPrimitive, d as SelectRootProps, f as SelectStyles, g as SelectValueProps, h as SelectOverlayProps, i as CardFooterProps, j as FieldDescriptionProps, k as FieldStyles, l as SelectPortalProps, m as SelectContentProps, n as CardRootProps, o as CardTitleProps, p as SelectOptionProps, r as CardStyles, s as CardHeaderProps, t as CardPrimitive, u as SelectRootBaseProps, v as ButtonPrimitive, w as InputPrimitiveBaseProps, x as ButtonStyles, y as ButtonPrimitiveRootProps } from "../index-Dafk8ZGv.mjs";
|
|
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 };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import "../portal-DoPaAohb.mjs";
|
|
2
|
+
import { a as FieldPrimitive, i as InputPrimitive, n as SelectPrimitive, r as ButtonPrimitive, t as CardPrimitive } from "../primitives-BYUlEz2_.mjs";
|
|
3
|
+
|
|
4
|
+
export { ButtonPrimitive, CardPrimitive, FieldPrimitive, InputPrimitive, SelectPrimitive };
|
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
import { t as Portal } from "./portal-DoPaAohb.mjs";
|
|
2
|
+
import React, { createContext, useContext, useEffect, useState } from "react";
|
|
3
|
+
import { ActivityIndicator, Pressable, StyleSheet, Text, TextInput, View } from "react-native";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
|
|
6
|
+
//#region src/primitives/field/context.ts
|
|
7
|
+
const FieldContext = createContext(void 0);
|
|
8
|
+
const useField = () => {
|
|
9
|
+
const context = useContext(FieldContext);
|
|
10
|
+
if (!context) throw new Error("useField must be used within a FieldProvider");
|
|
11
|
+
return context;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
15
|
+
//#region src/primitives/field/field-root.tsx
|
|
16
|
+
function FieldRoot(props) {
|
|
17
|
+
const composedStyles = [props.styles?.root, props.style];
|
|
18
|
+
const Component = props.render ?? View;
|
|
19
|
+
return /* @__PURE__ */ jsx(FieldContext.Provider, {
|
|
20
|
+
value: { styles: props.styles },
|
|
21
|
+
children: /* @__PURE__ */ jsx(Component, {
|
|
22
|
+
...props,
|
|
23
|
+
style: composedStyles
|
|
24
|
+
})
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region src/primitives/field/field-label.tsx
|
|
30
|
+
function FieldLabel(props) {
|
|
31
|
+
const field = useField();
|
|
32
|
+
return /* @__PURE__ */ jsx(props.render ?? Text, {
|
|
33
|
+
...props,
|
|
34
|
+
htmlFor: props.htmlFor,
|
|
35
|
+
style: [field.styles?.label, props.style]
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region src/primitives/field/field-description.tsx
|
|
41
|
+
function FieldDescription(props) {
|
|
42
|
+
const field = useField();
|
|
43
|
+
return /* @__PURE__ */ jsx(props.render ?? Text, {
|
|
44
|
+
...props,
|
|
45
|
+
style: [field.styles?.description, props.style]
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
//#endregion
|
|
50
|
+
//#region src/primitives/field/field-error.tsx
|
|
51
|
+
function FieldError(props) {
|
|
52
|
+
const field = useField();
|
|
53
|
+
return /* @__PURE__ */ jsx(props.render ?? Text, {
|
|
54
|
+
...props,
|
|
55
|
+
style: [field.styles?.error, props.style]
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
//#endregion
|
|
60
|
+
//#region src/primitives/field/index.ts
|
|
61
|
+
const FieldPrimitive = {
|
|
62
|
+
Root: FieldRoot,
|
|
63
|
+
Label: FieldLabel,
|
|
64
|
+
Description: FieldDescription,
|
|
65
|
+
Error: FieldError
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
//#endregion
|
|
69
|
+
//#region src/primitives/input/input.tsx
|
|
70
|
+
const calculateState$3 = (props, isFocused) => {
|
|
71
|
+
if (props.isDisabled) return "disabled";
|
|
72
|
+
if (isFocused) return "focused";
|
|
73
|
+
return "default";
|
|
74
|
+
};
|
|
75
|
+
function InputPrimitive(props) {
|
|
76
|
+
const [isFocused, setIsFocused] = useState(false);
|
|
77
|
+
const state = calculateState$3(props, isFocused);
|
|
78
|
+
const composedStyles = [
|
|
79
|
+
props.styles?.default?.style,
|
|
80
|
+
props.styles?.[state]?.style,
|
|
81
|
+
props.style
|
|
82
|
+
];
|
|
83
|
+
const composedProps = {
|
|
84
|
+
...props.styles?.default,
|
|
85
|
+
...props.styles?.[state],
|
|
86
|
+
...props
|
|
87
|
+
};
|
|
88
|
+
return /* @__PURE__ */ jsx(props.render ?? TextInput, {
|
|
89
|
+
...composedProps,
|
|
90
|
+
onChange: void 0,
|
|
91
|
+
onChangeText: props.onChange,
|
|
92
|
+
onFocus: (e) => {
|
|
93
|
+
setIsFocused(true);
|
|
94
|
+
props.onFocus?.(e);
|
|
95
|
+
},
|
|
96
|
+
onBlur: (e) => {
|
|
97
|
+
setIsFocused(false);
|
|
98
|
+
props.onBlur?.(e);
|
|
99
|
+
},
|
|
100
|
+
readOnly: props.isDisabled || props.readOnly,
|
|
101
|
+
style: composedStyles
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
//#endregion
|
|
106
|
+
//#region src/primitives/button/button-context.tsx
|
|
107
|
+
const ButtonPrimitiveContext = createContext(void 0);
|
|
108
|
+
const useButtonPrimitive = () => {
|
|
109
|
+
const context = useContext(ButtonPrimitiveContext);
|
|
110
|
+
if (!context) throw new Error("useButtonPrimitive must be used within a ButtonPrimitiveProvider");
|
|
111
|
+
return context;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
//#endregion
|
|
115
|
+
//#region src/primitives/button/button-root.tsx
|
|
116
|
+
const calculateState$2 = (props) => {
|
|
117
|
+
if (props.isDisabled) return "disabled";
|
|
118
|
+
if (props.isLoading) return "loading";
|
|
119
|
+
return "default";
|
|
120
|
+
};
|
|
121
|
+
function ButtonRoot(props) {
|
|
122
|
+
const state = calculateState$2(props);
|
|
123
|
+
const calculatedStyle = [
|
|
124
|
+
props.styles?.root?.default,
|
|
125
|
+
props.styles?.root?.[state],
|
|
126
|
+
props.style
|
|
127
|
+
];
|
|
128
|
+
const Container = props.render ?? Pressable;
|
|
129
|
+
return /* @__PURE__ */ jsx(ButtonPrimitiveContext.Provider, {
|
|
130
|
+
value: {
|
|
131
|
+
disabled: props.isDisabled,
|
|
132
|
+
state,
|
|
133
|
+
styles: props.styles
|
|
134
|
+
},
|
|
135
|
+
children: /* @__PURE__ */ jsx(Container, {
|
|
136
|
+
...props,
|
|
137
|
+
style: calculatedStyle
|
|
138
|
+
})
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
//#endregion
|
|
143
|
+
//#region src/utils/calculate-styles.ts
|
|
144
|
+
const calculateComposedStyles = (styles = {}, state, component, style) => {
|
|
145
|
+
const result = [];
|
|
146
|
+
const componentStyles = styles?.[component];
|
|
147
|
+
if (componentStyles && "default" in componentStyles && componentStyles["default"]) result.push(componentStyles["default"]);
|
|
148
|
+
if (componentStyles?.[state]) result.push(componentStyles[state]);
|
|
149
|
+
if (style) result.push(style);
|
|
150
|
+
return result;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
//#endregion
|
|
154
|
+
//#region src/primitives/button/button-label.tsx
|
|
155
|
+
function ButtonLabel(props) {
|
|
156
|
+
const button = useButtonPrimitive();
|
|
157
|
+
const calculatedStyle = calculateComposedStyles(button.styles, button.state, "label", props.style);
|
|
158
|
+
return /* @__PURE__ */ jsx(props.render ?? Text, {
|
|
159
|
+
style: calculatedStyle,
|
|
160
|
+
children: props.children
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
//#endregion
|
|
165
|
+
//#region src/primitives/button/button-spinner.tsx
|
|
166
|
+
function ButtonSpinner(props) {
|
|
167
|
+
const button = useButtonPrimitive();
|
|
168
|
+
calculateComposedStyles(button.styles, button.state, "spinner", props.style);
|
|
169
|
+
return /* @__PURE__ */ jsx(ActivityIndicator, {});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
//#endregion
|
|
173
|
+
//#region src/primitives/button/index.ts
|
|
174
|
+
const ButtonPrimitive = {
|
|
175
|
+
Root: ButtonRoot,
|
|
176
|
+
Label: ButtonLabel,
|
|
177
|
+
Spinner: ButtonSpinner
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
//#endregion
|
|
181
|
+
//#region src/primitives/select/context.ts
|
|
182
|
+
const SelectContext = createContext(void 0);
|
|
183
|
+
const useSelect = () => {
|
|
184
|
+
const context = useContext(SelectContext);
|
|
185
|
+
if (!context) throw new Error("useSelect must be used within a SelectProvider");
|
|
186
|
+
return context;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
//#endregion
|
|
190
|
+
//#region src/primitives/select/select-root.tsx
|
|
191
|
+
const calculateState$1 = (props) => {
|
|
192
|
+
if (props.isDisabled) return "disabled";
|
|
193
|
+
return "default";
|
|
194
|
+
};
|
|
195
|
+
function SelectRoot(props) {
|
|
196
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
197
|
+
const [triggerLayout, setTriggerLayout] = useState(null);
|
|
198
|
+
const [options, setOptions] = useState([]);
|
|
199
|
+
const state = calculateState$1(props);
|
|
200
|
+
const composedStyles = calculateComposedStyles(props.styles, state, "root", props.style);
|
|
201
|
+
const Component = props.render ?? View;
|
|
202
|
+
return /* @__PURE__ */ jsx(SelectContext.Provider, {
|
|
203
|
+
value: {
|
|
204
|
+
value: props.value,
|
|
205
|
+
onChange: props.onChange,
|
|
206
|
+
placeholder: props.placeholder,
|
|
207
|
+
isOpen,
|
|
208
|
+
setIsOpen,
|
|
209
|
+
triggerLayout,
|
|
210
|
+
setTriggerLayout,
|
|
211
|
+
options,
|
|
212
|
+
setOptions,
|
|
213
|
+
state,
|
|
214
|
+
isDisabled: props.isDisabled ?? false,
|
|
215
|
+
styles: props.styles ?? null
|
|
216
|
+
},
|
|
217
|
+
children: /* @__PURE__ */ jsx(Component, {
|
|
218
|
+
style: composedStyles,
|
|
219
|
+
children: props.children
|
|
220
|
+
})
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
//#endregion
|
|
225
|
+
//#region src/utils/normalize-layout.ts
|
|
226
|
+
const normalizeLayout = (layout) => {
|
|
227
|
+
if (!layout.y && "top" in layout && typeof layout.top === "number") layout.y = layout.top;
|
|
228
|
+
if (!layout.x && "left" in layout && typeof layout.left === "number") layout.x = layout.left;
|
|
229
|
+
return layout;
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
//#endregion
|
|
233
|
+
//#region src/primitives/select/select-trigger.tsx
|
|
234
|
+
function SelectTrigger(props) {
|
|
235
|
+
const select = useSelect();
|
|
236
|
+
const composedStyles = calculateComposedStyles(select.styles, select.state, "trigger", props.style);
|
|
237
|
+
return /* @__PURE__ */ jsx(props.render ?? Pressable, {
|
|
238
|
+
onPress: () => {
|
|
239
|
+
select.setIsOpen((prev) => !prev);
|
|
240
|
+
},
|
|
241
|
+
onLayout: (e) => {
|
|
242
|
+
const layout = normalizeLayout(e.nativeEvent.layout);
|
|
243
|
+
select.setTriggerLayout(layout);
|
|
244
|
+
},
|
|
245
|
+
disabled: select.isDisabled,
|
|
246
|
+
style: composedStyles,
|
|
247
|
+
children: props.children
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
//#endregion
|
|
252
|
+
//#region src/primitives/select/select-value.tsx
|
|
253
|
+
function SelectValue(props) {
|
|
254
|
+
const select = useSelect();
|
|
255
|
+
const selectedOption = select.options.find((option) => option.value === select.value);
|
|
256
|
+
const selectedOptionLabel = selectedOption?.label;
|
|
257
|
+
const composedStyles = calculateComposedStyles(select.styles, select.state, selectedOptionLabel ? "value" : "placeholder", props.style);
|
|
258
|
+
return /* @__PURE__ */ jsx(props.render ?? Text, {
|
|
259
|
+
style: composedStyles,
|
|
260
|
+
children: selectedOption?.label ?? select.placeholder
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
//#endregion
|
|
265
|
+
//#region src/primitives/select/select-portal.tsx
|
|
266
|
+
function SelectPortal(props) {
|
|
267
|
+
const select = useSelect();
|
|
268
|
+
useEffect(() => {
|
|
269
|
+
return () => {
|
|
270
|
+
select.setOptions([]);
|
|
271
|
+
};
|
|
272
|
+
}, []);
|
|
273
|
+
if (!select.isOpen) return null;
|
|
274
|
+
return /* @__PURE__ */ jsx(Portal, {
|
|
275
|
+
name: "select-portal",
|
|
276
|
+
children: /* @__PURE__ */ jsx(SelectContext.Provider, {
|
|
277
|
+
value: select,
|
|
278
|
+
children: props.children
|
|
279
|
+
})
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
//#endregion
|
|
284
|
+
//#region src/primitives/select/select-overlay.tsx
|
|
285
|
+
function SelectOverlay(props) {
|
|
286
|
+
const select = useSelect();
|
|
287
|
+
const composedStyles = calculateComposedStyles(select.styles, select.state, "overlay", props.style);
|
|
288
|
+
return /* @__PURE__ */ jsx(props.render ?? Pressable, {
|
|
289
|
+
onPress: () => {
|
|
290
|
+
select.setIsOpen(false);
|
|
291
|
+
},
|
|
292
|
+
style: [StyleSheet.absoluteFill, composedStyles],
|
|
293
|
+
children: props.children
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
//#endregion
|
|
298
|
+
//#region src/primitives/select/select-content.tsx
|
|
299
|
+
function SelectContent(props) {
|
|
300
|
+
const select = useSelect();
|
|
301
|
+
const composedStyles = calculateComposedStyles(select.styles, select.state, "content", props.style);
|
|
302
|
+
return /* @__PURE__ */ jsx(props.render ?? View, {
|
|
303
|
+
style: [composedStyles, {
|
|
304
|
+
position: "absolute",
|
|
305
|
+
top: select.triggerLayout?.y + select.triggerLayout?.height,
|
|
306
|
+
left: select.triggerLayout?.x,
|
|
307
|
+
width: select.triggerLayout?.width
|
|
308
|
+
}],
|
|
309
|
+
children: props.children
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
//#endregion
|
|
314
|
+
//#region src/primitives/select/select-option.tsx
|
|
315
|
+
const calculateState = (selectState, hovered, selected) => {
|
|
316
|
+
if (selectState === "disabled") return "disabled";
|
|
317
|
+
if (selected) return "selected";
|
|
318
|
+
if (hovered) return "hovered";
|
|
319
|
+
return "default";
|
|
320
|
+
};
|
|
321
|
+
function SelectOption(props) {
|
|
322
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
323
|
+
const select = useSelect();
|
|
324
|
+
const isSelected = select.value === props.value;
|
|
325
|
+
const optionState = calculateState(select.state, isHovered, isSelected);
|
|
326
|
+
const composedStyles = calculateComposedStyles(select.styles, optionState, "option", props.style);
|
|
327
|
+
useEffect(() => {
|
|
328
|
+
select.setOptions((prev) => {
|
|
329
|
+
if (prev.find((option) => option.value === props.value)) return prev;
|
|
330
|
+
return [...prev, {
|
|
331
|
+
value: props.value,
|
|
332
|
+
label: props.children
|
|
333
|
+
}];
|
|
334
|
+
});
|
|
335
|
+
}, [props.value, props.children]);
|
|
336
|
+
return /* @__PURE__ */ jsx(props.render ?? Text, {
|
|
337
|
+
value: props.value,
|
|
338
|
+
onPress: () => {
|
|
339
|
+
select.onChange?.(props.value);
|
|
340
|
+
select.setIsOpen(false);
|
|
341
|
+
},
|
|
342
|
+
onMouseEnter: () => setIsHovered(true),
|
|
343
|
+
onMouseLeave: () => setIsHovered(false),
|
|
344
|
+
style: composedStyles,
|
|
345
|
+
children: props.children
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
//#endregion
|
|
350
|
+
//#region src/primitives/select/index.ts
|
|
351
|
+
const SelectPrimitive = {
|
|
352
|
+
Root: SelectRoot,
|
|
353
|
+
Trigger: SelectTrigger,
|
|
354
|
+
Value: SelectValue,
|
|
355
|
+
Portal: SelectPortal,
|
|
356
|
+
Overlay: SelectOverlay,
|
|
357
|
+
Content: SelectContent,
|
|
358
|
+
Option: SelectOption
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
//#endregion
|
|
362
|
+
//#region src/primitives/card/context.ts
|
|
363
|
+
const CardContext = createContext(void 0);
|
|
364
|
+
const useCard = () => {
|
|
365
|
+
const context = useContext(CardContext);
|
|
366
|
+
if (!context) throw new Error("useCard must be used within a CardProvider");
|
|
367
|
+
return context;
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
//#endregion
|
|
371
|
+
//#region src/primitives/card/card-root.tsx
|
|
372
|
+
function CardRoot(props) {
|
|
373
|
+
const composedStyle = calculateComposedStyles(props.styles, "default", "root", props.style);
|
|
374
|
+
const Component = props.render ?? View;
|
|
375
|
+
return /* @__PURE__ */ jsx(CardContext.Provider, {
|
|
376
|
+
value: {
|
|
377
|
+
state: "default",
|
|
378
|
+
styles: props.styles
|
|
379
|
+
},
|
|
380
|
+
children: /* @__PURE__ */ jsx(Component, {
|
|
381
|
+
...props,
|
|
382
|
+
style: composedStyle
|
|
383
|
+
})
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
//#endregion
|
|
388
|
+
//#region src/primitives/card/card-header.tsx
|
|
389
|
+
function CardHeader(props) {
|
|
390
|
+
const card = useCard();
|
|
391
|
+
const composedStyle = calculateComposedStyles(card.styles, card.state, "header", props.style);
|
|
392
|
+
return /* @__PURE__ */ jsx(props.render ?? View, {
|
|
393
|
+
...props,
|
|
394
|
+
style: composedStyle
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
//#endregion
|
|
399
|
+
//#region src/primitives/card/card-title.tsx
|
|
400
|
+
function CardTitle(props) {
|
|
401
|
+
const card = useCard();
|
|
402
|
+
const composedStyle = calculateComposedStyles(card.styles, card.state, "title", props.style);
|
|
403
|
+
return /* @__PURE__ */ jsx(props.render ?? Text, {
|
|
404
|
+
...props,
|
|
405
|
+
style: composedStyle
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
//#endregion
|
|
410
|
+
//#region src/primitives/card/card-body.tsx
|
|
411
|
+
function CardBody(props) {
|
|
412
|
+
const card = useCard();
|
|
413
|
+
const composedStyle = calculateComposedStyles(card.styles, card.state, "body", props.style);
|
|
414
|
+
return /* @__PURE__ */ jsx(props.render ?? View, {
|
|
415
|
+
...props,
|
|
416
|
+
style: composedStyle
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
//#endregion
|
|
421
|
+
//#region src/primitives/card/card-footer.tsx
|
|
422
|
+
function CardFooter(props) {
|
|
423
|
+
const card = useCard();
|
|
424
|
+
const composedStyle = calculateComposedStyles(card.styles, card.state, "footer", props.style);
|
|
425
|
+
return /* @__PURE__ */ jsx(props.render ?? View, {
|
|
426
|
+
...props,
|
|
427
|
+
style: composedStyle
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
//#endregion
|
|
432
|
+
//#region src/primitives/card/index.ts
|
|
433
|
+
const CardPrimitive = {
|
|
434
|
+
Root: CardRoot,
|
|
435
|
+
Header: CardHeader,
|
|
436
|
+
Title: CardTitle,
|
|
437
|
+
Body: CardBody,
|
|
438
|
+
Footer: CardFooter
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
//#endregion
|
|
442
|
+
export { FieldPrimitive as a, InputPrimitive as i, SelectPrimitive as n, ButtonPrimitive as r, CardPrimitive as t };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { createContext, useContext, useEffect, useState } from "react";
|
|
2
|
+
import { useColorScheme } from "react-native";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
|
|
5
|
+
//#region src/themes/default/colors.ts
|
|
6
|
+
const lightColors = {
|
|
7
|
+
background: "hsla(223.81, 100%, 100%, 1)",
|
|
8
|
+
foreground: "hsla(223.81, 0%, 3.94%, 1)",
|
|
9
|
+
primary: "hsla(223.81, 0%, 9.05%, 1)",
|
|
10
|
+
primaryForeground: "hsla(223.81, 0%, 98.03%, 1)",
|
|
11
|
+
secondary: "hsla(223.81, 0%, 96.06%, 1)",
|
|
12
|
+
secondaryForeground: "hsla(223.81, 0%, 9.05%, 1)",
|
|
13
|
+
muted: "hsla(223.81, 0%, 96.06%, 1)",
|
|
14
|
+
mutedForeground: "hsla(223.81, 0%, 45.15%, 1)",
|
|
15
|
+
border: "hsla(223.81, 0%, 89.82%, 1)",
|
|
16
|
+
surface: "hsla(223.81, 100%, 100%, 1)",
|
|
17
|
+
danger: "hsla(0, 84.2%, 60.2%, 1)",
|
|
18
|
+
success: "hsla(173, 58%, 39%, 1)",
|
|
19
|
+
warning: "hsla(43, 74%, 66%, 1)",
|
|
20
|
+
info: "hsla(197, 37%, 24%, 1)"
|
|
21
|
+
};
|
|
22
|
+
const darkColors = {
|
|
23
|
+
background: "hsla(223.81, 0%, 3.94%, 1)",
|
|
24
|
+
foreground: "hsla(223.81, 0%, 98.03%, 1)",
|
|
25
|
+
primary: "hsla(223.81, 0%, 89.82%, 1)",
|
|
26
|
+
primaryForeground: "hsla(223.81, 0%, 9.05%, 1)",
|
|
27
|
+
secondary: "hsla(223.81, 0%, 14.94%, 1)",
|
|
28
|
+
secondaryForeground: "hsla(223.81, 0%, 98.03%, 1)",
|
|
29
|
+
muted: "hsla(223.81, 0%, 14.94%, 1)",
|
|
30
|
+
mutedForeground: "hsla(223.81, 0%, 63.02%, 1)",
|
|
31
|
+
border: "hsla(223.81, 0%, 15.51%, 1)",
|
|
32
|
+
surface: "hsla(223.81, 0%, 9.05%, 1)",
|
|
33
|
+
danger: "hsla(0, 62.8%, 30.6%, 1)",
|
|
34
|
+
success: "hsla(160, 60%, 45%, 1)",
|
|
35
|
+
warning: "hsla(30, 80%, 55%, 1)",
|
|
36
|
+
info: "hsla(220, 70%, 50%, 1)"
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region src/themes/default/index.ts
|
|
41
|
+
const defaultThemeAssets = {
|
|
42
|
+
colors: {
|
|
43
|
+
light: lightColors,
|
|
44
|
+
dark: darkColors
|
|
45
|
+
},
|
|
46
|
+
radius: 10,
|
|
47
|
+
fontFamily: "System"
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
//#endregion
|
|
51
|
+
//#region src/themes/themes.ts
|
|
52
|
+
const themes = { default: defaultThemeAssets };
|
|
53
|
+
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region src/themes/provider.tsx
|
|
56
|
+
const ThemeContext = createContext(null);
|
|
57
|
+
const ThemeProvider = (props) => {
|
|
58
|
+
const [themeName, setTheme] = useState("default");
|
|
59
|
+
const systemColorScheme = useColorScheme();
|
|
60
|
+
const [colorScheme, setColorScheme] = useState(systemColorScheme ?? "light");
|
|
61
|
+
const themesAssets = themes[themeName];
|
|
62
|
+
const colors = themesAssets.colors[colorScheme];
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
if (systemColorScheme) setColorScheme(systemColorScheme);
|
|
65
|
+
}, [systemColorScheme]);
|
|
66
|
+
return /* @__PURE__ */ jsx(ThemeContext.Provider, {
|
|
67
|
+
value: {
|
|
68
|
+
themeName,
|
|
69
|
+
setTheme,
|
|
70
|
+
colorScheme,
|
|
71
|
+
setColorScheme,
|
|
72
|
+
colors,
|
|
73
|
+
radius: themesAssets.radius,
|
|
74
|
+
fontFamily: themesAssets.fontFamily
|
|
75
|
+
},
|
|
76
|
+
children: props.children
|
|
77
|
+
});
|
|
78
|
+
};
|
|
79
|
+
const useTheme = () => {
|
|
80
|
+
const context = useContext(ThemeContext);
|
|
81
|
+
if (!context) throw new Error("useTheme must be used within a ThemeProvider");
|
|
82
|
+
return context;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
//#endregion
|
|
86
|
+
export { useTheme as n, ThemeProvider as t };
|
package/package.json
CHANGED
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@korsolutions/ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": ".src/index.ts",
|
|
6
6
|
"types": ".src/index.ts",
|
|
7
7
|
"exports": {
|
|
8
|
-
".":
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"
|
|
8
|
+
".": {
|
|
9
|
+
"default": "./dist/index.mjs",
|
|
10
|
+
"types": "./dist/index.d.mts"
|
|
11
|
+
},
|
|
12
|
+
"./primitives": {
|
|
13
|
+
"default": "./dist/primitives/index.mjs",
|
|
14
|
+
"types": "./dist/primitives/index.d.mts"
|
|
15
|
+
},
|
|
16
|
+
"./components": {
|
|
17
|
+
"default": "./dist/components/index.mjs",
|
|
18
|
+
"types": "./dist/components/index.d.mts"
|
|
19
|
+
}
|
|
13
20
|
},
|
|
14
21
|
"peerDependencies": {
|
|
15
22
|
"react": "*",
|
|
@@ -17,7 +24,8 @@
|
|
|
17
24
|
"react-native-web": "*"
|
|
18
25
|
},
|
|
19
26
|
"devDependencies": {
|
|
20
|
-
"@types/react": "^19.2.3"
|
|
27
|
+
"@types/react": "^19.2.3",
|
|
28
|
+
"tsdown": "0.17.0-beta.4"
|
|
21
29
|
},
|
|
22
30
|
"repository": {
|
|
23
31
|
"type": "git",
|
|
@@ -25,5 +33,9 @@
|
|
|
25
33
|
},
|
|
26
34
|
"bugs": {
|
|
27
35
|
"url": "https://github.com/KorSoftwareSolutions/ui/issues"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsdown",
|
|
39
|
+
"ts-check": "tsc --noEmit"
|
|
28
40
|
}
|
|
29
|
-
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { ButtonPrimitive } from "@/primitives";
|
|
3
|
+
import { ButtonVariants } from "./variants";
|
|
4
|
+
|
|
5
|
+
interface ButtonProps {
|
|
6
|
+
onPress?: () => void;
|
|
7
|
+
children?: string;
|
|
8
|
+
isDisabled?: boolean;
|
|
9
|
+
isLoading?: boolean;
|
|
10
|
+
|
|
11
|
+
variant?: keyof typeof ButtonVariants;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function Button(props: ButtonProps) {
|
|
15
|
+
const useVariantStyles = props.variant ? ButtonVariants[props.variant] : ButtonVariants["default"];
|
|
16
|
+
const variantStyles = useVariantStyles();
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<ButtonPrimitive.Root onPress={props.onPress} isDisabled={props.isDisabled} isLoading={props.isLoading} styles={variantStyles}>
|
|
20
|
+
{props.isLoading && <ButtonPrimitive.Spinner />}
|
|
21
|
+
<ButtonPrimitive.Label>{props.children}</ButtonPrimitive.Label>
|
|
22
|
+
</ButtonPrimitive.Root>
|
|
23
|
+
);
|
|
24
|
+
}
|