@object-ui/mobile 2.0.0 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,132 @@
1
+ # @object-ui/mobile
2
+
3
+ Mobile optimization for Object UI — responsive hooks, gesture support, touch targets, and PWA utilities.
4
+
5
+ ## Features
6
+
7
+ - 📱 **Responsive Hooks** - `useBreakpoint` and `useResponsive` for adaptive layouts
8
+ - 👆 **Gesture Support** - `useGesture` and `useSpecGesture` for swipe, pinch, and long-press detection
9
+ - 🔄 **Pull to Refresh** - Native pull-to-refresh behavior with `usePullToRefresh`
10
+ - 🎯 **Touch Targets** - `useTouchTarget` for accessible minimum-size touch areas
11
+ - 📐 **Responsive Containers** - `ResponsiveContainer` for breakpoint-aware rendering
12
+ - 🏗️ **MobileProvider** - Context provider for mobile-aware applications
13
+ - 📲 **PWA Support** - Manifest generation and service worker registration
14
+ - ⚙️ **Configurable Breakpoints** - Customizable breakpoint definitions
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install @object-ui/mobile
20
+ ```
21
+
22
+ **Peer Dependencies:**
23
+ - `react` ^18.0.0 || ^19.0.0
24
+ - `react-dom` ^18.0.0 || ^19.0.0
25
+
26
+ ## Quick Start
27
+
28
+ ```tsx
29
+ import { MobileProvider, useBreakpoint, useGesture } from '@object-ui/mobile';
30
+
31
+ function App() {
32
+ return (
33
+ <MobileProvider>
34
+ <ResponsiveApp />
35
+ </MobileProvider>
36
+ );
37
+ }
38
+
39
+ function ResponsiveApp() {
40
+ const { isMobile, isTablet, isDesktop } = useBreakpoint();
41
+
42
+ return (
43
+ <div>
44
+ {isMobile && <MobileNav />}
45
+ {isDesktop && <DesktopSidebar />}
46
+ <MainContent />
47
+ </div>
48
+ );
49
+ }
50
+ ```
51
+
52
+ ## API
53
+
54
+ ### MobileProvider
55
+
56
+ Wraps your application with mobile context:
57
+
58
+ ```tsx
59
+ <MobileProvider>
60
+ <App />
61
+ </MobileProvider>
62
+ ```
63
+
64
+ ### useBreakpoint
65
+
66
+ Hook for detecting the current breakpoint:
67
+
68
+ ```tsx
69
+ const { isMobile, isTablet, isDesktop, current } = useBreakpoint();
70
+ ```
71
+
72
+ ### useResponsive
73
+
74
+ Hook for responsive values based on screen size:
75
+
76
+ ```tsx
77
+ const columns = useResponsive({ mobile: 1, tablet: 2, desktop: 4 });
78
+ ```
79
+
80
+ ### useGesture / useSpecGesture
81
+
82
+ Hooks for gesture detection on touch devices:
83
+
84
+ ```tsx
85
+ const gestureRef = useGesture({
86
+ onSwipeLeft: () => navigateNext(),
87
+ onSwipeRight: () => navigateBack(),
88
+ onPinch: (scale) => handleZoom(scale),
89
+ });
90
+
91
+ return <div ref={gestureRef}>Swipeable content</div>;
92
+ ```
93
+
94
+ ### usePullToRefresh
95
+
96
+ Hook for pull-to-refresh behavior:
97
+
98
+ ```tsx
99
+ const { isRefreshing } = usePullToRefresh({
100
+ onRefresh: async () => await fetchData(),
101
+ });
102
+ ```
103
+
104
+ ### useTouchTarget
105
+
106
+ Hook for ensuring minimum touch target sizes:
107
+
108
+ ```tsx
109
+ const { targetProps } = useTouchTarget({ minSize: 44 });
110
+ return <button {...targetProps}>Tap me</button>;
111
+ ```
112
+
113
+ ### ResponsiveContainer
114
+
115
+ Renders children based on breakpoint:
116
+
117
+ ```tsx
118
+ <ResponsiveContainer mobile={<MobileView />} desktop={<DesktopView />} />
119
+ ```
120
+
121
+ ### PWA Utilities
122
+
123
+ ```tsx
124
+ import { generatePWAManifest, registerServiceWorker } from '@object-ui/mobile';
125
+
126
+ const manifest = generatePWAManifest({ name: 'My App', themeColor: '#000' });
127
+ registerServiceWorker({ cacheStrategy: 'network-first' });
128
+ ```
129
+
130
+ ## License
131
+
132
+ MIT
package/dist/index.d.ts CHANGED
@@ -19,12 +19,15 @@
19
19
  */
20
20
  export { useBreakpoint, type BreakpointState } from './useBreakpoint';
21
21
  export { useResponsive } from './useResponsive';
22
+ export { useResponsiveConfig, type SpecResponsiveConfig, type ResolvedResponsiveState } from './useResponsiveConfig';
22
23
  export { useGesture, type UseGestureOptions } from './useGesture';
24
+ export { useSpecGesture, type UseSpecGestureOptions } from './useSpecGesture';
25
+ export { useTouchTarget, type UseTouchTargetOptions, type TouchTargetResult } from './useTouchTarget';
23
26
  export { usePullToRefresh, type PullToRefreshOptions } from './usePullToRefresh';
24
27
  export { MobileProvider, type MobileProviderProps } from './MobileProvider';
25
28
  export { ResponsiveContainer, type ResponsiveContainerProps } from './ResponsiveContainer';
26
29
  export { generatePWAManifest } from './pwa';
27
30
  export { registerServiceWorker, type ServiceWorkerConfig } from './serviceWorker';
28
31
  export { BREAKPOINTS, resolveResponsiveValue } from './breakpoints';
29
- export type { BreakpointName, ResponsiveValue, ResponsiveConfig, MobileOverrides, PWAConfig, PWAIcon, CacheStrategy, OfflineConfig, OfflineRoute, GestureType, GestureConfig, GestureContext, MobileComponentConfig, } from '@object-ui/types';
32
+ export type { BreakpointName, ResponsiveValue, ResponsiveConfig, MobileOverrides, PWAConfig, PWAIcon, CacheStrategy, OfflineConfig, OfflineRoute, GestureType, GestureConfig, GestureContext, MobileComponentConfig, SpecGestureConfig, SwipeGestureConfig, PinchGestureConfig, LongPressGestureConfig, TouchInteraction, TouchTargetConfig, } from '@object-ui/types';
30
33
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,KAAK,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAC3F,OAAO,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,qBAAqB,EAAE,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAClF,OAAO,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAGpE,YAAY,EACV,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,SAAS,EACT,OAAO,EACP,aAAa,EACb,aAAa,EACb,YAAY,EACZ,WAAW,EACX,aAAa,EACb,cAAc,EACd,qBAAqB,GACtB,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,KAAK,oBAAoB,EAAE,KAAK,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACrH,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACtG,OAAO,EAAE,gBAAgB,EAAE,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,KAAK,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAC3F,OAAO,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,qBAAqB,EAAE,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAClF,OAAO,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAGpE,YAAY,EACV,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,SAAS,EACT,OAAO,EACP,aAAa,EACb,aAAa,EACb,YAAY,EACZ,WAAW,EACX,aAAa,EACb,cAAc,EACd,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACtB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -19,7 +19,10 @@
19
19
  */
20
20
  export { useBreakpoint } from './useBreakpoint';
21
21
  export { useResponsive } from './useResponsive';
22
+ export { useResponsiveConfig } from './useResponsiveConfig';
22
23
  export { useGesture } from './useGesture';
24
+ export { useSpecGesture } from './useSpecGesture';
25
+ export { useTouchTarget } from './useTouchTarget';
23
26
  export { usePullToRefresh } from './usePullToRefresh';
24
27
  export { MobileProvider } from './MobileProvider';
25
28
  export { ResponsiveContainer } from './ResponsiveContainer';
@@ -0,0 +1,60 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ import type { BreakpointName } from '@object-ui/types';
9
+ /**
10
+ * Spec-aligned ResponsiveConfig (mirrors @objectstack/spec ResponsiveConfigSchema).
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * const config: SpecResponsiveConfig = {
15
+ * columns: { xs: 12, sm: 6, lg: 4 },
16
+ * hiddenOn: ['xs'],
17
+ * order: { xs: 2, lg: 1 },
18
+ * };
19
+ * ```
20
+ */
21
+ export interface SpecResponsiveConfig {
22
+ /** The target breakpoint for this config */
23
+ breakpoint?: BreakpointName;
24
+ /** Breakpoints on which the component is hidden */
25
+ hiddenOn?: BreakpointName[];
26
+ /** Grid column counts per breakpoint (1-12) */
27
+ columns?: Partial<Record<BreakpointName, number>>;
28
+ /** Display order per breakpoint */
29
+ order?: Partial<Record<BreakpointName, number>>;
30
+ }
31
+ /**
32
+ * Resolved responsive state from a SpecResponsiveConfig.
33
+ */
34
+ export interface ResolvedResponsiveState {
35
+ /** Whether the component is hidden at the current breakpoint */
36
+ hidden: boolean;
37
+ /** Resolved column count for the current breakpoint */
38
+ columns: number | undefined;
39
+ /** Resolved display order for the current breakpoint */
40
+ order: number | undefined;
41
+ /** Current active breakpoint name */
42
+ breakpoint: BreakpointName;
43
+ }
44
+ /**
45
+ * Hook that consumes @objectstack/spec ResponsiveConfigSchema and
46
+ * resolves breakpoint-aware layout state.
47
+ *
48
+ * @example
49
+ * ```tsx
50
+ * const { hidden, columns, order } = useResponsiveConfig({
51
+ * columns: { xs: 12, sm: 6, lg: 4 },
52
+ * hiddenOn: ['xs'],
53
+ * order: { xs: 2, lg: 1 },
54
+ * });
55
+ * if (hidden) return null;
56
+ * return <div style={{ gridColumn: `span ${columns}`, order }}>...</div>;
57
+ * ```
58
+ */
59
+ export declare function useResponsiveConfig(config?: SpecResponsiveConfig): ResolvedResponsiveState;
60
+ //# sourceMappingURL=useResponsiveConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useResponsiveConfig.d.ts","sourceRoot":"","sources":["../src/useResponsiveConfig.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,oBAAoB;IACnC,4CAA4C;IAC5C,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,mDAAmD;IACnD,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAC;IAC5B,+CAA+C;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;IAClD,mCAAmC;IACnC,KAAK,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;CACjD;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,gEAAgE;IAChE,MAAM,EAAE,OAAO,CAAC;IAChB,uDAAuD;IACvD,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,wDAAwD;IACxD,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,qCAAqC;IACrC,UAAU,EAAE,cAAc,CAAC;CAC5B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,CAAC,EAAE,oBAAoB,GAAG,uBAAuB,CAoB1F"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ import { useMemo } from 'react';
9
+ import { useBreakpoint } from './useBreakpoint';
10
+ import { resolveResponsiveValue } from './breakpoints';
11
+ /**
12
+ * Hook that consumes @objectstack/spec ResponsiveConfigSchema and
13
+ * resolves breakpoint-aware layout state.
14
+ *
15
+ * @example
16
+ * ```tsx
17
+ * const { hidden, columns, order } = useResponsiveConfig({
18
+ * columns: { xs: 12, sm: 6, lg: 4 },
19
+ * hiddenOn: ['xs'],
20
+ * order: { xs: 2, lg: 1 },
21
+ * });
22
+ * if (hidden) return null;
23
+ * return <div style={{ gridColumn: `span ${columns}`, order }}>...</div>;
24
+ * ```
25
+ */
26
+ export function useResponsiveConfig(config) {
27
+ const { breakpoint } = useBreakpoint();
28
+ return useMemo(() => {
29
+ if (!config) {
30
+ return { hidden: false, columns: undefined, order: undefined, breakpoint };
31
+ }
32
+ const hidden = config.hiddenOn?.includes(breakpoint) ?? false;
33
+ const columns = config.columns
34
+ ? resolveResponsiveValue(config.columns, breakpoint)
35
+ : undefined;
36
+ const order = config.order
37
+ ? resolveResponsiveValue(config.order, breakpoint)
38
+ : undefined;
39
+ return { hidden, columns, order, breakpoint };
40
+ }, [config, breakpoint]);
41
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ import type { SpecGestureConfig } from '@object-ui/types';
9
+ export interface UseSpecGestureOptions {
10
+ /** Spec gesture configuration */
11
+ config: SpecGestureConfig;
12
+ /** Callback when a swipe gesture is detected */
13
+ onSwipe?: (direction: string) => void;
14
+ /** Callback when a pinch gesture is detected */
15
+ onPinch?: (scale: number) => void;
16
+ /** Callback when a long-press gesture is detected */
17
+ onLongPress?: () => void;
18
+ }
19
+ /**
20
+ * Spec-aware gesture hook that maps an @objectstack/spec GestureConfig
21
+ * to the existing useGesture hook.
22
+ *
23
+ * @example
24
+ * ```tsx
25
+ * const ref = useSpecGesture({
26
+ * config: { type: 'swipe', enabled: true, swipe: { direction: 'left', threshold: 80 } },
27
+ * onSwipe: (dir) => console.log('Swiped', dir),
28
+ * });
29
+ * return <div ref={ref}>Swipe me</div>;
30
+ * ```
31
+ */
32
+ export declare function useSpecGesture<T extends HTMLElement = HTMLElement>(options: UseSpecGestureOptions): import("react").RefObject<T | null>;
33
+ //# sourceMappingURL=useSpecGesture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSpecGesture.d.ts","sourceRoot":"","sources":["../src/useSpecGesture.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAe,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAEvE,MAAM,WAAW,qBAAqB;IACpC,iCAAiC;IACjC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,gDAAgD;IAChD,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,gDAAgD;IAChD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B;AASD;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EAChE,OAAO,EAAE,qBAAqB,uCAiC/B"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ import { useGesture } from './useGesture';
9
+ const SWIPE_DIRECTION_MAP = {
10
+ left: 'swipe-left',
11
+ right: 'swipe-right',
12
+ up: 'swipe-up',
13
+ down: 'swipe-down',
14
+ };
15
+ /**
16
+ * Spec-aware gesture hook that maps an @objectstack/spec GestureConfig
17
+ * to the existing useGesture hook.
18
+ *
19
+ * @example
20
+ * ```tsx
21
+ * const ref = useSpecGesture({
22
+ * config: { type: 'swipe', enabled: true, swipe: { direction: 'left', threshold: 80 } },
23
+ * onSwipe: (dir) => console.log('Swiped', dir),
24
+ * });
25
+ * return <div ref={ref}>Swipe me</div>;
26
+ * ```
27
+ */
28
+ export function useSpecGesture(options) {
29
+ const { config, onSwipe, onPinch, onLongPress } = options;
30
+ const enabled = config.enabled ?? true;
31
+ let gestureType = 'tap';
32
+ let threshold;
33
+ let longPressDuration;
34
+ let onGesture = () => { };
35
+ if (config.swipe && onSwipe) {
36
+ const dir = Array.isArray(config.swipe.direction)
37
+ ? config.swipe.direction[0]
38
+ : config.swipe.direction;
39
+ gestureType = (dir && SWIPE_DIRECTION_MAP[dir]) ?? 'swipe-left';
40
+ threshold = config.swipe.threshold;
41
+ onGesture = (ctx) => onSwipe(ctx.direction ?? dir ?? 'left');
42
+ }
43
+ else if (config.longPress && onLongPress) {
44
+ gestureType = 'long-press';
45
+ longPressDuration = config.longPress.duration;
46
+ onGesture = () => onLongPress();
47
+ }
48
+ else if (config.pinch && onPinch) {
49
+ gestureType = 'pinch';
50
+ onGesture = (ctx) => onPinch(ctx.scale ?? 1);
51
+ }
52
+ return useGesture({
53
+ type: gestureType,
54
+ onGesture,
55
+ threshold,
56
+ longPressDuration,
57
+ enabled,
58
+ });
59
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ import type { TouchTargetConfig } from '@object-ui/types';
9
+ export interface UseTouchTargetOptions {
10
+ /** Spec touch target configuration */
11
+ config?: TouchTargetConfig;
12
+ }
13
+ export interface TouchTargetResult {
14
+ /** CSS style properties enforcing minimum touch target sizes */
15
+ style: {
16
+ minWidth: string;
17
+ minHeight: string;
18
+ padding: string | undefined;
19
+ };
20
+ /** CSS class for touch-action optimization */
21
+ className: string;
22
+ }
23
+ /**
24
+ * Hook that returns style and className props enforcing minimum
25
+ * touch target sizes per the @objectstack/spec TouchTargetConfig.
26
+ *
27
+ * Defaults follow WCAG 2.5.5 (44×44 CSS pixels).
28
+ *
29
+ * @example
30
+ * ```tsx
31
+ * const target = useTouchTarget({ config: { minWidth: 48, minHeight: 48 } });
32
+ * return <button style={target.style} className={target.className}>Tap</button>;
33
+ * ```
34
+ */
35
+ export declare function useTouchTarget(options?: UseTouchTargetOptions): TouchTargetResult;
36
+ //# sourceMappingURL=useTouchTarget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTouchTarget.d.ts","sourceRoot":"","sources":["../src/useTouchTarget.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,MAAM,WAAW,qBAAqB;IACpC,sCAAsC;IACtC,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,gEAAgE;IAChE,KAAK,EAAE;QACL,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;KAC7B,CAAC;IACF,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,iBAAiB,CAcrF"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ /**
9
+ * Hook that returns style and className props enforcing minimum
10
+ * touch target sizes per the @objectstack/spec TouchTargetConfig.
11
+ *
12
+ * Defaults follow WCAG 2.5.5 (44×44 CSS pixels).
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * const target = useTouchTarget({ config: { minWidth: 48, minHeight: 48 } });
17
+ * return <button style={target.style} className={target.className}>Tap</button>;
18
+ * ```
19
+ */
20
+ export function useTouchTarget(options = {}) {
21
+ const { config } = options;
22
+ const minWidth = config?.minWidth ?? 44;
23
+ const minHeight = config?.minHeight ?? 44;
24
+ const padding = config?.padding ?? 0;
25
+ return {
26
+ style: {
27
+ minWidth: `${minWidth}px`,
28
+ minHeight: `${minHeight}px`,
29
+ padding: padding > 0 ? `${padding}px` : undefined,
30
+ },
31
+ className: 'touch-manipulation',
32
+ };
33
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@object-ui/mobile",
3
- "version": "2.0.0",
3
+ "version": "3.0.1",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Mobile optimization for Object UI with responsive components, PWA support, and touch gesture handling.",
@@ -26,11 +26,11 @@
26
26
  "react": "^18.0.0 || ^19.0.0"
27
27
  },
28
28
  "dependencies": {
29
- "@object-ui/types": "2.0.0"
29
+ "@object-ui/types": "3.0.1"
30
30
  },
31
31
  "devDependencies": {
32
- "@types/react": "^19.2.13",
33
- "react": "^19.1.0",
32
+ "@types/react": "19.2.13",
33
+ "react": "19.2.4",
34
34
  "typescript": "^5.9.3",
35
35
  "vitest": "^4.0.18"
36
36
  },