@onlynative/components 0.0.0-alpha.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.
@@ -0,0 +1,332 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/switch/index.ts
21
+ var switch_exports = {};
22
+ __export(switch_exports, {
23
+ Switch: () => Switch
24
+ });
25
+ module.exports = __toCommonJS(switch_exports);
26
+
27
+ // src/switch/Switch.tsx
28
+ var import_react = require("react");
29
+ var import_react_native4 = require("react-native");
30
+ var import_core = require("@onlynative/core");
31
+
32
+ // ../utils/dist/chunk-OQRDRRQA.mjs
33
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
34
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
35
+ }) : x)(function(x) {
36
+ if (typeof require !== "undefined") return require.apply(this, arguments);
37
+ throw Error('Dynamic require of "' + x + '" is not supported');
38
+ });
39
+
40
+ // ../utils/dist/index.mjs
41
+ var import_react_native = require("react-native");
42
+ var import_react_native2 = require("react-native");
43
+ function parseHexColor(color) {
44
+ const normalized = color.replace("#", "");
45
+ if (normalized.length !== 6 && normalized.length !== 8) {
46
+ return null;
47
+ }
48
+ const r = Number.parseInt(normalized.slice(0, 2), 16);
49
+ const g = Number.parseInt(normalized.slice(2, 4), 16);
50
+ const b = Number.parseInt(normalized.slice(4, 6), 16);
51
+ if (Number.isNaN(r) || Number.isNaN(g) || Number.isNaN(b)) {
52
+ return null;
53
+ }
54
+ return { r, g, b };
55
+ }
56
+ function clampAlpha(alpha) {
57
+ return Math.max(0, Math.min(1, alpha));
58
+ }
59
+ function alphaColor(color, alpha) {
60
+ const channels = parseHexColor(color);
61
+ const boundedAlpha = clampAlpha(alpha);
62
+ if (!channels) {
63
+ return color;
64
+ }
65
+ return `rgba(${channels.r}, ${channels.g}, ${channels.b}, ${boundedAlpha})`;
66
+ }
67
+ function blendColor(base, overlay, overlayAlpha) {
68
+ const baseChannels = parseHexColor(base);
69
+ const overlayChannels = parseHexColor(overlay);
70
+ const boundedAlpha = clampAlpha(overlayAlpha);
71
+ if (!baseChannels || !overlayChannels) {
72
+ return alphaColor(overlay, boundedAlpha);
73
+ }
74
+ const r = Math.round(
75
+ (1 - boundedAlpha) * baseChannels.r + boundedAlpha * overlayChannels.r
76
+ );
77
+ const g = Math.round(
78
+ (1 - boundedAlpha) * baseChannels.g + boundedAlpha * overlayChannels.g
79
+ );
80
+ const b = Math.round(
81
+ (1 - boundedAlpha) * baseChannels.b + boundedAlpha * overlayChannels.b
82
+ );
83
+ return `rgb(${r}, ${g}, ${b})`;
84
+ }
85
+ var _MCIcons = null;
86
+ var _resolved = false;
87
+ function getMaterialCommunityIcons() {
88
+ if (!_resolved) {
89
+ _resolved = true;
90
+ try {
91
+ const mod = __require("@expo/vector-icons/MaterialCommunityIcons");
92
+ _MCIcons = mod.default || mod;
93
+ } catch {
94
+ _MCIcons = null;
95
+ }
96
+ }
97
+ if (!_MCIcons) {
98
+ throw new Error(
99
+ "@expo/vector-icons is required for icon support. Install it with: npx expo install @expo/vector-icons"
100
+ );
101
+ }
102
+ return _MCIcons;
103
+ }
104
+
105
+ // src/switch/styles.ts
106
+ var import_react_native3 = require("react-native");
107
+ function getColors(theme, selected) {
108
+ const disabledOnSurface12 = alphaColor(theme.colors.onSurface, 0.12);
109
+ const disabledOnSurface38 = alphaColor(theme.colors.onSurface, 0.38);
110
+ if (selected) {
111
+ return {
112
+ trackColor: theme.colors.primary,
113
+ thumbColor: theme.colors.onPrimary,
114
+ iconColor: theme.colors.onPrimaryContainer,
115
+ hoveredTrackColor: blendColor(
116
+ theme.colors.primary,
117
+ theme.colors.onPrimary,
118
+ theme.stateLayer.hoveredOpacity
119
+ ),
120
+ pressedTrackColor: blendColor(
121
+ theme.colors.primary,
122
+ theme.colors.onPrimary,
123
+ theme.stateLayer.pressedOpacity
124
+ ),
125
+ borderColor: "transparent",
126
+ borderWidth: 0,
127
+ disabledTrackColor: disabledOnSurface12,
128
+ disabledThumbColor: theme.colors.surface,
129
+ disabledBorderColor: "transparent",
130
+ disabledBorderWidth: 0
131
+ };
132
+ }
133
+ return {
134
+ trackColor: theme.colors.surfaceContainerHighest,
135
+ thumbColor: theme.colors.outline,
136
+ iconColor: theme.colors.surfaceContainerHighest,
137
+ hoveredTrackColor: blendColor(
138
+ theme.colors.surfaceContainerHighest,
139
+ theme.colors.onSurface,
140
+ theme.stateLayer.hoveredOpacity
141
+ ),
142
+ pressedTrackColor: blendColor(
143
+ theme.colors.surfaceContainerHighest,
144
+ theme.colors.onSurface,
145
+ theme.stateLayer.pressedOpacity
146
+ ),
147
+ borderColor: theme.colors.outline,
148
+ borderWidth: 2,
149
+ disabledTrackColor: disabledOnSurface12,
150
+ disabledThumbColor: disabledOnSurface38,
151
+ disabledBorderColor: disabledOnSurface12,
152
+ disabledBorderWidth: 2
153
+ };
154
+ }
155
+ function applyColorOverrides(theme, colors, containerColor, contentColor) {
156
+ if (!containerColor && !contentColor) return colors;
157
+ const result = { ...colors };
158
+ if (contentColor) {
159
+ result.thumbColor = contentColor;
160
+ result.iconColor = contentColor;
161
+ }
162
+ if (containerColor) {
163
+ const overlay = contentColor != null ? contentColor : colors.thumbColor;
164
+ result.trackColor = containerColor;
165
+ result.borderColor = containerColor;
166
+ result.hoveredTrackColor = blendColor(
167
+ containerColor,
168
+ overlay,
169
+ theme.stateLayer.hoveredOpacity
170
+ );
171
+ result.pressedTrackColor = blendColor(
172
+ containerColor,
173
+ overlay,
174
+ theme.stateLayer.pressedOpacity
175
+ );
176
+ if (contentColor) {
177
+ result.iconColor = containerColor;
178
+ }
179
+ }
180
+ return result;
181
+ }
182
+ function createStyles(theme, selected, hasIcon, containerColor, contentColor) {
183
+ const colors = applyColorOverrides(
184
+ theme,
185
+ getColors(theme, selected),
186
+ containerColor,
187
+ contentColor
188
+ );
189
+ const thumbSize = selected || hasIcon ? 24 : 16;
190
+ const trackWidth = 52;
191
+ const trackHeight = 32;
192
+ const trackPadding = 4;
193
+ const thumbOffset = selected ? trackWidth - trackPadding - thumbSize : trackPadding;
194
+ return import_react_native3.StyleSheet.create({
195
+ track: {
196
+ width: trackWidth,
197
+ height: trackHeight,
198
+ borderRadius: trackHeight / 2,
199
+ backgroundColor: colors.trackColor,
200
+ borderColor: colors.borderColor,
201
+ borderWidth: colors.borderWidth,
202
+ justifyContent: "center",
203
+ cursor: "pointer"
204
+ },
205
+ hoveredTrack: {
206
+ backgroundColor: colors.hoveredTrackColor
207
+ },
208
+ pressedTrack: {
209
+ backgroundColor: colors.pressedTrackColor
210
+ },
211
+ disabledTrack: {
212
+ backgroundColor: colors.disabledTrackColor,
213
+ borderColor: colors.disabledBorderColor,
214
+ borderWidth: colors.disabledBorderWidth,
215
+ cursor: "auto"
216
+ },
217
+ thumb: {
218
+ width: thumbSize,
219
+ height: thumbSize,
220
+ borderRadius: thumbSize / 2,
221
+ backgroundColor: colors.thumbColor,
222
+ marginStart: thumbOffset,
223
+ alignItems: "center",
224
+ justifyContent: "center"
225
+ },
226
+ disabledThumb: {
227
+ backgroundColor: colors.disabledThumbColor
228
+ },
229
+ iconColor: {
230
+ color: colors.iconColor
231
+ },
232
+ disabledIconColor: {
233
+ color: alphaColor(theme.colors.onSurface, 0.38)
234
+ }
235
+ });
236
+ }
237
+
238
+ // src/switch/Switch.tsx
239
+ var import_jsx_runtime = require("react/jsx-runtime");
240
+ function resolveStyle(trackStyle, hoveredTrackStyle, pressedTrackStyle, disabledTrackStyle, disabled, style) {
241
+ if (typeof style === "function") {
242
+ return (state) => [
243
+ trackStyle,
244
+ state.hovered && !state.pressed && !disabled ? hoveredTrackStyle : void 0,
245
+ state.pressed && !disabled ? pressedTrackStyle : void 0,
246
+ disabled ? disabledTrackStyle : void 0,
247
+ style(state)
248
+ ];
249
+ }
250
+ return (state) => [
251
+ trackStyle,
252
+ state.hovered && !state.pressed && !disabled ? hoveredTrackStyle : void 0,
253
+ state.pressed && !disabled ? pressedTrackStyle : void 0,
254
+ disabled ? disabledTrackStyle : void 0,
255
+ style
256
+ ];
257
+ }
258
+ function Switch({
259
+ style,
260
+ value = false,
261
+ onValueChange,
262
+ selectedIcon = "check",
263
+ unselectedIcon,
264
+ containerColor,
265
+ contentColor,
266
+ disabled = false,
267
+ ...props
268
+ }) {
269
+ const isDisabled = Boolean(disabled);
270
+ const isSelected = Boolean(value);
271
+ const hasIcon = isSelected || Boolean(unselectedIcon);
272
+ const theme = (0, import_core.useTheme)();
273
+ const styles = (0, import_react.useMemo)(
274
+ () => createStyles(theme, isSelected, hasIcon, containerColor, contentColor),
275
+ [theme, isSelected, hasIcon, containerColor, contentColor]
276
+ );
277
+ const resolvedIconColor = (0, import_react.useMemo)(() => {
278
+ const base = import_react_native4.StyleSheet.flatten([
279
+ styles.iconColor,
280
+ isDisabled ? styles.disabledIconColor : void 0
281
+ ]);
282
+ return typeof (base == null ? void 0 : base.color) === "string" ? base.color : void 0;
283
+ }, [styles.iconColor, styles.disabledIconColor, isDisabled]);
284
+ const handlePress = () => {
285
+ if (!isDisabled) {
286
+ onValueChange == null ? void 0 : onValueChange(!isSelected);
287
+ }
288
+ };
289
+ const iconName = isSelected ? selectedIcon : unselectedIcon;
290
+ const MaterialCommunityIcons = iconName ? getMaterialCommunityIcons() : null;
291
+ const iconSize = 16;
292
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
293
+ import_react_native4.Pressable,
294
+ {
295
+ ...props,
296
+ accessibilityRole: "switch",
297
+ accessibilityState: {
298
+ disabled: isDisabled,
299
+ checked: isSelected
300
+ },
301
+ hitSlop: import_react_native4.Platform.OS === "web" ? void 0 : 4,
302
+ disabled: isDisabled,
303
+ onPress: handlePress,
304
+ style: resolveStyle(
305
+ styles.track,
306
+ styles.hoveredTrack,
307
+ styles.pressedTrack,
308
+ styles.disabledTrack,
309
+ isDisabled,
310
+ style
311
+ ),
312
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
313
+ import_react_native4.View,
314
+ {
315
+ style: [styles.thumb, isDisabled ? styles.disabledThumb : void 0],
316
+ children: iconName ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
317
+ MaterialCommunityIcons,
318
+ {
319
+ name: iconName,
320
+ size: iconSize,
321
+ color: resolvedIconColor
322
+ }
323
+ ) : null
324
+ }
325
+ )
326
+ }
327
+ );
328
+ }
329
+ // Annotate the CommonJS export names for ESM import in node:
330
+ 0 && (module.exports = {
331
+ Switch
332
+ });
@@ -0,0 +1,52 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import MaterialCommunityIcons from '@expo/vector-icons/MaterialCommunityIcons';
3
+ import { ComponentProps } from 'react';
4
+ import { TextInputProps, StyleProp, TextStyle } from 'react-native';
5
+
6
+ /** Visual container style for the text field. */
7
+ type TextFieldVariant = 'filled' | 'outlined';
8
+ interface TextFieldProps extends Omit<TextInputProps, 'placeholderTextColor' | 'editable'> {
9
+ /** Floating label text. Animates above the input when focused or filled. */
10
+ label?: string;
11
+ /**
12
+ * Container style.
13
+ * @default 'filled'
14
+ */
15
+ variant?: TextFieldVariant;
16
+ /** Helper text displayed below the field. Hidden when `error` or `errorText` is active. */
17
+ supportingText?: string;
18
+ /** Error message. When provided, implicitly sets `error` to `true` and replaces `supportingText`. */
19
+ errorText?: string;
20
+ /**
21
+ * When `true`, renders the field in error state with error colors.
22
+ * @default false
23
+ */
24
+ error?: boolean;
25
+ /**
26
+ * Disables text input and reduces opacity.
27
+ * @default false
28
+ */
29
+ disabled?: boolean;
30
+ /** MaterialCommunityIcons icon name rendered at the start of the field. */
31
+ leadingIcon?: ComponentProps<typeof MaterialCommunityIcons>['name'];
32
+ /** MaterialCommunityIcons icon name rendered at the end of the field. */
33
+ trailingIcon?: ComponentProps<typeof MaterialCommunityIcons>['name'];
34
+ /** Called when the trailing icon is pressed. */
35
+ onTrailingIconPress?: () => void;
36
+ /**
37
+ * Override the container (background) color.
38
+ * Disabled state still uses the standard disabled appearance.
39
+ */
40
+ containerColor?: string;
41
+ /**
42
+ * Override the content (input text and icon) color.
43
+ * Error and disabled states take precedence.
44
+ */
45
+ contentColor?: string;
46
+ /** Additional style applied to the text input element. */
47
+ inputStyle?: StyleProp<TextStyle>;
48
+ }
49
+
50
+ declare function TextField({ value, onChangeText, label, placeholder, variant, supportingText, errorText, error, disabled, leadingIcon, trailingIcon, onTrailingIconPress, multiline, onFocus, onBlur, style, containerColor, contentColor, inputStyle, ...textInputProps }: TextFieldProps): react_jsx_runtime.JSX.Element;
51
+
52
+ export { TextField, type TextFieldProps, type TextFieldVariant };